📄 guipopupctrl.cc
字号:
// 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] )
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] )
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 //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -