Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#include "ListWidget.h"
#include "Font.h"
#include "WidgetManager.h"
#include "ScrollbarWidget.h"
#include "ListListener.h"
#include "SexyAppBase.h"

using namespace Sexy;

static int gInitialListWidgetColors[][3] = {{255, 255, 255}, {255, 255, 255}, {0, 0, 0}, {0, 192, 0}, {0, 0, 128}, {255, 255, 255}};

ListWidget::ListWidget(int theId, Font *theFont, ListListener *theListListener)
{
        mJustify = JUSTIFY_LEFT;
        mHiliteIdx = -1;
        mSelectIdx = -1;

        if (theFont != NULL)
                mItemHeight = theFont->GetHeight();
        else
                mItemHeight = -1;

        SetColors(gInitialListWidgetColors, 6);
               
        mId = theId;
        mFont = theFont;
        mListListener = theListListener;
        mParent = NULL;
        mChild = NULL;
        mScrollbar = NULL;
        mPosition = 0;
        mPageSize = 0;
        mSortFromChild = false;
        mDrawOutline = true;
        mMaxNumericPlaces = 0; 
        mDrawSelectWhenHilited = false;
        mDoFingerWhenHilited = true;
}
       
ListWidget::~ListWidget()
{
}

void ListWidget::RemovedFromManager(WidgetManager *theManager)
{
        Widget::RemovedFromManager(theManager);
        if (mListListener)
                mListListener->ListClosed(mId);
}

SexyString ListWidget::GetSortKey(int theIdx)
{
        SexyString aString = mLines[theIdx];
       
        while (aString.length() < (ulong) mMaxNumericPlaces)
                aString = _S("0") + aString;

        if (mSortFromChild)
                return mChild->GetSortKey(theIdx) + aString;
        else
        {
                if (mChild == NULL)    
                        return aString;
                else
                        return aString + mChild->GetSortKey(theIdx);
        }

        return _S("");
}
       
void ListWidget::Sort(bool ascending)
{
        int aCount = mLines.size();
        int* aMap = new int[aCount];
        SexyString* aKeys = new SexyString[aCount];

        int i;
        for (i = 0; i < aCount; i++)
        {
                aMap[i] = i;
                aKeys[i] = GetSortKey(i);              
        }
               
        for (i = 1; i < aCount; i++)
                for (int j = 0; j < aCount - i; j++)
                {
                        int aComp = aKeys[j].compare(aKeys[j+1]);
                        if ((ascending && (aComp > 0)) || (!ascending && (aComp < 0)))
                        {
                                int aSwapInt = aMap[j];
                                aMap[j] = aMap[j+1];
                                aMap[j+1] = aSwapInt;
                                               
                                SexyString aSwapKey = aKeys[j];
                                aKeys[j] = aKeys[j+1];
                                aKeys[j+1] = aSwapKey;
                        }
                }
               
        ListWidget *aListWidget = this;
        while (aListWidget->mParent != NULL)   
                aListWidget = aListWidget->mParent;

        while (aListWidget != NULL)
        {
                SexyStringVector aNewLines;
                ColorVector aNewLineColors;
                       
                for (int i = 0; i < aCount; i++)
                {
                        aNewLines.push_back(aListWidget->mLines[aMap[i]]);
                        aNewLineColors.push_back(aListWidget->mLineColors[aMap[i]]);
                }
               
                aListWidget->mLines = aNewLines;
                aListWidget->mLineColors = aNewLineColors;
               
                aListWidget->MarkDirty();
                                               
                aListWidget = aListWidget->mChild;
        }

        delete aMap;
        delete aKeys;
}
       
SexyString ListWidget::GetStringAt(int theIdx)
{
        return
                mLines[theIdx];
}
       
