822 lines
24 KiB
C++
Executable File
822 lines
24 KiB
C++
Executable File
//-----------------------------------------------------------------------------
|
|
// Torque Game Engine
|
|
// Copyright (C) GarageGames.com, Inc.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "dgl/dgl.h"
|
|
#include "gui/core/guiCanvas.h"
|
|
#include "gui/controls/guiPopUpCtrl.h"
|
|
#include "console/consoleTypes.h"
|
|
#include "gui/core/guiDefaultControlRender.h"
|
|
|
|
IMPLEMENT_CONOBJECT(GuiPopUpMenuCtrl);
|
|
|
|
GuiPopUpBackgroundCtrl::GuiPopUpBackgroundCtrl(GuiPopUpMenuCtrl *ctrl, GuiPopUpTextListCtrl *textList)
|
|
{
|
|
mPopUpCtrl = ctrl;
|
|
mTextList = textList;
|
|
}
|
|
|
|
void GuiPopUpBackgroundCtrl::onMouseDown(const GuiEvent &event)
|
|
{
|
|
mTextList->setSelectedCell(Point2I(-1,-1));
|
|
mPopUpCtrl->closePopUp();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
GuiPopUpTextListCtrl::GuiPopUpTextListCtrl()
|
|
{
|
|
mPopUpCtrl = NULL;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
GuiPopUpTextListCtrl::GuiPopUpTextListCtrl(GuiPopUpMenuCtrl *ctrl)
|
|
{
|
|
mPopUpCtrl = ctrl;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpTextListCtrl::onCellSelected( Point2I /*cell*/ )
|
|
{
|
|
// Do nothing, the parent control will take care of everything...
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool GuiPopUpTextListCtrl::onKeyDown(const GuiEvent &event)
|
|
{
|
|
//if the control is a dead end, don't process the input:
|
|
if ( !mVisible || !mActive || !mAwake )
|
|
return false;
|
|
|
|
//see if the key down is a <return> or not
|
|
if ( event.modifier == 0 )
|
|
{
|
|
if ( event.keyCode == KEY_RETURN )
|
|
{
|
|
mPopUpCtrl->closePopUp();
|
|
return true;
|
|
}
|
|
else if ( event.keyCode == KEY_ESCAPE )
|
|
{
|
|
mSelectedCell.set( -1, -1 );
|
|
mPopUpCtrl->closePopUp();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//otherwise, pass the event to it's parent
|
|
return Parent::onKeyDown(event);
|
|
}
|
|
|
|
void GuiPopUpTextListCtrl::onMouseDown(const GuiEvent &event)
|
|
{
|
|
Parent::onMouseDown(event);
|
|
mPopUpCtrl->closePopUp();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
|
|
{
|
|
ColorI fontColor;
|
|
mPopUpCtrl->getFontColor( fontColor, mList[cell.y].id, selected, mouseOver );
|
|
|
|
dglSetBitmapModulation( fontColor );
|
|
dglDrawText( mFont, Point2I( offset.x + 4, offset.y ), mList[cell.y].text );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
GuiPopUpMenuCtrl::GuiPopUpMenuCtrl(void)
|
|
{
|
|
VECTOR_SET_ASSOCIATION(mEntries);
|
|
VECTOR_SET_ASSOCIATION(mSchemes);
|
|
|
|
mSelIndex = -1;
|
|
mActive = true;
|
|
mMaxPopupHeight = 200;
|
|
mScrollDir = GuiScrollCtrl::None;
|
|
mScrollCount = 0;
|
|
mLastYvalue = 0;
|
|
mIncValue = 0;
|
|
mRevNum = 0;
|
|
mInAction = false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
GuiPopUpMenuCtrl::~GuiPopUpMenuCtrl()
|
|
{
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::initPersistFields(void)
|
|
{
|
|
Parent::initPersistFields();
|
|
|
|
addField("maxPopupHeight", TypeS32, Offset(mMaxPopupHeight, GuiPopUpMenuCtrl));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
ConsoleMethod( GuiPopUpMenuCtrl, add, void, 4, 5, "(string name, int idNum, int scheme=0)")
|
|
{
|
|
if ( argc > 4 )
|
|
object->addEntry(argv[2],dAtoi(argv[3]),dAtoi(argv[4]));
|
|
else
|
|
object->addEntry(argv[2],dAtoi(argv[3]),0);
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, addScheme, void, 6, 6, "(int id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL)")
|
|
{
|
|
ColorI fontColor, fontColorHL, fontColorSEL;
|
|
U32 r, g, b;
|
|
char buf[64];
|
|
|
|
dStrcpy( buf, argv[3] );
|
|
char* temp = dStrtok( buf, " \0" );
|
|
r = temp ? dAtoi( temp ) : 0;
|
|
temp = dStrtok( NULL, " \0" );
|
|
g = temp ? dAtoi( temp ) : 0;
|
|
temp = dStrtok( NULL, " \0" );
|
|
b = temp ? dAtoi( temp ) : 0;
|
|
fontColor.set( r, g, b );
|
|
|
|
dStrcpy( buf, argv[4] );
|
|
temp = dStrtok( buf, " \0" );
|
|
r = temp ? dAtoi( temp ) : 0;
|
|
temp = dStrtok( NULL, " \0" );
|
|
g = temp ? dAtoi( temp ) : 0;
|
|
temp = dStrtok( NULL, " \0" );
|
|
b = temp ? dAtoi( temp ) : 0;
|
|
fontColorHL.set( r, g, b );
|
|
|
|
dStrcpy( buf, argv[5] );
|
|
temp = dStrtok( buf, " \0" );
|
|
r = temp ? dAtoi( temp ) : 0;
|
|
temp = dStrtok( NULL, " \0" );
|
|
g = temp ? dAtoi( temp ) : 0;
|
|
temp = dStrtok( NULL, " \0" );
|
|
b = temp ? dAtoi( temp ) : 0;
|
|
fontColorSEL.set( r, g, b );
|
|
|
|
object->addScheme( dAtoi( argv[2] ), fontColor, fontColorHL, fontColorSEL );
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, setText, void, 3, 3, "(string text)")
|
|
{
|
|
object->setText(argv[2]);
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, getText, const char*, 2, 2, "")
|
|
{
|
|
return object->getText();
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, clear, void, 2, 2, "Clear the popup list.")
|
|
{
|
|
object->clear();
|
|
}
|
|
|
|
ConsoleMethod(GuiPopUpMenuCtrl, sort, void, 2, 2, "Sort the list alphabetically.")
|
|
{
|
|
object->sort();
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, forceOnAction, void, 2, 2, "")
|
|
{
|
|
object->onAction();
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, forceClose, void, 2, 2, "")
|
|
{
|
|
object->closePopUp();
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, getSelected, S32, 2, 2, "")
|
|
{
|
|
return object->getSelected();
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, setSelected, void, 3, 3, "(int id)")
|
|
{
|
|
object->setSelected(dAtoi(argv[2]));
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, getTextById, const char*, 3, 3, "(int id)")
|
|
{
|
|
return(object->getTextById(dAtoi(argv[2])));
|
|
}
|
|
|
|
ConsoleMethod( GuiPopUpMenuCtrl, setEnumContent, void, 4, 4, "(string class, string enum)"
|
|
"This fills the popup with a classrep's field enumeration type info.\n\n"
|
|
"More of a helper function than anything. If console access to the field list is added, "
|
|
"at least for the enumerated types, then this should go away..")
|
|
{
|
|
AbstractClassRep * classRep = AbstractClassRep::getClassList();
|
|
|
|
// walk the class list to get our class
|
|
while(classRep)
|
|
{
|
|
if(!dStricmp(classRep->getClassName(), argv[2]))
|
|
break;
|
|
classRep = classRep->getNextClass();
|
|
}
|
|
|
|
// get it?
|
|
if(!classRep)
|
|
{
|
|
Con::warnf(ConsoleLogEntry::General, "failed to locate class rep for '%s'", argv[2]);
|
|
return;
|
|
}
|
|
|
|
// walk the fields to check for this one (findField checks StringTableEntry ptrs...)
|
|
U32 i;
|
|
for(i = 0; i < classRep->mFieldList.size(); i++)
|
|
if(!dStricmp(classRep->mFieldList[i].pFieldname, argv[3]))
|
|
break;
|
|
|
|
// found it?
|
|
if(i == classRep->mFieldList.size())
|
|
{
|
|
Con::warnf(ConsoleLogEntry::General, "failed to locate field '%s' for class '%s'", argv[3], argv[2]);
|
|
return;
|
|
}
|
|
|
|
const AbstractClassRep::Field & field = classRep->mFieldList[i];
|
|
|
|
// check the type
|
|
if(field.type != TypeEnum)
|
|
{
|
|
Con::warnf(ConsoleLogEntry::General, "field '%s' is not an enumeration for class '%s'", argv[3], argv[2]);
|
|
return;
|
|
}
|
|
|
|
AssertFatal(field.table, avar("enumeration '%s' for class '%s' with NULL ", argv[3], argv[2]));
|
|
|
|
// fill it
|
|
for(i = 0; i < field.table->size; i++)
|
|
object->addEntry(field.table->table[i].label, field.table->table[i].index);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
ConsoleMethod( GuiPopUpMenuCtrl, findText, S32, 3, 3, "(string text)"
|
|
"Returns the position of the first entry containing the specified text.")
|
|
{
|
|
return( object->findText( argv[2] ) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
ConsoleMethod( GuiPopUpMenuCtrl, size, S32, 2, 2, "Get the size of the menu - the number of entries in it.")
|
|
{
|
|
return( object->getNumEntries() );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
ConsoleMethod( GuiPopUpMenuCtrl, replaceText, void, 3, 3, "(bool doReplaceText)")
|
|
{
|
|
object->replaceText(dAtoi(argv[2]));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool GuiPopUpMenuCtrl::onAdd()
|
|
{
|
|
if (!Parent::onAdd())
|
|
return false;
|
|
mSelIndex = -1;
|
|
mReplaceText = true;
|
|
return true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::onSleep()
|
|
{
|
|
Parent::onSleep();
|
|
closePopUp(); // Tests in function.
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::clear()
|
|
{
|
|
mEntries.setSize(0);
|
|
setText("");
|
|
mSelIndex = -1;
|
|
mRevNum = 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
static S32 QSORT_CALLBACK textCompare(const void *a,const void *b)
|
|
{
|
|
GuiPopUpMenuCtrl::Entry *ea = (GuiPopUpMenuCtrl::Entry *) (a);
|
|
GuiPopUpMenuCtrl::Entry *eb = (GuiPopUpMenuCtrl::Entry *) (b);
|
|
return (dStricmp(ea->buf, eb->buf));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::sort()
|
|
{
|
|
dQsort((void *)&(mEntries[0]), mEntries.size(), sizeof(Entry), textCompare);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::addEntry(const char *buf, S32 id, U32 scheme)
|
|
{
|
|
Entry e;
|
|
dStrcpy(e.buf, buf);
|
|
e.id = id;
|
|
e.scheme = scheme;
|
|
|
|
// see if there is a shortcut key
|
|
char * cp = dStrchr(e.buf, '~');
|
|
e.ascii = cp ? cp[1] : 0;
|
|
|
|
mEntries.push_back(e);
|
|
|
|
if ( mInAction && mTl )
|
|
{
|
|
// Add the new entry:
|
|
mTl->addEntry( e.id, e.buf );
|
|
repositionPopup();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::addScheme( U32 id, ColorI fontColor, ColorI fontColorHL, ColorI fontColorSEL )
|
|
{
|
|
if ( !id )
|
|
return;
|
|
|
|
Scheme newScheme;
|
|
newScheme.id = id;
|
|
newScheme.fontColor = fontColor;
|
|
newScheme.fontColorHL = fontColorHL;
|
|
newScheme.fontColorSEL = fontColorSEL;
|
|
|
|
mSchemes.push_back( newScheme );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
S32 GuiPopUpMenuCtrl::getSelected()
|
|
{
|
|
if (mSelIndex == -1)
|
|
return 0;
|
|
return mEntries[mSelIndex].id;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
const char* GuiPopUpMenuCtrl::getTextById(S32 id)
|
|
{
|
|
for ( U32 i = 0; i < mEntries.size(); i++ )
|
|
{
|
|
if ( mEntries[i].id == id )
|
|
return( mEntries[i].buf );
|
|
}
|
|
|
|
return( "" );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
S32 GuiPopUpMenuCtrl::findText( const char* text )
|
|
{
|
|
for ( U32 i = 0; i < mEntries.size(); i++ )
|
|
{
|
|
if ( dStrcmp( text, mEntries[i].buf ) == 0 )
|
|
return( mEntries[i].id );
|
|
}
|
|
return( -1 );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::setSelected(S32 id)
|
|
{
|
|
S32 i;
|
|
for (i = 0; U32(i) < mEntries.size(); i++)
|
|
if (id == mEntries[i].id)
|
|
{
|
|
//i = (mRevNum > i) ? mRevNum - i : i;
|
|
mSelIndex = i;
|
|
setText(mEntries[i].buf);
|
|
|
|
// Now perform the popup action:
|
|
char idval[24];
|
|
dSprintf( idval, sizeof(idval), "%d", mEntries[mSelIndex].id );
|
|
Con::executef( this, 3, "onSelect", idval, mEntries[mSelIndex].buf );
|
|
return;
|
|
}
|
|
|
|
setText("");
|
|
mSelIndex = -1;
|
|
|
|
Con::executef( this, 1, "onCancel" );
|
|
|
|
// Execute the popup console command:
|
|
if ( mConsoleCommand[0] )
|
|
{
|
|
char buf[16];
|
|
dSprintf(buf, sizeof(buf), "%d", getId());
|
|
Con::setVariable("$ThisControl", buf);
|
|
Con::evaluate( mConsoleCommand, false );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
const char *GuiPopUpMenuCtrl::getScriptValue()
|
|
{
|
|
return getText();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|
{
|
|
updateRect;
|
|
Point2I localStart;
|
|
|
|
if(mScrollDir != GuiScrollCtrl::None)
|
|
autoScroll();
|
|
|
|
RectI r(offset, mBounds.extent);
|
|
RectI buttonRect( ( r.point.x + r.extent.x ) - 18, r.point.y + 2, 16, r.extent.y - 4);
|
|
if( mProfile->mBorder && mProfile->mOpaque)
|
|
{
|
|
if(mInAction)
|
|
{
|
|
renderFilledBorder(r, mProfile->mBorderColorHL, mProfile->mFillColor);
|
|
renderFilledBorder( buttonRect, mProfile->mBorderColorHL, mProfile->mFillColorNA);
|
|
}
|
|
else
|
|
{
|
|
renderFilledBorder(r, mProfile->mBorderColorHL, mProfile->mFillColor);
|
|
renderFilledBorder( buttonRect, mProfile->mBorderColorHL, mProfile->mFillColorNA);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
S32 txt_w = mFont->getStrWidth((const UTF8 *)mText);
|
|
localStart.x = 0;
|
|
localStart.y = (mBounds.extent.y - (mFont->getHeight())) / 2;
|
|
|
|
// align the horizontal
|
|
switch (mProfile->mAlignment)
|
|
{
|
|
case GuiControlProfile::RightJustify:
|
|
localStart.x = mBounds.extent.x - txt_w;
|
|
break;
|
|
case GuiControlProfile::CenterJustify:
|
|
localStart.x = (mBounds.extent.x - txt_w) / 2;
|
|
break;
|
|
default: // GuiControlProfile::LeftJustify
|
|
localStart.x = 4;
|
|
break;
|
|
}
|
|
Point2I globalStart = localToGlobalCoord(localStart);
|
|
dglSetBitmapModulation(mProfile->mFontColor);
|
|
dglDrawText(mFont, globalStart, mText, mProfile->mFontColors);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::closePopUp()
|
|
{
|
|
if ( !mInAction )
|
|
return;
|
|
|
|
// Get the selection from the text list:
|
|
mSelIndex = mTl->getSelectedCell().y;
|
|
mSelIndex = (mRevNum >= mSelIndex && mSelIndex != -1) ? mRevNum - mSelIndex : mSelIndex;
|
|
if ( mSelIndex != -1 )
|
|
{
|
|
if(mReplaceText)
|
|
setText( mEntries[mSelIndex].buf );
|
|
setIntVariable( mEntries[mSelIndex].id );
|
|
}
|
|
|
|
// Release the mouse:
|
|
mInAction = false;
|
|
mTl->mouseUnlock();
|
|
|
|
// Pop the background:
|
|
getRoot()->popDialogControl(mBackground);
|
|
|
|
// Kill the popup:
|
|
mBackground->removeObject( mSc );
|
|
mTl->deleteObject();
|
|
mSc->deleteObject();
|
|
mBackground->deleteObject();
|
|
|
|
// Set this as the first responder:
|
|
setFirstResponder();
|
|
|
|
// Now perform the popup action:
|
|
if ( mSelIndex != -1 )
|
|
{
|
|
char idval[24];
|
|
dSprintf( idval, sizeof(idval), "%d", mEntries[mSelIndex].id );
|
|
Con::executef( this, 3, "onSelect", idval, mEntries[mSelIndex].buf );
|
|
}
|
|
else
|
|
Con::executef( this, 1, "onCancel" );
|
|
|
|
// Execute the popup console command:
|
|
if ( mConsoleCommand[0] )
|
|
{
|
|
char buf[16];
|
|
dSprintf(buf, sizeof(buf), "%d", getId());
|
|
Con::setVariable("$ThisControl", buf);
|
|
Con::evaluate( mConsoleCommand, false );
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool GuiPopUpMenuCtrl::onKeyDown(const GuiEvent &event)
|
|
{
|
|
//if the control is a dead end, don't process the input:
|
|
if ( !mVisible || !mActive || !mAwake )
|
|
return false;
|
|
|
|
//see if the key down is a <return> or not
|
|
if ( event.keyCode == KEY_RETURN && event.modifier == 0 )
|
|
{
|
|
onAction();
|
|
return true;
|
|
}
|
|
|
|
S32 selected = mSelIndex;
|
|
switch( event.keyCode )
|
|
{
|
|
case KEY_RIGHT:
|
|
case KEY_DOWN:
|
|
if( ( selected + 1 ) < mEntries.size() )
|
|
setSelected( mEntries[selected + 1].id );
|
|
break;
|
|
case KEY_UP:
|
|
case KEY_LEFT:
|
|
if( ( selected - 1 ) > 0 )
|
|
setSelected( mEntries[selected - 1].id );
|
|
|
|
break;
|
|
}
|
|
|
|
//otherwise, pass the event to its parent
|
|
return Parent::onKeyDown( event );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::onAction()
|
|
{
|
|
GuiControl *canCtrl = getParent();
|
|
|
|
addChildren();
|
|
|
|
GuiCanvas *root = getRoot();
|
|
Point2I windowExt = root->mBounds.extent;
|
|
|
|
mBackground->mBounds.point.set(0,0);
|
|
mBackground->mBounds.extent = root->mBounds.extent;
|
|
|
|
S32 textWidth = 0, width = mBounds.extent.x;
|
|
const S32 menuSpace = 5;
|
|
const S32 textSpace = 2;
|
|
bool setScroll = false;
|
|
|
|
for(U32 i=0; i<mEntries.size(); ++i)
|
|
if(S32(mFont->getStrWidth((const UTF8 *)mEntries[i].buf)) > textWidth)
|
|
textWidth = mFont->getStrWidth((const UTF8 *)mEntries[i].buf);
|
|
|
|
if(textWidth > mBounds.extent.x)
|
|
{
|
|
textWidth +=10;
|
|
width = textWidth;
|
|
}
|
|
|
|
mTl->setCellSize(Point2I(width, mFont->getHeight()+3));
|
|
|
|
for(U32 j=0; j<mEntries.size(); ++j)
|
|
mTl->addEntry(mEntries[j].id, mEntries[j].buf);
|
|
|
|
Point2I pointInGC = canCtrl->localToGlobalCoord(mBounds.point);
|
|
Point2I scrollPoint(pointInGC.x, pointInGC.y + mBounds.extent.y);
|
|
|
|
//Calc max Y distance, so Scroll Ctrl will fit on window
|
|
S32 maxYdis = windowExt.y - pointInGC.y - mBounds.extent.y - menuSpace;
|
|
|
|
//If scroll bars need to be added
|
|
if(maxYdis < mTl->mBounds.extent.y + textSpace)
|
|
{
|
|
//Should we pop menu list above the button
|
|
if(maxYdis < pointInGC.y - menuSpace)
|
|
{
|
|
reverseTextList();
|
|
maxYdis = pointInGC.y - menuSpace;
|
|
//Does the menu need a scroll bar
|
|
if(maxYdis < mTl->mBounds.extent.y + textSpace)
|
|
{
|
|
//Calc for the width of the scroll bar
|
|
if(textWidth >= width)
|
|
width += 20;
|
|
mTl->setCellSize(Point2I(width,mFont->getHeight() + textSpace));
|
|
//Pop menu list above the button
|
|
scrollPoint.set(pointInGC.x, menuSpace - 1);
|
|
setScroll = true;
|
|
}
|
|
//No scroll bar needed
|
|
else
|
|
{
|
|
maxYdis = mTl->mBounds.extent.y + textSpace;
|
|
scrollPoint.set(pointInGC.x, pointInGC.y - maxYdis -1);
|
|
}
|
|
}
|
|
//Scroll bar needed but Don't pop above button
|
|
else
|
|
{
|
|
mRevNum = 0;
|
|
//Calc for the width of the scroll bar
|
|
if(textWidth >= width)
|
|
width += 20;
|
|
mTl->setCellSize(Point2I(width,mFont->getHeight() + textSpace));
|
|
setScroll = true;
|
|
}
|
|
}
|
|
//No scroll bar needed
|
|
else
|
|
maxYdis = mTl->mBounds.extent.y + textSpace;
|
|
|
|
//offset it from the background so it lines up properly
|
|
mSc->mBounds.point = mBackground->globalToLocalCoord(scrollPoint);
|
|
|
|
if(mSc->mBounds.point.x + width > mBackground->mBounds.extent.x)
|
|
if(width - mBounds.extent.x > 0)
|
|
mSc->mBounds.point.x -= width - mBounds.extent.x;
|
|
|
|
mSc->mBounds.extent.set(width-1, maxYdis);
|
|
|
|
mSc->registerObject();
|
|
mTl->registerObject();
|
|
mBackground->registerObject();
|
|
|
|
mSc->addObject( mTl );
|
|
mBackground->addObject( mSc );
|
|
|
|
// JDD - push the popup dialog to the topmost layer, so it's never under anything
|
|
root->pushDialogControl(mBackground,99);
|
|
|
|
if ( setScroll )
|
|
{
|
|
if ( mSelIndex )
|
|
mTl->scrollCellVisible( Point2I(0, mSelIndex));
|
|
else
|
|
mTl->scrollCellVisible( Point2I( 0, 0 ) );
|
|
}
|
|
|
|
mTl->setFirstResponder();
|
|
|
|
mInAction = true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::addChildren()
|
|
{
|
|
mTl = new GuiPopUpTextListCtrl(this);
|
|
AssertFatal(mTl, "Failed to create the GuiPopUpTextListCtrl for the PopUpMenu");
|
|
mTl->mProfile = mProfile;
|
|
mTl->setField("noDuplicates", "false");
|
|
|
|
mSc = new GuiScrollCtrl;
|
|
AssertFatal(mSc, "Failed to create the GuiScrollCtrl for the PopUpMenu");
|
|
mSc->mProfile = mProfile;
|
|
mSc->setField("hScrollBar","AlwaysOff");
|
|
mSc->setField("vScrollBar","dynamic");
|
|
|
|
mBackground = new GuiPopUpBackgroundCtrl(this, mTl);
|
|
AssertFatal(mBackground, "Failed to create the GuiBackgroundCtrl for the PopUpMenu");
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::repositionPopup()
|
|
{
|
|
if ( !mInAction || !mSc || !mTl )
|
|
return;
|
|
|
|
// I'm not concerned with this right now...
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::reverseTextList()
|
|
{
|
|
mTl->clear();
|
|
for(S32 i=mEntries.size()-1; i >= 0; --i)
|
|
mTl->addEntry(mEntries[i].id, mEntries[i].buf);
|
|
|
|
// Don't lose the selected cell:
|
|
if ( mSelIndex >= 0 )
|
|
mTl->setSelectedCell( Point2I( 0, mEntries.size() - mSelIndex - 1 ) );
|
|
|
|
mRevNum = mEntries.size() - 1;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool GuiPopUpMenuCtrl::getFontColor( ColorI &fontColor, S32 id, bool selected, bool mouseOver )
|
|
{
|
|
U32 i;
|
|
Entry* entry = NULL;
|
|
for ( i = 0; i < mEntries.size(); i++ )
|
|
{
|
|
if ( mEntries[i].id == id )
|
|
{
|
|
entry = &mEntries[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !entry )
|
|
return( false );
|
|
|
|
if ( entry->scheme != 0 )
|
|
{
|
|
// Find the entry's color scheme:
|
|
for ( i = 0; i < mSchemes.size(); i++ )
|
|
{
|
|
if ( mSchemes[i].id == entry->scheme )
|
|
{
|
|
fontColor = selected ? mSchemes[i].fontColorSEL : mouseOver ? mSchemes[i].fontColorHL : mSchemes[i].fontColor;
|
|
return( true );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Default color scheme...
|
|
fontColor = selected ? mProfile->mFontColorSEL : mouseOver ? mProfile->mFontColorHL : mProfile->mFontColor;
|
|
|
|
return( true );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::onMouseDown(const GuiEvent &event)
|
|
{
|
|
event;
|
|
onAction();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::onMouseUp(const GuiEvent &event)
|
|
{
|
|
event;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::setupAutoScroll(const GuiEvent &event)
|
|
{
|
|
GuiControl *parent = getParent();
|
|
if (! parent) return;
|
|
|
|
Point2I mousePt = mSc->globalToLocalCoord(event.mousePoint);
|
|
|
|
mEventSave = event;
|
|
|
|
if(mLastYvalue != mousePt.y)
|
|
{
|
|
mScrollDir = GuiScrollCtrl::None;
|
|
if(mousePt.y > mSc->mBounds.extent.y || mousePt.y < 0)
|
|
{
|
|
S32 topOrBottom = (mousePt.y > mSc->mBounds.extent.y) ? 1 : 0;
|
|
mSc->scrollTo(0, topOrBottom);
|
|
return;
|
|
}
|
|
|
|
F32 percent = (F32)mousePt.y / (F32)mSc->mBounds.extent.y;
|
|
if(percent > 0.7f && mousePt.y > mLastYvalue)
|
|
{
|
|
mIncValue = percent - 0.5f;
|
|
mScrollDir = GuiScrollCtrl::DownArrow;
|
|
}
|
|
else if(percent < 0.3f && mousePt.y < mLastYvalue)
|
|
{
|
|
mIncValue = 0.5f - percent;
|
|
mScrollDir = GuiScrollCtrl::UpArrow;
|
|
}
|
|
mLastYvalue = mousePt.y;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::autoScroll()
|
|
{
|
|
mScrollCount += mIncValue;
|
|
|
|
while(mScrollCount > 1)
|
|
{
|
|
mSc->autoScroll(mScrollDir);
|
|
mScrollCount -= 1;
|
|
}
|
|
mTl->onMouseMove(mEventSave);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void GuiPopUpMenuCtrl::replaceText(S32 boolVal)
|
|
{
|
|
mReplaceText = boolVal;
|
|
}
|
|
// EOF //
|