void ListWidget::Resize(int theX, int theY, int theWidth, int theHeight)
{
        Widget::Resize(theX, theY, theWidth, theHeight);
       
        double aPageSize = 1;                  
        int anItemHeight = (mItemHeight != -1) ? mItemHeight : mFont->GetHeight();
       
        if (mHeight > anItemHeight+8)
                aPageSize = (mHeight - 8.0) / anItemHeight;
               
        mPageSize = aPageSize;
               
        if (mScrollbar != NULL)
                mScrollbar->SetPageSize(aPageSize);
}
       
int ListWidget::AddLine(const SexyString& theLine, bool alphabetical)
{      
        int anIdx = -1;
        bool inserted = false;

        if (alphabetical)
        {      
                for (int i = 0; i < (int) mLines.size(); i++)          
                        if (sexystrcmp(theLine.c_str(), mLines[i].c_str()) < 0)
                        {
                                anIdx = i;
                                               
                                ListWidget *aListWidget = this;

                                while (aListWidget->mParent != NULL)
                                        aListWidget = aListWidget->mParent;

                                while (aListWidget != NULL)
                                {
                                        if (aListWidget == this)
                                                aListWidget->mLines.insert(aListWidget->mLines.begin() + i, theLine);
                                        else
                                                aListWidget->mLines.insert(aListWidget->mLines.begin() + i, _S("-"));
                                       
                                        aListWidget->mLineColors.insert(aListWidget->mLineColors.begin() + i, mColors[COLOR_TEXT]);
                                        aListWidget->MarkDirty();
                                       
                                        aListWidget = aListWidget->mChild;
                                }
                                               
                                inserted = true;
                                break;
                        }
        }
               
        if (!inserted)
        {
                anIdx = mLines.size();
                       
                ListWidget *aListWidget = this;
               
                while (aListWidget->mParent!=NULL)
                        aListWidget = aListWidget->mParent;

                while (aListWidget!=NULL)
                {
                        if (aListWidget==this)
                                aListWidget->mLines.push_back(theLine);
                        else
                                aListWidget->mLines.push_back(_S("-"));
                                               
                        aListWidget->mLineColors.push_back(mColors[COLOR_TEXT]);
                        aListWidget->MarkDirty();
                               
                        aListWidget = aListWidget->mChild;
                }
        }
               
        if (mScrollbar!=NULL)
                mScrollbar->SetMaxValue(mLines.size());        
               
        return anIdx;
}

       
void ListWidget::SetLine(int theIdx, const SexyString& theString)
{
        mLines[theIdx] = theString;    
        MarkDirty();
}
       
int ListWidget::GetLineCount()
{
        return mLines.size();  
}
       
int ListWidget::GetLineIdx(const SexyString& theLine)
{      
        for (ulong i = 0; i < mLines.size(); i++)      
                if (sexystrcmp(mLines[i].c_str(), theLine.c_str()) == 0)
                        return i;
       
        return -1;
}
       
void ListWidget::SetColor(const SexyString& theLine, const Color& theColor)
{
        int anIdx = GetLineIdx(theLine);
        SetLineColor(anIdx, theColor); 
}

void ListWidget::SetColor(int theIdx, const Color& theColor)
{
        Widget::SetColor(theIdx, theColor);
}
               
void ListWidget::SetLineColor(int theIdx, const Color& theColor)
{
        if ((theIdx >= 0) && (theIdx < (int)mLines.size()))
        {
                ListWidget *aListWidget = this;

                while (aListWidget->mParent != NULL)
                        aListWidget = aListWidget->mParent;

                while (aListWidget != NULL)
                {
                        aListWidget->mLineColors[theIdx] = theColor;
                        aListWidget->MarkDirty();
                               
                        aListWidget = aListWidget->mChild;
                }                      
        }
}

void ListWidget::RemoveLine(int theIdx)
{
        if (theIdx != -1)
        {
                ListWidget *aListWidget = this;

                while (aListWidget->mParent != NULL)
                        aListWidget = aListWidget->mParent;

                while (aListWidget != NULL)
                {
                        aListWidget->mLines.erase(aListWidget->mLines.begin() + theIdx);
                        aListWidget->mLineColors.erase(aListWidget->mLineColors.begin() + theIdx);
                               
                        aListWidget->MarkDirty();
                        aListWidget = aListWidget->mChild;     
                }
        }
               
        if (mScrollbar != NULL)
                mScrollbar->SetMaxValue(mLines.size());
}
       
void ListWidget::RemoveAll()
{
        ListWidget *aListWidget = this;

        while (aListWidget->mParent != NULL)
                aListWidget = aListWidget->mParent;                    

        while (aListWidget != NULL)
        {
                aListWidget->mLines.clear();
                aListWidget->mLineColors.clear();
                aListWidget->mSelectIdx = -1;
                aListWidget->mHiliteIdx = -1;
                               
                aListWidget->MarkDirty();
                aListWidget = aListWidget->mChild;     
        }

        if (mScrollbar != NULL)
                mScrollbar->SetMaxValue(mLines.size());
}
       
int ListWidget::GetOptimalWidth()
{
        int aMaxWidth = 0;
       
        for (ulong i = 0; i < mLines.size(); i++)
                aMaxWidth = max(aMaxWidth, mFont->StringWidth(mLines[i]));

        return aMaxWidth + 16;
}
       
int ListWidget::GetOptimalHeight()
{
        int anItemHeight = (mItemHeight != -1) ? mItemHeight : mFont->GetHeight();

        return anItemHeight * mLines.size() + 8;
}
       
void ListWidget::OrderInManagerChanged()
{
        Widget::OrderInManagerChanged();

        if (mChild != NULL)
                gSexyAppBase->mWidgetManager->PutInfront(mChild, this);
        if (mScrollbar != NULL)
                gSexyAppBase->mWidgetManager->PutInfront(mScrollbar, this);
}

void ListWidget::Draw(Graphics *g)
{
        g->SetColor(mColors[COLOR_BKG]);
        g->FillRect(0, 0, mWidth, mHeight);
               
        Graphics aClipG(*g);
        aClipG.ClipRect(4, 4, mWidth - 8, mHeight - 8);
               
        Graphics aSelectClipG(*g);
        aSelectClipG.ClipRect(0, 4, mWidth, mHeight - 8);
                               
        aClipG.SetFont(mFont);
               
        int aFirstLine = (int) mPosition;
        int aLastLine = min((int) mLines.size()-1, (int) mPosition + (int) mPageSize + 1);
               
        int anItemHeight, anItemOffset;
        if (mItemHeight != -1)
        {
                anItemHeight = mItemHeight;
                anItemOffset = (anItemHeight-mFont->GetHeight())/2;
        }
        else
        {
                anItemHeight = mFont->GetHeight();
                anItemOffset = 0;
        }
       
        for (int i = aFirstLine; i <= aLastLine; i++)
        {
                int aDrawY = 4 + (int) ((i - mPosition)*anItemHeight);
                       
                if (i == mSelectIdx || (i==mHiliteIdx && mDrawSelectWhenHilited))
                {
                        aSelectClipG.SetColor(mColors[COLOR_SELECT]);
                        aSelectClipG.FillRect(0, aDrawY, mWidth, anItemHeight);
                }
                       
                if (i == mHiliteIdx)
                        aClipG.SetColor(mColors[COLOR_HILITE]);
                else if ((i == mSelectIdx) && (mColors.size() > COLOR_SELECT_TEXT))
                        aClipG.SetColor(mColors[COLOR_SELECT_TEXT]);
                else
                        aClipG.SetColor(mLineColors[i]);

                SexyString aString = mLines[i];
                int aFontX;
                switch (mJustify)
                {
                case JUSTIFY_LEFT:
                        aFontX = 4;
                        break;
                case JUSTIFY_CENTER:
                        aFontX = (mWidth - mFont->StringWidth(aString))/2;
                        break;
                default:
                        aFontX = mWidth - mFont->StringWidth(aString) - 4;
                        break;
                }
                       
                aClipG.DrawString(aString, aFontX, aDrawY + mFont->GetAscent() + anItemOffset);
        }
                                                       
        if (mDrawOutline)
        {
                g->SetColor(mColors[COLOR_OUTLINE]);           
                g->DrawRect(0, 0, mWidth-1, mHeight-1);
        }
}
       
void ListWidget::ScrollPosition(int theId, double thePosition)
{
        if (mChild != NULL)    
                mChild->ScrollPosition(theId, thePosition);
               
        mPosition = thePosition;                                               
        MarkDirty();
}

void ListWidget::SetHilite(int theHiliteIdx, bool notifyListener)
{
        int anOldIdx = mHiliteIdx;
        mHiliteIdx = theHiliteIdx;
        if (anOldIdx!=mHiliteIdx && notifyListener && mListListener!=NULL)
                mListListener->ListHiliteChanged(mId,anOldIdx,mHiliteIdx);
}

       
void ListWidget::MouseMove(int x, int y)
{
        int anItemHeight = (mItemHeight != -1) ? mItemHeight : mFont->GetHeight();
               
        int aNewHilite = (int) (((y - 4) / (double) anItemHeight) + mPosition);
        if ((aNewHilite < 0) || (aNewHilite >= (int) mLines.size()))
                aNewHilite = -1;
               
        if (aNewHilite != mHiliteIdx)
        {
                ListWidget* aListWidget = this;

                while (aListWidget->mParent != NULL)
                        aListWidget = aListWidget->mParent;

                while (aListWidget != NULL)
                {
                        aListWidget->SetHilite(aNewHilite,true);
                        aListWidget->MarkDirty();
                        aListWidget = aListWidget->mChild;     
                }
                                                                       
                if (mHiliteIdx == -1 || !mDoFingerWhenHilited)
                        mWidgetManager->mApp->SetCursor(CURSOR_POINTER);
                else
                        mWidgetManager->mApp->SetCursor(CURSOR_HAND);
        }
}
       
void ListWidget::MouseDown(int x, int y, int theBtnNum, int theClickCount)
{
        if ((mHiliteIdx != -1) && (mListListener != NULL))
                mListListener->ListClicked(mId, mHiliteIdx, theClickCount);
}
       
void ListWidget::MouseLeave()
{
        ListWidget *aListWidget = this;

        while (aListWidget->mParent != NULL)
                aListWidget = aListWidget->mParent;                    

        while (aListWidget != NULL)
        {
                aListWidget->SetHilite(-1,true);       
                aListWidget->MarkDirty();      
                aListWidget = aListWidget->mChild;
        }
               
        mWidgetManager->mApp->SetCursor(CURSOR_POINTER);
}
       
void ListWidget::SetSelect(int theSelectIdx)
{
        ListWidget *aListWidget = this;

        while (aListWidget->mParent != NULL)
                aListWidget = aListWidget->mParent;

        while (aListWidget != NULL)    
        {
                aListWidget->mSelectIdx = theSelectIdx;
                aListWidget->MarkDirty();      
                aListWidget = aListWidget->mChild;
        }
}


void ListWidget::MouseWheel(int theDelta)
{
        if (mScrollbar != NULL)
        {
                int aScrollAmount = 5;
                if (theDelta > 0)
                {
                        mScrollbar->SetValue(mScrollbar->mValue - aScrollAmount);
//                      mScrollbar->mUpdateMode = ScrollbarWidget::UPDATE_MODE_PGUP;
//                      mScrollbar->mUpdateAcc = 0;
                }
                else if (theDelta < 0)
                {
                        mScrollbar->SetValue(mScrollbar->mValue + aScrollAmount);
//                      mScrollbar->mUpdateMode = ScrollbarWidget::UPDATE_MODE_PGDN;
//                      mScrollbar->mUpdateAcc = 0;
                }
        }
}