diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 82c0475f0..5202e57bf 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -276,8 +276,6 @@ bool GuiCanvas::onAdd() // Define the menu bar for this canvas (if any) Con::executef(this, "onCreateMenu"); - Sim::findObject("PlatformGenericMenubar", mMenuBarCtrl); - return parentRet; } @@ -302,21 +300,39 @@ void GuiCanvas::setMenuBar(SimObject *obj) Parent::removeObject( oldMenuBar ); // set new menubar - if( mMenuBarCtrl ) - Parent::addObject(mMenuBarCtrl); + if (mMenuBarCtrl) + { + //Add a wrapper control so that the menubar sizes correctly + GuiControlProfile* profile; + Sim::findObject("GuiModelessDialogProfile", profile); + + if (!profile) + { + Con::errorf("GuiCanvas::setMenuBar: Unable to find the GuiModelessDialogProfile profile!"); + return; + } + + GuiControl* menuBackground = new GuiControl(); + menuBackground->registerObject(); + + menuBackground->setControlProfile(profile); + + menuBackground->addObject(mMenuBarCtrl); + + Parent::addObject(menuBackground); + } // update window accelerator keys if( oldMenuBar != mMenuBarCtrl ) { - StringTableEntry ste = StringTable->insert("menubar"); - GuiMenuBar* menu = NULL; - menu = !oldMenuBar ? NULL : dynamic_cast(oldMenuBar->findObjectByInternalName( ste, true)); - if( menu ) - menu->removeWindowAcceleratorMap( *getPlatformWindow()->getInputGenerator() ); + GuiMenuBar* oldMenu = dynamic_cast(oldMenuBar); + GuiMenuBar* newMenu = dynamic_cast(mMenuBarCtrl); - menu = !mMenuBarCtrl ? NULL : dynamic_cast(mMenuBarCtrl->findObjectByInternalName( ste, true)); - if( menu ) - menu->buildWindowAcceleratorMap( *getPlatformWindow()->getInputGenerator() ); + if(oldMenu) + oldMenu->removeWindowAcceleratorMap(*getPlatformWindow()->getInputGenerator()); + + if(newMenu) + newMenu->buildWindowAcceleratorMap(*getPlatformWindow()->getInputGenerator()); } } @@ -1633,27 +1649,26 @@ void GuiCanvas::maintainSizing() Point2I newPos = screenRect.point; // if menubar is active displace content gui control - if( mMenuBarCtrl && (ctrl == getContentControl()) ) - { - const SimObject *menu = mMenuBarCtrl->findObjectByInternalName( StringTable->insert("menubar"), true); + if (mMenuBarCtrl && (ctrl == getContentControl())) + { + /*const SimObject *menu = mMenuBarCtrl->findObjectByInternalName( StringTable->insert("menubar"), true); - if( !menu ) - continue; + if( !menu ) + continue; - AssertFatal( dynamic_cast(menu), ""); + AssertFatal( dynamic_cast(menu), "");*/ - const U32 yOffset = static_cast(menu)->getExtent().y; - newPos.y += yOffset; - newExt.y -= yOffset; + const U32 yOffset = static_cast(mMenuBarCtrl)->mMenubarHeight; + newPos.y += yOffset; + newExt.y -= yOffset; } - if(pos != newPos || ext != newExt) + if (pos != newPos || ext != newExt) { ctrl->resize(newPos, newExt); resetUpdateRegions(); } } - } void GuiCanvas::setupFences() diff --git a/Engine/source/gui/core/guiCanvas.h b/Engine/source/gui/core/guiCanvas.h index dfc98da38..b193bfbf1 100644 --- a/Engine/source/gui/core/guiCanvas.h +++ b/Engine/source/gui/core/guiCanvas.h @@ -210,6 +210,7 @@ public: virtual void onRemove(); void setMenuBar(SimObject *obj); + SimObject* getMenuBar() { return mMenuBarCtrl; } static void initPersistFields(); diff --git a/Engine/source/gui/editor/guiMenuBar.cpp b/Engine/source/gui/editor/guiMenuBar.cpp index 688531a87..0fe8c3c71 100644 --- a/Engine/source/gui/editor/guiMenuBar.cpp +++ b/Engine/source/gui/editor/guiMenuBar.cpp @@ -142,24 +142,11 @@ IMPLEMENT_CALLBACK( GuiMenuBar, onMenuItemSelect, void, ( S32 menuId, const char "@see GuiTickCtrl\n\n" ); -IMPLEMENT_CALLBACK( GuiMenuBar, onSubmenuSelect, void, ( S32 submenuId, const char* submenuText ),( submenuId, submenuText ), - "@brief Called whenever a submenu is selected.\n\n" - "@param submenuId Id of the selected submenu\n" - "@param submenuText Text of the selected submenu\n\n" - "@tsexample\n" - "GuiMenuBar::onSubmenuSelect(%this,%submenuId,%submenuText)\n" - "{\n" - " // Code to run when the callback occurs\n" - "}\n" - "@endtsexample\n\n" - "@see GuiTickCtrl\n\n" -); - //------------------------------------------------------------------------------ // console methods //------------------------------------------------------------------------------ -DefineEngineMethod( GuiMenuBar, clearMenus, void, (),, +/*DefineEngineMethod( GuiMenuBar, clearMenus, void, (),, "@brief Clears all the menus from the menu bar.\n\n" "@tsexample\n" "// Inform the GuiMenuBar control to clear all menus from itself.\n" @@ -818,14 +805,14 @@ GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu) { U32 id = dAtoi(menu); for (U32 i = 0; i < mMenuList.size(); ++i) - if (id == mMenuList[i]->id) + if (id == mMenuList[i].id) return mMenuList[i]; return NULL; } else { for (U32 i = 0; i < mMenuList.size(); ++i) - if (!dStricmp(menu, mMenuList[i]->text)) + if (!dStricmp(menu, mMenuList[i].text)) return mMenuList[i]; return NULL; } @@ -1093,19 +1080,18 @@ void GuiMenuBar::clearSubmenuItems(MenuItem *menuitem) while(menuitem->submenu->firstMenuItem) removeSubmenuItem(menuitem, menuitem->submenu->firstMenuItem); } - +*/ //------------------------------------------------------------------------------ // initialization, input and render methods //------------------------------------------------------------------------------ GuiMenuBar::GuiMenuBar() { - mMenuList.clear(); + //mMenuList.clear(); menuBarDirty = true; mouseDownMenu = NULL; mouseOverMenu = NULL; mCurAcceleratorIndex = 0; - mBackground = NULL; mPadding = 0; mCheckmarkBitmapIndex = 0; // Default to the first image in the bitmap array for the check mark @@ -1114,21 +1100,28 @@ GuiMenuBar::GuiMenuBar() mVerticalMargin = 1; // Default number of pixels on the top and bottom of a menu's text mBitmapMargin = 2; // Default number of pixels between a menu's bitmap and text + mMenubarHeight = 20; + // Added: mouseDownSubmenu = NULL; mouseOverSubmenu = NULL; - mSubmenuBackground = NULL; - mSubmenuTextList = NULL; - mMouseOverCounter = 0; - mCountMouseOver = false; - mMouseHoverAmount = 30; + + mMouseInMenu = false; + setProcessTicks(false); } +void GuiMenuBar::onRemove() +{ + Parent::onRemove(); +} + void GuiMenuBar::initPersistFields() { addField("padding", TypeS32, Offset( mPadding, GuiMenuBar ),"Extra padding to add to the bounds of the control.\n"); + addField("menubarHeight", TypeS32, Offset(mMenubarHeight, GuiMenuBar), "Sets the height of the menubar when attached to the canvas.\n"); + Parent::initPersistFields(); } @@ -1153,52 +1146,75 @@ bool GuiMenuBar::onWake() return true; } -GuiMenuBar::Menu *GuiMenuBar::findHitMenu(Point2I mousePoint) +void GuiMenuBar::addObject(SimObject* object) +{ + PopupMenu* popup = dynamic_cast(object); + + if (!popup) + { + //if it's not a popup, handle it normally + Parent::addObject(object); + } + else + { + //otherwise, if it IS a popup, don't add it as a child object, but instead just insert it as a menu entry + insert(object, -1); + } +} + +GuiMenuBar::MenuEntry *GuiMenuBar::findHitMenu(Point2I mousePoint) { Point2I pos = globalToLocalCoord(mousePoint); for (U32 i = 0; i < mMenuList.size(); ++i) - if (mMenuList[i]->visible && mMenuList[i]->bounds.pointInRect(pos)) - return mMenuList[i]; + { + if (mMenuList[i].visible && mMenuList[i].bounds.pointInRect(pos)) + return &mMenuList[i]; + } + return NULL; } void GuiMenuBar::onPreRender() { + setHeight(mMenubarHeight); + Parent::onPreRender(); - if(menuBarDirty) + if (menuBarDirty) { menuBarDirty = false; U32 curX = mPadding; for (U32 i = 0; i < mMenuList.size(); ++i) { - if (!mMenuList[i]->visible) + if (!mMenuList[i].visible) continue; - // Bounds depends on if there is a bitmap to be drawn or not - if (mMenuList[i]->bitmapIndex == -1) - { - // Text only - mMenuList[i]->bounds.set(curX, 0, mProfile->mFont->getStrWidth(mMenuList[i]->text) + (mHorizontalMargin * 2), getHeight() - (mVerticalMargin * 2)); - - } else - { - // Will the bitmap and text be draw? - if (!mMenuList[i]->drawBitmapOnly) + // Bounds depends on if there is a bitmap to be drawn or not + if (mMenuList[i].bitmapIndex == -1) { + // Text only + mMenuList[i].bounds.set(curX, 0, mProfile->mFont->getStrWidth(mMenuList[i].text) + (mHorizontalMargin * 2), getHeight() - (mVerticalMargin * 2)); + + } + else + { + // Will the bitmap and text be draw? + if (!mMenuList[i].drawBitmapOnly) + { // Draw the bitmap and the text RectI *bitmapBounds = mProfile->mBitmapArrayRects.address(); - mMenuList[i]->bounds.set(curX, 0, bitmapBounds[mMenuList[i]->bitmapIndex].extent.x + mProfile->mFont->getStrWidth(mMenuList[i]->text) + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2)); + mMenuList[i].bounds.set(curX, 0, bitmapBounds[mMenuList[i].bitmapIndex].extent.x + mProfile->mFont->getStrWidth(mMenuList[i].text) + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2)); - } else - { + } + else + { // Only the bitmap will be drawn RectI *bitmapBounds = mProfile->mBitmapArrayRects.address(); - mMenuList[i]->bounds.set(curX, 0, bitmapBounds[mMenuList[i]->bitmapIndex].extent.x + mBitmapMargin + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2)); + mMenuList[i].bounds.set(curX, 0, bitmapBounds[mMenuList[i].bitmapIndex].extent.x + mBitmapMargin + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2)); + } } - } - curX += mMenuList[i]->bounds.extent.x; + curX += mMenuList[i].bounds.extent.x; } mouseOverMenu = NULL; mouseDownMenu = NULL; @@ -1207,12 +1223,12 @@ void GuiMenuBar::onPreRender() void GuiMenuBar::checkMenuMouseMove(const GuiEvent &event) { - Menu *hit = findHitMenu(event.mousePoint); + MenuEntry *hit = findHitMenu(event.mousePoint); if(hit && hit != mouseDownMenu) { // gotta close out the current menu... - mTextList->setSelectedCell(Point2I(-1, -1)); - closeMenu(); + mouseDownMenu->popupMenu->hidePopup(); + mouseOverMenu = mouseDownMenu = hit; setUpdate(); onAction(); @@ -1221,87 +1237,63 @@ void GuiMenuBar::checkMenuMouseMove(const GuiEvent &event) void GuiMenuBar::onMouseMove(const GuiEvent &event) { - Menu *hit = findHitMenu(event.mousePoint); - if(hit != mouseOverMenu) - { - // If we need to, reset the mouse over menu counter and indicate - // that we should track it. - if(hit) - mMouseOverCounter = 0; - if(!mCountMouseOver) - { - // We've never started the counter, so start it. - if(hit) - mCountMouseOver = true; - } + MenuEntry *hit = findHitMenu(event.mousePoint); - mouseOverMenu = hit; + if (mouseDownMenu != nullptr && hit != nullptr) + { + //we have a standing click, so just update and go + mouseDownMenu = mouseOverMenu = hit; setUpdate(); + onAction(); + + return; } + + mouseOverMenu = hit; + setUpdate(); +} + +void GuiMenuBar::onMouseEnter(const GuiEvent &event) +{ + onMouseInMenu_callback(true); + mMouseInMenu = true; } void GuiMenuBar::onMouseLeave(const GuiEvent &event) { if(mouseOverMenu) setUpdate(); - mouseOverMenu = NULL; - // As we've left the control, don't track how long the mouse has been - // within it. - if(mCountMouseOver && mMouseOverCounter >= mMouseHoverAmount) - { - onMouseInMenu_callback(false); // Last parameter indicates if we've entered or left the menu - } - mCountMouseOver = false; - mMouseOverCounter = 0; + mouseOverMenu = NULL; + mMouseInMenu = false; } void GuiMenuBar::onMouseDragged(const GuiEvent &event) { - Menu *hit = findHitMenu(event.mousePoint); - - if(hit != mouseOverMenu) - { - // If we need to, reset the mouse over menu counter and indicate - // that we should track it. - if(hit) - mMouseOverCounter = 0; - if(!mCountMouseOver) - { - // We've never started the counter, so start it. - if(hit) - mCountMouseOver = true; - } - - mouseOverMenu = hit; - mouseDownMenu = hit; - setUpdate(); - onAction(); - } } void GuiMenuBar::onMouseDown(const GuiEvent &event) +{ +} + +void GuiMenuBar::onMouseUp(const GuiEvent &event) { mouseDownMenu = mouseOverMenu = findHitMenu(event.mousePoint); setUpdate(); onAction(); } -void GuiMenuBar::onMouseUp(const GuiEvent &event) -{ - mouseDownMenu = NULL; - setUpdate(); -} - void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect) { - RectI ctrlRect(offset, getExtent()); + Point2I extent = getExtent(); + + RectI ctrlRect(offset, extent); GFXDrawUtil* drawUtil = GFX->getDrawUtil(); //if opaque, fill the update rect with the fill color if (mProfile->mOpaque) - drawUtil->drawRectFill(RectI(offset, getExtent()), mProfile->mFillColor); + drawUtil->drawRectFill(RectI(offset, extent), mProfile->mFillColor); //if there's a border, draw the border if (mProfile->mBorder) @@ -1309,63 +1301,65 @@ void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect) for (U32 i = 0; i < mMenuList.size(); ++i) { - if (!mMenuList[i]->visible) + if (!mMenuList[i].visible) continue; + ColorI fontColor = mProfile->mFontColor; - RectI bounds = mMenuList[i]->bounds; + RectI bounds = mMenuList[i].bounds; bounds.point += offset; - + Point2I start; - start.x = mMenuList[i]->bounds.point.x + mHorizontalMargin; - start.y = mMenuList[i]->bounds.point.y + (mMenuList[i]->bounds.extent.y - mProfile->mFont->getHeight()) / 2; + start.x = mMenuList[i].bounds.point.x + mHorizontalMargin; + start.y = mMenuList[i].bounds.point.y + (mMenuList[i].bounds.extent.y - mProfile->mFont->getHeight()) / 2; - // Draw the border - if (mMenuList[i]->drawBorder) - { - RectI highlightBounds = bounds; - highlightBounds.inset(1,1); - if (mMenuList[i] == mouseDownMenu) - renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL ); - else if (mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL) - renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL); - } + // Draw the border + if (mMenuList[i].drawBorder) + { + RectI highlightBounds = bounds; + highlightBounds.inset(1, 1); + if (&mMenuList[i] == mouseDownMenu) + renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL); + else if (&mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL) + renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL); + } - // Do we draw a bitmap? - if (mMenuList[i]->bitmapIndex != -1) - { - S32 index = mMenuList[i]->bitmapIndex * 3; - if (mMenuList[i] == mouseDownMenu) + // Do we draw a bitmap? + if (mMenuList[i].bitmapIndex != -1) + { + S32 index = mMenuList[i].bitmapIndex * 3; + if (&mMenuList[i] == mouseDownMenu) ++index; - else if (mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL) + else if (&mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL) index += 2; RectI rect = mProfile->mBitmapArrayRects[index]; - Point2I bitmapstart(start); - bitmapstart.y = mMenuList[i]->bounds.point.y + (mMenuList[i]->bounds.extent.y - rect.extent.y) / 2; + Point2I bitmapstart(start); + bitmapstart.y = mMenuList[i].bounds.point.y + (mMenuList[i].bounds.extent.y - rect.extent.y) / 2; drawUtil->clearBitmapModulation(); - drawUtil->drawBitmapSR( mProfile->mTextureObject, offset + bitmapstart, rect); + drawUtil->drawBitmapSR(mProfile->mTextureObject, offset + bitmapstart, rect); - // Should we also draw the text? - if (!mMenuList[i]->drawBitmapOnly) - { + // Should we also draw the text? + if (!mMenuList[i].drawBitmapOnly) + { start.x += mBitmapMargin; - drawUtil->setBitmapModulation( fontColor ); - drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i]->text, mProfile->mFontColors); - } - } else - { - drawUtil->setBitmapModulation( fontColor ); - drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i]->text, mProfile->mFontColors); - } + drawUtil->setBitmapModulation(fontColor); + drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i].text, mProfile->mFontColors); + } + } + else + { + drawUtil->setBitmapModulation(fontColor); + drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i].text, mProfile->mFontColors); + } } - renderChildControls( offset, updateRect ); + renderChildControls(offset, updateRect); } -void GuiMenuBar::buildWindowAcceleratorMap( WindowInputGenerator &inputGenerator ) +void GuiMenuBar::buildWindowAcceleratorMap(WindowInputGenerator &inputGenerator) { // ok, accelerator map is cleared... // add all our keys: @@ -1373,20 +1367,21 @@ void GuiMenuBar::buildWindowAcceleratorMap( WindowInputGenerator &inputGenerator for (U32 i = 0; i < mMenuList.size(); ++i) { - for (MenuItem *item = mMenuList[i]->firstMenuItem; item; item = item->nextMenuItem) + for (U32 item = 0; item < mMenuList[i].popupMenu->mMenuItems.size(); item++) { - if(!item->accelerator) + if (!mMenuList[i].popupMenu->mMenuItems[item].accelerator) { - item->accelerator = 0; + mMenuList[i].popupMenu->mMenuItems[item].accelerator = 0; continue; } - EventDescriptor accelEvent; - ActionMap::createEventDescriptor(item->accelerator, &accelEvent); - - //now we have a modifier, and a key, add them to the canvas - inputGenerator.addAcceleratorKey( this, item->cmd, accelEvent.eventCode, accelEvent.flags); - item->acceleratorIndex = mCurAcceleratorIndex; + EventDescriptor accelEvent; + ActionMap::createEventDescriptor(mMenuList[i].popupMenu->mMenuItems[item].accelerator, &accelEvent); + + //now we have a modifier, and a key, add them to the canvas + inputGenerator.addAcceleratorKey(this, mMenuList[i].popupMenu->mMenuItems[item].cmd, accelEvent.eventCode, accelEvent.flags); + + mMenuList[i].popupMenu->mMenuItems[item].acceleratorIndex = mCurAcceleratorIndex; mCurAcceleratorIndex++; } } @@ -1403,591 +1398,112 @@ void GuiMenuBar::acceleratorKeyPress(U32 index) // and find the item that corresponds to the accelerator index for (U32 i = 0; i < mMenuList.size(); ++i) { - if (!mMenuList[i]->visible) + if (!mMenuList[i].visible) continue; - for (MenuItem *item = mMenuList[i]->firstMenuItem; item; item = item->nextMenuItem) + for(U32 item = 0; item < mMenuList[i].popupMenu->mMenuItems.size(); item++) { - if(item->acceleratorIndex == index) + if(mMenuList[i].popupMenu->mMenuItems[item].acceleratorIndex == index) { // first, call the script callback for menu selection: - onMenuSelect_callback(mMenuList[i]->id, mMenuList[i]->text); - - if(item->visible) - menuItemSelected(mMenuList[i], item); + onMenuSelect_callback(mMenuList[i].popupMenu->getId(), mMenuList[i].text); return; } } } } -//------------------------------------------------------------------------------ -// Menu display class methods -//------------------------------------------------------------------------------ - -GuiMenuBackgroundCtrl::GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl *textList) -{ - mMenuBarCtrl = ctrl; - mTextList = textList; -} - -void GuiMenuBackgroundCtrl::onMouseDown(const GuiEvent &event) -{ - mTextList->setSelectedCell(Point2I(-1,-1)); - mMenuBarCtrl->closeMenu(); -} - -void GuiMenuBackgroundCtrl::onMouseMove(const GuiEvent &event) -{ - GuiCanvas *root = getRoot(); - GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1); - if(ctrlHit == mMenuBarCtrl) // see if the current mouse over menu is right... - mMenuBarCtrl->checkMenuMouseMove(event); -} - -void GuiMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event) -{ - GuiCanvas *root = getRoot(); - GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1); - if(ctrlHit == mMenuBarCtrl) // see if the current mouse over menu is right... - mMenuBarCtrl->checkMenuMouseMove(event); -} - -GuiMenuTextListCtrl::GuiMenuTextListCtrl(GuiMenuBar *ctrl) -{ - mMenuBarCtrl = ctrl; - isSubMenu = false; // Added -} - -void GuiMenuTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver) -{ - if(dStrcmp(mList[cell.y].text + 3, "-\t")) // Was: dStrcmp(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag - Parent::onRenderCell(offset, cell, selected, mouseOver); - else - { - S32 yp = offset.y + mCellSize.y / 2; - GFX->getDrawUtil()->drawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128,128,128)); - GFX->getDrawUtil()->drawLine(offset.x, yp+1, offset.x + mCellSize.x, yp+1, ColorI(255,255,255)); - } - // now see if there's a bitmap... - U8 idx = mList[cell.y].text[0]; - if(idx != 1) - { - // there's a bitmap... - U32 index = U32(idx - 2) * 3; - if(!mList[cell.y].active) - index += 2; - else if(selected || mouseOver) - index ++; - - RectI rect = mProfile->mBitmapArrayRects[index]; - Point2I off = mMenuBarCtrl->maxBitmapSize - rect.extent; - off /= 2; - - GFX->getDrawUtil()->clearBitmapModulation(); - GFX->getDrawUtil()->drawBitmapSR(mProfile->mTextureObject, offset + off, rect); - } - - // Check if this is a submenu - idx = mList[cell.y].text[1]; - if(idx != 1) - { - // This is a submenu, so draw an arrow - S32 left = offset.x + mCellSize.x - 12; - S32 right = left + 8; - S32 top = mCellSize.y / 2 + offset.y - 4; - S32 bottom = top + 8; - S32 middle = top + 4; - - PrimBuild::begin( GFXTriangleList, 3 ); - if( selected || mouseOver ) - PrimBuild::color( mProfile->mFontColorHL ); - else - PrimBuild::color( mProfile->mFontColor ); - - PrimBuild::vertex2i( left, top ); - PrimBuild::vertex2i( right, middle ); - PrimBuild::vertex2i( left, bottom ); - PrimBuild::end(); - } -} - -bool GuiMenuTextListCtrl::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 or not - if ( event.modifier == 0 ) - { - if ( event.keyCode == KEY_RETURN ) - { - mMenuBarCtrl->closeMenu(); - return true; - } - else if ( event.keyCode == KEY_ESCAPE ) - { - mSelectedCell.set( -1, -1 ); - mMenuBarCtrl->closeMenu(); - return true; - } - } - - //otherwise, pass the event to it's parent - return Parent::onKeyDown(event); -} - -void GuiMenuTextListCtrl::onMouseDown(const GuiEvent &event) -{ - Parent::onMouseDown(event); -} - -void GuiMenuTextListCtrl::onMouseUp(const GuiEvent &event) -{ - Parent::onMouseUp(event); - mMenuBarCtrl->closeMenu(); -} - -void GuiMenuTextListCtrl::onCellHighlighted(Point2I cell) -{ - // If this text list control is part of a submenu, then don't worry about - // passing this along - if(!isSubMenu) - { - RectI globalbounds(getBounds()); - Point2I globalpoint = localToGlobalCoord(globalbounds.point); - globalbounds.point = globalpoint; - mMenuBarCtrl->highlightedMenuItem(cell.y, globalbounds, mCellSize); - } -} - -//------------------------------------------------------------------------------ -// Submenu display class methods -//------------------------------------------------------------------------------ - -GuiSubmenuBackgroundCtrl::GuiSubmenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl *textList) : GuiMenuBackgroundCtrl(ctrl, textList) -{ -} - -void GuiSubmenuBackgroundCtrl::onMouseDown(const GuiEvent &event) -{ - mTextList->setSelectedCell(Point2I(-1,-1)); - mMenuBarCtrl->closeMenu(); -} - -bool GuiSubmenuBackgroundCtrl::pointInControl(const Point2I& parentCoordPoint) -{ - S32 xt = parentCoordPoint.x - getLeft(); - S32 yt = parentCoordPoint.y - getTop(); - - if(findHitControl(Point2I(xt,yt)) == this) - return false; - else - return true; -// return xt >= 0 && yt >= 0 && xt < getWidth() && yt < getHeight(); -} - -//------------------------------------------------------------------------------ - -void GuiMenuBar::menuItemSelected(GuiMenuBar::Menu *menu, GuiMenuBar::MenuItem *item) -{ - if(item->enabled) - onMenuItemSelect_callback(menu->id, menu->text, item->id, item->text); -} - void GuiMenuBar::onSleep() { - if(mBackground) // a menu is up? - { - mTextList->setSelectedCell(Point2I(-1, -1)); - closeMenu(); - } Parent::onSleep(); } -void GuiMenuBar::closeMenu() -{ - // First close any open submenu - closeSubmenu(); - - // Get the selection from the text list: - S32 selectionIndex = mTextList->getSelectedCell().y; - - // Pop the background: - if( getRoot() ) - getRoot()->popDialogControl(mBackground); - else - return; - - // Kill the popup: - mBackground->deleteObject(); - mBackground = NULL; - - // Now perform the popup action: - if ( selectionIndex != -1 ) - { - MenuItem *list = mouseDownMenu->firstMenuItem; - - while(selectionIndex && list) - { - list = list->nextMenuItem; - selectionIndex--; - } - if(list) - menuItemSelected(mouseDownMenu, list); - } - mouseDownMenu = NULL; -} - -// Called when a menu item is highlighted by the mouse -void GuiMenuBar::highlightedMenuItem(S32 selectionIndex, const RectI& bounds, Point2I cellSize) -{ - S32 selstore = selectionIndex; - - // Now perform the popup action: - if ( selectionIndex != -1 ) - { - MenuItem *list = mouseDownMenu->firstMenuItem; - - while(selectionIndex && list) - { - list = list->nextMenuItem; - selectionIndex--; - } - - if(list) - { - // If the highlighted item has changed... - if(mouseOverSubmenu != list) - { - closeSubmenu(); - mouseOverSubmenu = NULL; - - // Check if this is a submenu. If so, open the submenu. - if(list->isSubmenu) - { - // If there are submenu items, then open the submenu - if(list->submenu->firstMenuItem) - { - mouseOverSubmenu = list; - onSubmenuAction(selstore, bounds, cellSize); - } - } - } - } - } -} - //------------------------------------------------------------------------------ void GuiMenuBar::onAction() { if(!mouseDownMenu) return; - // first, call the script callback for menu selection: - onMenuSelect_callback(mouseDownMenu->id, mouseDownMenu->text); - - MenuItem *visWalk = mouseDownMenu->firstMenuItem; - while(visWalk) - { - if(visWalk->visible) - break; - visWalk = visWalk->nextMenuItem; - } - if(!visWalk) - { - mouseDownMenu = NULL; - return; - } - - mTextList = new GuiMenuTextListCtrl(this); - mTextList->setControlProfile(mProfile); - - mBackground = new GuiMenuBackgroundCtrl(this, mTextList); - - GuiCanvas *root = getRoot(); - Point2I windowExt = root->getExtent(); - - mBackground->resize( Point2I(0,0), root->getExtent()); - S32 textWidth = 0, width = 0; - S32 acceleratorWidth = 0; - - GFont *font = mProfile->mFont; - - for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem) - { - if(!walk->visible) - continue; - - S32 iTextWidth = font->getStrWidth(walk->text); - S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0; - - if(iTextWidth > textWidth) - textWidth = iTextWidth; - if(iAcceleratorWidth > acceleratorWidth) - acceleratorWidth = iAcceleratorWidth; - } - width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4; - - mTextList->setCellSize(Point2I(width, font->getHeight()+2)); - mTextList->clearColumnOffsets(); - mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index. - mTextList->addColumnOffset(maxBitmapSize.x + 1); - mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4); - - U32 entryCount = 0; - - for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem) - { - if(!walk->visible) - continue; - - char buf[512]; - - // If this menu item is a submenu, then set the isSubmenu to 2 to indicate - // an arrow should be drawn. Otherwise set the isSubmenu normally. - char isSubmenu = 1; - if(walk->isSubmenu) - isSubmenu = 2; - - char bitmapIndex = 1; - if(walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= mProfile->mBitmapArrayRects.size())) - bitmapIndex = walk->bitmapIndex + 2; - dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : ""); - mTextList->addEntry(entryCount, buf); - - if(!walk->enabled) - mTextList->setEntryActive(entryCount, false); - - entryCount++; - } - Point2I menuPoint = localToGlobalCoord(mouseDownMenu->bounds.point); - menuPoint.y += mouseDownMenu->bounds.extent.y; // Used to have this at the end: + 2; - - GuiControl *ctrl = new GuiControl; - RectI ctrlBounds( menuPoint, mTextList->getExtent() + Point2I(6, 6)); - - ctrl->setControlProfile(mProfile); - mTextList->setPosition( mTextList->getPosition() + Point2I(3,3) ); - - // Make sure the menu doesn't go beyond the Canvas' bottom edge. - if((ctrlBounds.point.y + ctrlBounds.extent.y) > windowExt.y) - { - // Pop the menu above the menu bar - Point2I menuBar = localToGlobalCoord(mouseDownMenu->bounds.point); - ctrlBounds.point.y = menuBar.y - ctrl->getHeight(); - } - - ctrl->resize(ctrlBounds.point, ctrlBounds.extent); - //mTextList->setPosition(Point2I(3,3)); - - mTextList->registerObject(); - mBackground->registerObject(); - ctrl->registerObject(); - - mBackground->addObject( ctrl ); - ctrl->addObject( mTextList ); - - root->pushDialogControl(mBackground, mLayer + 1); - mTextList->setFirstResponder(); -} - -//------------------------------------------------------------------------------ -// Performs an action when a menu item that is a submenu is selected/highlighted -void GuiMenuBar::onSubmenuAction(S32 selectionIndex, const RectI& bounds, Point2I cellSize) -{ - if(!mouseOverSubmenu) - return; + mouseDownMenu->popupMenu->hidePopup(); // first, call the script callback for menu selection: - onSubmenuSelect_callback(mouseOverSubmenu->id, mouseOverSubmenu->text); + onMenuSelect_callback(mouseDownMenu->popupMenu->getId(), mouseDownMenu->text); - MenuItem *visWalk = mouseOverSubmenu->submenu->firstMenuItem; - while(visWalk) - { - if(visWalk->visible) - break; - visWalk = visWalk->nextMenuItem; - } - if(!visWalk) - { - mouseOverSubmenu = NULL; - return; - } - - mSubmenuTextList = new GuiMenuTextListCtrl(this); - mSubmenuTextList->setControlProfile(mProfile); - mSubmenuTextList->isSubMenu = true; // Indicate that this text list is part of a submenu - - mSubmenuBackground = new GuiSubmenuBackgroundCtrl(this, mSubmenuTextList); + mouseDownMenu->popupMenu->mMenuBarCtrl = this; GuiCanvas *root = getRoot(); - Point2I windowExt = root->getExtent(); - - mSubmenuBackground->resize( Point2I(0,0), root->getExtent()); - S32 textWidth = 0, width = 0; - S32 acceleratorWidth = 0; - - GFont *font = mProfile->mFont; - - for(MenuItem *walk = mouseOverSubmenu->submenu->firstMenuItem; walk; walk = walk->nextMenuItem) - { - if(!walk->visible) - continue; - - S32 iTextWidth = font->getStrWidth(walk->text); - S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0; - - if(iTextWidth > textWidth) - textWidth = iTextWidth; - if(iAcceleratorWidth > acceleratorWidth) - acceleratorWidth = iAcceleratorWidth; - } - width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4; - - mSubmenuTextList->setCellSize(Point2I(width, font->getHeight()+3)); - mSubmenuTextList->clearColumnOffsets(); - mSubmenuTextList->addColumnOffset(-1); // add an empty column in for the bitmap index. - mSubmenuTextList->addColumnOffset(maxBitmapSize.x + 1); - mSubmenuTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4); - - U32 entryCount = 0; - - for(MenuItem *walk = mouseOverSubmenu->submenu->firstMenuItem; walk; walk = walk->nextMenuItem) - { - if(!walk->visible) - continue; - - char buf[512]; - - // Can't have submenus within submenus. - char isSubmenu = 1; - - char bitmapIndex = 1; - if(walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= mProfile->mBitmapArrayRects.size())) - bitmapIndex = walk->bitmapIndex + 2; - dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : ""); - mSubmenuTextList->addEntry(entryCount, buf); - - if(!walk->enabled) - mSubmenuTextList->setEntryActive(entryCount, false); - - entryCount++; - } - Point2I menuPoint = bounds.point; //localToGlobalCoord(bounds.point); - menuPoint.x += bounds.extent.x; - menuPoint.y += cellSize.y * selectionIndex - 6; - - GuiControl *ctrl = new GuiControl; - RectI ctrlBounds(menuPoint, mSubmenuTextList->getExtent() + Point2I(6, 6)); - ctrl->setControlProfile(mProfile); - mSubmenuTextList->setPosition( getPosition() + Point2I(3,3)); - - // Make sure the menu doesn't go beyond the Canvas' bottom edge. - if((ctrlBounds.point.y + ctrlBounds.extent.y ) > windowExt.y) - { - // Pop the menu above the menu bar - ctrlBounds.point.y -= mSubmenuTextList->getHeight() - cellSize.y - 6 - 3; - } - - // And the same for the right edge - if((ctrlBounds.point.x + ctrlBounds.extent.x) > windowExt.x) - { - // Pop the submenu to the left of the menu - ctrlBounds.point.x -= mSubmenuTextList->getWidth() + cellSize.x + 6; - } - ctrl->resize(ctrlBounds.point, ctrlBounds.extent); - - //mSubmenuTextList->setPosition(Point2I(3,3)); - - mSubmenuTextList->registerObject(); - mSubmenuBackground->registerObject(); - ctrl->registerObject(); - - mSubmenuBackground->addObject( ctrl ); - ctrl->addObject( mSubmenuTextList ); - - root->pushDialogControl(mSubmenuBackground, mLayer + 1); - mSubmenuTextList->setFirstResponder(); -} - -// Close down the submenu controls -void GuiMenuBar::closeSubmenu() -{ - if(!mSubmenuBackground || !mSubmenuTextList) - return; - - // Get the selection from the text list: - S32 selectionIndex = mSubmenuTextList->getSelectedCell().y; - - // Pop the background: - if( getRoot() ) - getRoot()->popDialogControl(mSubmenuBackground); - - // Kill the popup: - mSubmenuBackground->deleteObject(); - mSubmenuBackground = NULL; - mSubmenuTextList = NULL; - - // Now perform the popup action: - if ( selectionIndex != -1 ) - { - MenuItem *list = NULL; - if(mouseOverSubmenu) - { - list = mouseOverSubmenu->submenu->firstMenuItem; - - while(selectionIndex && list) - { - list = list->nextMenuItem; - selectionIndex--; - } - } - if(list) - menuItemSelected(list->submenuParentMenu, list); - } - mouseOverSubmenu = NULL; -} - -// Find if the mouse pointer is within a menu item -GuiMenuBar::MenuItem *GuiMenuBar::findHitMenuItem(Point2I mousePoint) -{ - -// for(Menu *walk = menuList; walk; walk = walk->nextMenu) -// if(walk->visible && walk->bounds.pointInRect(pos)) -// return walk; - return NULL; -} - -// Checks if the mouse has been moved to a new menu item -void GuiMenuBar::checkSubmenuMouseMove(const GuiEvent &event) -{ - MenuItem *hit = findHitMenuItem(event.mousePoint); - if(hit && hit != mouseOverSubmenu) - { - // gotta close out the current menu... - mSubmenuTextList->setSelectedCell(Point2I(-1, -1)); -// closeSubmenu(); - setUpdate(); - } + Point2I pos = Point2I(mouseDownMenu->bounds.point.x, mouseDownMenu->bounds.point.y + mouseDownMenu->bounds.extent.y); + mouseDownMenu->popupMenu->showPopup(root, pos.x, pos.y); } // Process a tick void GuiMenuBar::processTick() { - // If we are to track a tick, then do so. - if(mCountMouseOver) - { - // If we're at a particular number of ticks, notify the script function - if(mMouseOverCounter < mMouseHoverAmount) - { - ++mMouseOverCounter; + if(mMouseInMenu) + onMouseInMenu_callback(true); +} - } else if(mMouseOverCounter == mMouseHoverAmount) - { - ++mMouseOverCounter; - onMouseInMenu_callback(true); // Last parameter indicates if we've entered or left the menu - } +void GuiMenuBar::insert(SimObject* pObject, S32 pos) +{ + PopupMenu* menu = dynamic_cast(pObject); + if (menu == nullptr) + return; + + MenuEntry newMenu; + newMenu.pos = pos >= mMenuList.size() || pos == -1 ? pos = mMenuList.size() : pos; + newMenu.drawBitmapOnly = false; + newMenu.drawBorder = true; + newMenu.bitmapIndex = -1; + newMenu.text = menu->barTitle; + newMenu.visible = true; + newMenu.popupMenu = menu; + + if (pos >= mMenuList.size() || pos == -1) + mMenuList.push_back(newMenu); + else + mMenuList.insert(pos, newMenu); +} + +PopupMenu* GuiMenuBar::getMenu(U32 index) +{ + if (index >= mMenuList.size()) + return nullptr; + + return mMenuList[index].popupMenu; +} + +//----------------------------------------------------------------------------- +// Console Methods +//----------------------------------------------------------------------------- +DefineConsoleMethod(GuiMenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)") +{ + GuiCanvas* canv = dynamic_cast(Sim::findObject(canvas)); + if (canv) + { + canv->setMenuBar(object); } } + +DefineConsoleMethod(GuiMenuBar, removeFromCanvas, void, (), , "()") +{ + GuiCanvas* canvas = object->getRoot(); + + if(canvas) + canvas->setMenuBar(nullptr); +} + +DefineConsoleMethod(GuiMenuBar, getMenuCount, S32, (), , "()") +{ + return object->getMenuListCount(); +} + +DefineConsoleMethod(GuiMenuBar, getMenu, S32, (S32 index), (0), "(Index)") +{ + return object->getMenu(index)->getId(); +} + +//----------------------------------------------------------------------------- +DefineConsoleMethod(GuiMenuBar, insert, void, (SimObject* pObject, S32 pos), (nullAsType(), -1), "(object, pos) insert object at position") +{ + object->insert(pObject, pos); +} \ No newline at end of file diff --git a/Engine/source/gui/editor/guiMenuBar.h b/Engine/source/gui/editor/guiMenuBar.h index a41455a16..d266378e3 100644 --- a/Engine/source/gui/editor/guiMenuBar.h +++ b/Engine/source/gui/editor/guiMenuBar.h @@ -23,119 +23,43 @@ #ifndef _GUIMENUBAR_H_ #define _GUIMENUBAR_H_ -#ifndef _GUITEXTLISTCTRL_H_ -#include "gui/controls/guiTextListCtrl.h" -#endif #ifndef _GUITICKCTRL_H_ #include "gui/shiny/guiTickCtrl.h" #endif +#ifndef _POPUPMENU_H_ +#include "gui/editor/popupMenu.h" +#endif + class GuiMenuBar; -class GuiMenuTextListCtrl; class WindowInputGenerator; -class GuiMenuBackgroundCtrl : public GuiControl -{ - typedef GuiControl Parent; - -protected: - GuiMenuBar *mMenuBarCtrl; - GuiMenuTextListCtrl *mTextList; -public: - GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList); - void onMouseDown(const GuiEvent &event); - void onMouseMove(const GuiEvent &event); - void onMouseDragged(const GuiEvent &event); -}; - -class GuiSubmenuBackgroundCtrl : public GuiMenuBackgroundCtrl -{ - typedef GuiMenuBackgroundCtrl Parent; - -public: - GuiSubmenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList); - bool pointInControl(const Point2I & parentCoordPoint); - void onMouseDown(const GuiEvent &event); -}; - //------------------------------------------------------------------------------ - -class GuiMenuTextListCtrl : public GuiTextListCtrl -{ - private: - typedef GuiTextListCtrl Parent; - - protected: - GuiMenuBar *mMenuBarCtrl; - - public: - bool isSubMenu; // Indicates that this text list is in a submenu - - GuiMenuTextListCtrl(); // for inheritance - GuiMenuTextListCtrl(GuiMenuBar *ctrl); - - // GuiControl overloads: - bool onKeyDown(const GuiEvent &event); - void onMouseDown(const GuiEvent &event); - void onMouseUp(const GuiEvent &event); - void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver); - - virtual void onCellHighlighted(Point2I cell); // Added -}; - -//------------------------------------------------------------------------------ - class GuiMenuBar : public GuiTickCtrl // Was: GuiControl { typedef GuiTickCtrl Parent; // Was: GuiControl Parent; public: - struct Menu; + struct MenuEntry + { + U32 pos; + RectI bounds; - struct MenuItem // an individual item in a pull-down menu - { - char *text; // the text of the menu item - U32 id; // a script-assigned identifier - char *accelerator; // the keyboard accelerator shortcut for the menu item - U32 acceleratorIndex; // index of this accelerator - bool enabled; // true if the menu item is selectable - bool visible; // true if the menu item is visible - S32 bitmapIndex; // index of the bitmap in the bitmap array - S32 checkGroup; // the group index of the item visa vi check marks - - // only one item in the group can be checked. - MenuItem *nextMenuItem; // next menu item in the linked list - - bool isSubmenu; // This menu item has a submenu that will be displayed - - Menu* submenuParentMenu; // For a submenu, this is the parent menu - Menu* submenu; - String cmd; - }; - - struct Menu - { - char *text; - U32 id; - RectI bounds; bool visible; - S32 bitmapIndex; // Index of the bitmap in the bitmap array (-1 = no bitmap) - bool drawBitmapOnly; // Draw only the bitmap and not the text - bool drawBorder; // Should a border be drawn around this menu (usually if we only have a bitmap, we don't want a border) + S32 bitmapIndex; + bool drawBitmapOnly; - Menu *nextMenu; - MenuItem *firstMenuItem; - }; - - GuiMenuBackgroundCtrl *mBackground; - GuiMenuTextListCtrl *mTextList; - - GuiSubmenuBackgroundCtrl *mSubmenuBackground; // Background for a submenu - GuiMenuTextListCtrl *mSubmenuTextList; // Text list for a submenu + bool drawBorder; - Vector mMenuList; - Menu *mouseDownMenu; - Menu *mouseOverMenu; + StringTableEntry text; + PopupMenu* popupMenu; + }; + + Vector mMenuList; + + MenuEntry *mouseDownMenu; + MenuEntry *mouseOverMenu; MenuItem* mouseDownSubmenu; // Stores the menu item that is a submenu that has been selected MenuItem* mouseOverSubmenu; // Stores the menu item that is a submenu that has been highlighted @@ -151,59 +75,26 @@ public: S32 mVerticalMargin; // Top and bottom margin around the text of each menu S32 mBitmapMargin; // Margin between a menu's bitmap and text - // Used to keep track of the amount of ticks that the mouse is hovering - // over a menu. - S32 mMouseOverCounter; - bool mCountMouseOver; - S32 mMouseHoverAmount; + U32 mMenubarHeight; + + bool mMouseInMenu; GuiMenuBar(); + + void onRemove(); bool onWake(); void onSleep(); - // internal menu handling functions - // these are used by the script manipulation functions to add/remove/change menu items - static Menu* sCreateMenu(const char *menuText, U32 menuId); - void addMenu(Menu *menu, S32 pos = -1); - void addMenu(const char *menuText, U32 menuId); - Menu *findMenu(const char *menu); // takes either a menu text or a string id - static MenuItem *findMenuItem(Menu *menu, const char *menuItem); // takes either a menu text or a string id - void removeMenu(Menu *menu); - static void removeMenuItem(Menu *menu, MenuItem *menuItem); - static MenuItem* addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup, const char *cmd); - static MenuItem* addMenuItem(Menu *menu, MenuItem *menuItem); - static void clearMenuItems(Menu *menu); - void clearMenus(); + virtual void addObject(SimObject* object); - void attachToMenuBar(Menu* menu, S32 pos = -1); - void removeFromMenuBar(Menu* menu); - - // Methods to deal with submenus - static MenuItem* findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem); - static MenuItem* findSubmenuItem(MenuItem *menuItem, const char *submenuItem); - static void addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup); - static void addSubmenuItem(Menu *menu, MenuItem *submenu, MenuItem *newMenuItem ); - static void removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem); - static void clearSubmenuItems(MenuItem *menuitem); - void onSubmenuAction(S32 selectionIndex, const RectI& bounds, Point2I cellSize); - void closeSubmenu(); - void checkSubmenuMouseMove(const GuiEvent &event); - MenuItem *findHitMenuItem(Point2I mousePoint); - - void highlightedMenuItem(S32 selectionIndex, const RectI& bounds, Point2I cellSize); // Called whenever a menu item is highlighted by the mouse - - // display/mouse functions - - Menu *findHitMenu(Point2I mousePoint); - - // Called when the GUI theme changes and a bitmap arrary may need updating - // void onThemeChange(); + MenuEntry *findHitMenu(Point2I mousePoint); void onPreRender(); void onRender(Point2I offset, const RectI &updateRect); void checkMenuMouseMove(const GuiEvent &event); void onMouseMove(const GuiEvent &event); + void onMouseEnter(const GuiEvent &event); void onMouseLeave(const GuiEvent &event); void onMouseDown(const GuiEvent &event); void onMouseDragged(const GuiEvent &event); @@ -215,18 +106,21 @@ public: void removeWindowAcceleratorMap( WindowInputGenerator &inputGenerator ); void acceleratorKeyPress(U32 index); - virtual void menuItemSelected(Menu *menu, MenuItem *item); - // Added to support 'ticks' void processTick(); + void insert(SimObject* pObject, S32 pos); + static void initPersistFields(); + U32 getMenuListCount() { return mMenuList.size(); } + + PopupMenu* getMenu(U32 index); + DECLARE_CONOBJECT(GuiMenuBar); DECLARE_CALLBACK( void, onMouseInMenu, ( bool hasLeftMenu )); DECLARE_CALLBACK( void, onMenuSelect, ( S32 menuId, const char* menuText )); DECLARE_CALLBACK( void, onMenuItemSelect, ( S32 menuId, const char* menuText, S32 menuItemId, const char* menuItemText )); - DECLARE_CALLBACK( void, onSubmenuSelect, ( S32 submenuId, const char* submenuText )); }; #endif diff --git a/Engine/source/gui/editor/guiPopupMenuCtrl.cpp b/Engine/source/gui/editor/guiPopupMenuCtrl.cpp index 36e693203..99c354102 100644 --- a/Engine/source/gui/editor/guiPopupMenuCtrl.cpp +++ b/Engine/source/gui/editor/guiPopupMenuCtrl.cpp @@ -25,20 +25,32 @@ #include "gfx/primBuilder.h" #include "gui/core/guiCanvas.h" -GuiPopupMenuBackgroundCtrl::GuiPopupMenuBackgroundCtrl(GuiPopupMenuTextListCtrl *textList) +GuiPopupMenuBackgroundCtrl::GuiPopupMenuBackgroundCtrl() { - mTextList = textList; - mTextList->mBackground = this; + mMenuBarCtrl = nullptr; } void GuiPopupMenuBackgroundCtrl::onMouseDown(const GuiEvent &event) { - mTextList->setSelectedCell(Point2I(-1, -1)); + +} + +void GuiPopupMenuBackgroundCtrl::onMouseUp(const GuiEvent &event) +{ + clearPopups(); + + //Pass along the event just in case we clicked over a menu item. We don't want to eat the input for it. + if (mMenuBarCtrl) + mMenuBarCtrl->onMouseUp(event); + close(); } void GuiPopupMenuBackgroundCtrl::onMouseMove(const GuiEvent &event) { + //It's possible we're trying to pan through a menubar while a popup is displayed. Pass along our event to the menubar for good measure + if (mMenuBarCtrl) + mMenuBarCtrl->onMouseMove(event); } void GuiPopupMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event) @@ -48,26 +60,64 @@ void GuiPopupMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event) void GuiPopupMenuBackgroundCtrl::close() { getRoot()->removeObject(this); + + mMenuBarCtrl = nullptr; +} + +S32 GuiPopupMenuBackgroundCtrl::findPopupMenu(PopupMenu* menu) +{ + S32 menuId = -1; + + for (U32 i = 0; i < mPopups.size(); i++) + { + if (mPopups[i]->getId() == menu->getId()) + return i; + } + + return menuId; +} + +void GuiPopupMenuBackgroundCtrl::clearPopups() +{ + for (U32 i = 0; i < mPopups.size(); i++) + { + mPopups[i]->mTextList->setSelectedCell(Point2I(-1, -1)); + mPopups[i]->mTextList->mPopup->hidePopup(); + } } GuiPopupMenuTextListCtrl::GuiPopupMenuTextListCtrl() { isSubMenu = false; // Added - mMenu = NULL; - mMenuBar = NULL; - mPopup = NULL; + + mMenuBar = nullptr; + mPopup = nullptr; + + mLastHighlightedMenuIdx = -1; } void GuiPopupMenuTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver) { - if (dStrcmp(mList[cell.y].text + 3, "-\t")) // Was: dStrcmp(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag - Parent::onRenderCell(offset, cell, selected, mouseOver); - else + //check if we're a real entry, or if it's a divider + if (mPopup->mMenuItems[cell.y].isSpacer) { S32 yp = offset.y + mCellSize.y / 2; - GFX->getDrawUtil()->drawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128, 128, 128)); - GFX->getDrawUtil()->drawLine(offset.x, yp + 1, offset.x + mCellSize.x, yp + 1, ColorI(255, 255, 255)); + GFX->getDrawUtil()->drawLine(offset.x + 5, yp, offset.x + mCellSize.x - 5, yp, ColorI(128, 128, 128)); } + else + { + if (dStrcmp(mList[cell.y].text + 3, "-\t")) // Was: dStrcmp(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag + { + Parent::onRenderCell(offset, cell, selected, mouseOver); + } + else + { + S32 yp = offset.y + mCellSize.y / 2; + GFX->getDrawUtil()->drawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128, 128, 128)); + GFX->getDrawUtil()->drawLine(offset.x, yp + 1, offset.x + mCellSize.x, yp + 1, ColorI(255, 255, 255)); + } + } + // now see if there's a bitmap... U8 idx = mList[cell.y].text[0]; if (idx != 1) @@ -153,17 +203,12 @@ void GuiPopupMenuTextListCtrl::onMouseUp(const GuiEvent &event) if (selectionIndex != -1) { - GuiMenuBar::MenuItem *list = mMenu->firstMenuItem; + MenuItem *item = &mPopup->mMenuItems[selectionIndex]; - while (selectionIndex && list) + if (item) { - list = list->nextMenuItem; - selectionIndex--; - } - if (list) - { - if (list->enabled) - dAtob(Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), list->text ? list->text : "")); + if (item->enabled) + dAtob(Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), item->text.isNotEmpty() ? item->text : "")); } } @@ -181,4 +226,23 @@ void GuiPopupMenuTextListCtrl::onCellHighlighted(Point2I cell) Point2I globalpoint = localToGlobalCoord(globalbounds.point); globalbounds.point = globalpoint; } + + S32 selectionIndex = cell.y; + + if (selectionIndex != -1 && mLastHighlightedMenuIdx != selectionIndex) + { + mLastHighlightedMenuIdx = selectionIndex; + + mPopup->hidePopupSubmenus(); + } + + if (selectionIndex != -1) + { + MenuItem *list = &mPopup->mMenuItems[selectionIndex]; + + if (list->isSubmenu && list->subMenu != nullptr) + { + list->subMenu->showPopup(getRoot(), getPosition().x + mCellSize.x, getPosition().y + (selectionIndex * mCellSize.y)); + } + } } \ No newline at end of file diff --git a/Engine/source/gui/editor/guiPopupMenuCtrl.h b/Engine/source/gui/editor/guiPopupMenuCtrl.h index c26fa855d..54632a009 100644 --- a/Engine/source/gui/editor/guiPopupMenuCtrl.h +++ b/Engine/source/gui/editor/guiPopupMenuCtrl.h @@ -42,6 +42,7 @@ class GuiPopupMenuBackgroundCtrl; class GuiPopupMenuTextListCtrl : public GuiTextListCtrl { friend class GuiPopupMenuBackgroundCtrl; + friend class PopupMenu; private: typedef GuiTextListCtrl Parent; @@ -51,10 +52,12 @@ private: public: bool isSubMenu; // Indicates that this text list is in a submenu Point2I maxBitmapSize; - GuiMenuBar::Menu* mMenu; + GuiMenuBar* mMenuBar; PopupMenu* mPopup; + S32 mLastHighlightedMenuIdx; + GuiPopupMenuTextListCtrl(); // GuiControl overloads: @@ -70,16 +73,21 @@ class GuiPopupMenuBackgroundCtrl : public GuiControl { typedef GuiControl Parent; -protected: - GuiPopupMenuTextListCtrl *mTextList; - public: - GuiPopupMenuBackgroundCtrl(GuiPopupMenuTextListCtrl* textList); + GuiPopupMenuBackgroundCtrl(); void onMouseDown(const GuiEvent &event); + void onMouseUp(const GuiEvent &event); void onMouseMove(const GuiEvent &event); void onMouseDragged(const GuiEvent &event); void close(); + + void clearPopups(); + + S32 findPopupMenu(PopupMenu* menu); + + Vector mPopups; + GuiMenuBar* mMenuBarCtrl; }; #endif \ No newline at end of file diff --git a/Engine/source/gui/editor/popupMenu.cpp b/Engine/source/gui/editor/popupMenu.cpp new file mode 100644 index 000000000..0e5db18da --- /dev/null +++ b/Engine/source/gui/editor/popupMenu.cpp @@ -0,0 +1,506 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- +#include "gui/editor/popupMenu.h" +#include "console/consoleTypes.h" +#include "console/engineAPI.h" +#include "gui/core/guiCanvas.h" +#include "core/util/safeDelete.h" +#include "gui/editor/guiPopupMenuCtrl.h" +#include "gui/editor/guiMenuBar.h" + +static U32 sMaxPopupGUID = 0; +PopupMenuEvent PopupMenu::smPopupMenuEvent; +bool PopupMenu::smSelectionEventHandled = false; + +/// Event class used to remove popup menus from the event notification in a safe way +class PopUpNotifyRemoveEvent : public SimEvent +{ +public: + void process(SimObject *object) + { + PopupMenu::smPopupMenuEvent.remove((PopupMenu *)object, &PopupMenu::handleSelectEvent); + } +}; + +//----------------------------------------------------------------------------- +// Constructor/Destructor +//----------------------------------------------------------------------------- +PopupMenu::PopupMenu() +{ + bitmapIndex = -1; + + barTitle = StringTable->EmptyString(); + + mMenuBarCtrl = nullptr; + mTextList = nullptr; + + isSubmenu = false; +} + +PopupMenu::~PopupMenu() +{ + PopupMenu::smPopupMenuEvent.remove(this, &PopupMenu::handleSelectEvent); +} + +IMPLEMENT_CONOBJECT(PopupMenu); + +ConsoleDocClass( PopupMenu, + "@brief PopupMenu represents a system menu.\n\n" + "You can add menu items to the menu, but there is no torque object associated " + "with these menu items, they exist only in a platform specific manner.\n\n" + "@note Internal use only\n\n" + "@internal" +); + +//----------------------------------------------------------------------------- +void PopupMenu::initPersistFields() +{ + Parent::initPersistFields(); + + addField("barTitle", TypeCaseString, Offset(barTitle, PopupMenu), ""); +} + +//----------------------------------------------------------------------------- +bool PopupMenu::onAdd() +{ + if(! Parent::onAdd()) + return false; + + Con::executef(this, "onAdd"); + return true; +} + +void PopupMenu::onRemove() +{ + Con::executef(this, "onRemove"); + + Parent::onRemove(); +} + +//----------------------------------------------------------------------------- +void PopupMenu::onMenuSelect() +{ + Con::executef(this, "onMenuSelect"); +} + +//----------------------------------------------------------------------------- +void PopupMenu::handleSelectEvent(U32 popID, U32 command) +{ +} + +//----------------------------------------------------------------------------- +bool PopupMenu::onMessageReceived(StringTableEntry queue, const char* event, const char* data) +{ + return Con::executef(this, "onMessageReceived", queue, event, data); +} + +bool PopupMenu::onMessageObjectReceived(StringTableEntry queue, Message *msg ) +{ + return Con::executef(this, "onMessageReceived", queue, Con::getIntArg(msg->getId())); +} + +////////////////////////////////////////////////////////////////////////// +// Platform Menu Data +////////////////////////////////////////////////////////////////////////// +GuiMenuBar* PopupMenu::getMenuBarCtrl() +{ + return mMenuBarCtrl; +} + +////////////////////////////////////////////////////////////////////////// +// Public Methods +////////////////////////////////////////////////////////////////////////// +S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator, const char* cmd) +{ + String titleString = title; + + MenuItem newItem; + newItem.id = pos; + newItem.text = titleString; + newItem.cmd = cmd; + + if (titleString.isEmpty() || titleString == String("-")) + newItem.isSpacer = true; + else + newItem.isSpacer = false; + + if (accelerator[0]) + newItem.accelerator = dStrdup(accelerator); + else + newItem.accelerator = NULL; + + newItem.visible = true; + newItem.isChecked = false; + newItem.acceleratorIndex = 0; + newItem.enabled = !newItem.isSpacer; + + newItem.isSubmenu = false; + newItem.subMenu = nullptr; + newItem.subMenuParentMenu = nullptr; + + mMenuItems.push_back(newItem); + + return pos; +} + +S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu) +{ + S32 itemPos = insertItem(pos, title, "", ""); + + mMenuItems[itemPos].isSubmenu = true; + mMenuItems[itemPos].subMenu = submenu; + mMenuItems[itemPos].subMenuParentMenu = this; + + submenu->isSubmenu = true; + + return itemPos; +} + +bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator, const char* cmd) +{ + String titleString = title; + + for (U32 i = 0; i < mMenuItems.size(); i++) + { + if (mMenuItems[i].text == titleString) + { + mMenuItems[i].id = pos; + mMenuItems[i].cmd = cmd; + + if (accelerator && accelerator[0]) + mMenuItems[i].accelerator = dStrdup(accelerator); + else + mMenuItems[i].accelerator = NULL; + return true; + } + } + + return false; +} + +void PopupMenu::removeItem(S32 itemPos) +{ + if (mMenuItems.size() < itemPos || itemPos < 0) + return; + + mMenuItems.erase(itemPos); +} + +////////////////////////////////////////////////////////////////////////// +void PopupMenu::enableItem(S32 pos, bool enable) +{ + if (mMenuItems.size() < pos || pos < 0) + return; + + mMenuItems[pos].enabled = enable; +} + +void PopupMenu::checkItem(S32 pos, bool checked) +{ + if (mMenuItems.size() < pos || pos < 0) + return; + + if (checked && mMenuItems[pos].checkGroup != -1) + { + // first, uncheck everything in the group: + for (U32 i = 0; i < mMenuItems.size(); i++) + if (mMenuItems[i].checkGroup == mMenuItems[pos].checkGroup && mMenuItems[i].isChecked) + mMenuItems[i].isChecked = false; + } + + mMenuItems[pos].isChecked; +} + +void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos) +{ + for (U32 i = 0; i < mMenuItems.size(); i++) + { + if (mMenuItems[i].id >= firstPos && mMenuItems[i].id <= lastPos) + { + mMenuItems[i].isChecked = false; + } + } +} + +bool PopupMenu::isItemChecked(S32 pos) +{ + if (mMenuItems.size() < pos || pos < 0) + return false; + + return mMenuItems[pos].isChecked; +} + +U32 PopupMenu::getItemCount() +{ + return mMenuItems.size(); +} + +////////////////////////////////////////////////////////////////////////// +bool PopupMenu::canHandleID(U32 id) +{ + return true; +} + +bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */) +{ + return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(command), text ? text : "")); +} + +////////////////////////////////////////////////////////////////////////// +void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */) +{ + if (owner == NULL) + return; + + GuiControl* editorGui; + Sim::findObject("EditorGui", editorGui); + + if (editorGui) + { + GuiPopupMenuBackgroundCtrl* backgroundCtrl; + Sim::findObject("PopUpMenuControl", backgroundCtrl); + + GuiControlProfile* profile; + Sim::findObject("GuiMenubarProfile", profile); + + if (!profile) + return; + + if (mTextList == nullptr) + { + mTextList = new GuiPopupMenuTextListCtrl(); + mTextList->registerObject(); + mTextList->setControlProfile(profile); + + mTextList->mPopup = this; + mTextList->mMenuBar = getMenuBarCtrl(); + } + + if (!backgroundCtrl) + { + backgroundCtrl = new GuiPopupMenuBackgroundCtrl(); + + backgroundCtrl->registerObject("PopUpMenuControl"); + } + + if (!backgroundCtrl || !mTextList) + return; + + if (!isSubmenu) + { + //if we're a 'parent' menu, then tell the background to clear out all existing other popups + + backgroundCtrl->clearPopups(); + } + + //find out if we're doing a first-time add + S32 popupIndex = backgroundCtrl->findPopupMenu(this); + + if (popupIndex == -1) + { + backgroundCtrl->addObject(mTextList); + backgroundCtrl->mPopups.push_back(this); + } + + mTextList->mBackground = backgroundCtrl; + + owner->pushDialogControl(backgroundCtrl, 10); + + //Set the background control's menubar, if any, and if it's not already set + if(backgroundCtrl->mMenuBarCtrl == nullptr) + backgroundCtrl->mMenuBarCtrl = getMenuBarCtrl(); + + backgroundCtrl->setExtent(editorGui->getExtent()); + + mTextList->clear(); + + S32 textWidth = 0, width = 0; + S32 acceleratorWidth = 0; + GFont *font = profile->mFont; + + Point2I maxBitmapSize = Point2I(0, 0); + + S32 numBitmaps = profile->mBitmapArrayRects.size(); + if (numBitmaps) + { + RectI *bitmapBounds = profile->mBitmapArrayRects.address(); + for (S32 i = 0; i < numBitmaps; i++) + { + if (bitmapBounds[i].extent.x > maxBitmapSize.x) + maxBitmapSize.x = bitmapBounds[i].extent.x; + if (bitmapBounds[i].extent.y > maxBitmapSize.y) + maxBitmapSize.y = bitmapBounds[i].extent.y; + } + } + + for (U32 i = 0; i < mMenuItems.size(); i++) + { + if (!mMenuItems[i].visible) + continue; + + S32 iTextWidth = font->getStrWidth(mMenuItems[i].text.c_str()); + S32 iAcceleratorWidth = mMenuItems[i].accelerator ? font->getStrWidth(mMenuItems[i].accelerator) : 0; + + if (iTextWidth > textWidth) + textWidth = iTextWidth; + if (iAcceleratorWidth > acceleratorWidth) + acceleratorWidth = iAcceleratorWidth; + } + + width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4; + + mTextList->setCellSize(Point2I(width, font->getHeight() + 2)); + mTextList->clearColumnOffsets(); + mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index. + mTextList->addColumnOffset(maxBitmapSize.x + 1); + mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4); + + U32 entryCount = 0; + + for (U32 i = 0; i < mMenuItems.size(); i++) + { + if (!mMenuItems[i].visible) + continue; + + char buf[512]; + + // If this menu item is a submenu, then set the isSubmenu to 2 to indicate + // an arrow should be drawn. Otherwise set the isSubmenu normally. + char isSubmenu = 1; + if (mMenuItems[i].isSubmenu) + isSubmenu = 2; + + char bitmapIndex = 1; + if (mMenuItems[i].bitmapIndex >= 0 && (mMenuItems[i].bitmapIndex * 3 <= profile->mBitmapArrayRects.size())) + bitmapIndex = mMenuItems[i].bitmapIndex + 2; + + dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, mMenuItems[i].text.c_str(), mMenuItems[i].accelerator ? mMenuItems[i].accelerator : ""); + mTextList->addEntry(entryCount, buf); + + if (!mMenuItems[i].enabled) + mTextList->setEntryActive(entryCount, false); + + entryCount++; + } + + Point2I pos = Point2I::Zero; + + if (x == -1 && y == -1) + pos = owner->getCursorPos(); + else + pos = Point2I(x, y); + + mTextList->setPosition(pos); + + //nudge in if we'd overshoot the screen + S32 widthDiff = (mTextList->getPosition().x + mTextList->getExtent().x) - backgroundCtrl->getWidth(); + if (widthDiff > 0) + { + Point2I popupPos = mTextList->getPosition(); + mTextList->setPosition(popupPos.x - widthDiff, popupPos.y); + } + + mTextList->setHidden(false); + } +} + +void PopupMenu::hidePopup() +{ + if (mTextList) + { + mTextList->setHidden(true); + } + + hidePopupSubmenus(); +} + +void PopupMenu::hidePopupSubmenus() +{ + for (U32 i = 0; i < mMenuItems.size(); i++) + { + if (mMenuItems[i].subMenu != nullptr) + mMenuItems[i].subMenu->hidePopup(); + } +} + +//----------------------------------------------------------------------------- +// Console Methods +//----------------------------------------------------------------------------- +DefineConsoleMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator, const char* cmd), ("", "", ""), "(pos[, title][, accelerator][, cmd])") +{ + return object->insertItem(pos, title, accelerator, cmd); +} + +DefineConsoleMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)") +{ + object->removeItem(pos); +} + +DefineConsoleMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, String subMenu), , "(pos, title, subMenu)") +{ + PopupMenu *mnu = dynamic_cast(Sim::findObject(subMenu)); + if(mnu == NULL) + { + Con::errorf("PopupMenu::insertSubMenu - Invalid PopupMenu object specified for submenu"); + return -1; + } + return object->insertSubMenu(pos, title, mnu); +} + +DefineConsoleMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator, const char *cmd), (""), "(pos, title[, accelerator][, cmd])") +{ + return object->setItem(pos, title, accelerator, cmd); +} + +//----------------------------------------------------------------------------- + +DefineConsoleMethod(PopupMenu, enableItem, void, (S32 pos, bool enabled), , "(pos, enabled)") +{ + object->enableItem(pos, enabled); +} + +DefineConsoleMethod(PopupMenu, checkItem, void, (S32 pos, bool checked), , "(pos, checked)") +{ + object->checkItem(pos, checked); +} + +DefineConsoleMethod(PopupMenu, checkRadioItem, void, (S32 firstPos, S32 lastPos, S32 checkPos), , "(firstPos, lastPos, checkPos)") +{ + object->checkRadioItem(firstPos, lastPos, checkPos); +} + +DefineConsoleMethod(PopupMenu, isItemChecked, bool, (S32 pos), , "(pos)") +{ + return object->isItemChecked(pos); +} + +DefineConsoleMethod(PopupMenu, getItemCount, S32, (), , "()") +{ + return object->getItemCount(); +} + +//----------------------------------------------------------------------------- +DefineConsoleMethod(PopupMenu, showPopup, void, (const char * canvasName, S32 x, S32 y), ( -1, -1), "(Canvas,[x, y])") +{ + GuiCanvas *pCanvas = dynamic_cast(Sim::findObject(canvasName)); + object->showPopup(pCanvas, x, y); +} diff --git a/Engine/source/platform/menus/popupMenu.h b/Engine/source/gui/editor/popupMenu.h similarity index 69% rename from Engine/source/platform/menus/popupMenu.h rename to Engine/source/gui/editor/popupMenu.h index 8d1239972..9a6dd0821 100644 --- a/Engine/source/platform/menus/popupMenu.h +++ b/Engine/source/gui/editor/popupMenu.h @@ -19,17 +19,43 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- +#ifndef _POPUPMENU_H_ +#define _POPUPMENU_H_ + #include "console/simBase.h" #include "core/util/tVector.h" #include "util/messaging/dispatcher.h" #include "gui/core/guiCanvas.h" -#ifndef _POPUPMENU_H_ -#define _POPUPMENU_H_ +class PopupMenu; +class GuiMenuBar; +class GuiPopupMenuTextListCtrl; +class GuiPopupMenuBackgroundCtrl; -// Forward ref used by the platform code -struct PlatformPopupMenuData; -class MenuBar; +struct MenuItem // an individual item in a pull-down menu +{ + String text; // the text of the menu item + U32 id; // a script-assigned identifier + char *accelerator; // the keyboard accelerator shortcut for the menu item + U32 acceleratorIndex; // index of this accelerator + bool enabled; // true if the menu item is selectable + bool visible; // true if the menu item is visible + S32 bitmapIndex; // index of the bitmap in the bitmap array + S32 checkGroup; // the group index of the item visa vi check marks - + // only one item in the group can be checked. + + bool isSubmenu; // This menu item has a submenu that will be displayed + + bool isChecked; + + bool isSpacer; + + bool isMenubarEntry; + + PopupMenu* subMenuParentMenu; // For a submenu, this is the parent menu + PopupMenu* subMenu; + String cmd; +}; // PopupMenu represents a menu. // You can add menu items to the menu, but there is no torque object associated @@ -37,30 +63,32 @@ class MenuBar; class PopupMenu : public SimObject, public virtual Dispatcher::IMessageListener { typedef SimObject Parent; - - friend class MenuBar; - -private: - /// Used by MenuBar to attach the menu to the menu bar. Do not use anywhere else. - void attachToMenuBar(GuiCanvas *owner, S32 pos); + friend class GuiMenuBar; + friend class GuiPopupMenuTextListCtrl; + friend class GuiPopupMenuBackgroundCtrl; protected: - PlatformPopupMenuData *mData; - - SimSet *mSubmenus; - SimObjectPtr mCanvas; + Vector mMenuItems; - StringTableEntry mBarTitle; + GuiMenuBar* mMenuBarCtrl; - U32 mPopupGUID; - - bool mIsPopup; + StringTableEntry barTitle; + + RectI bounds; + bool visible; + + S32 bitmapIndex; // Index of the bitmap in the bitmap array (-1 = no bitmap) + bool drawBitmapOnly; // Draw only the bitmap and not the text + bool drawBorder; // Should a border be drawn around this menu (usually if we only have a bitmap, we don't want a border) + + bool isSubmenu; + + //This is the gui control that renders our popup + GuiPopupMenuTextListCtrl *mTextList; public: PopupMenu(); virtual ~PopupMenu(); - void createPlatformPopupMenuData(); - void deletePlatformPopupMenuData(); DECLARE_CONOBJECT(PopupMenu); @@ -72,15 +100,6 @@ public: static PopupMenuEvent smPopupMenuEvent; static bool smSelectionEventHandled; /// Set to true if any menu or submenu handles a selection event - /// Creates the platform specific menu object, a peer to this object. - /// The platform menu *must* exist before calling any method that manipulates - /// menu items or displays the menu. - /// implementd on a per-platform basis. - void createPlatformMenu(); - - void setBarTitle(const char * val) { mBarTitle = StringTable->insert(val, true); } - StringTableEntry getBarTitle() const { return mBarTitle; } - /// pass NULL for @p title to insert a separator /// returns the menu item's ID, or -1 on failure. /// implementd on a per-platform basis. @@ -118,39 +137,7 @@ public: /// Returns the number of items in the menu. U32 getItemCount(); - /// Returns the popup GUID - U32 getPopupGUID() { return mPopupGUID; } - //----------------------------------------------------------------------------- - // New code should not use these methods directly, use the menu bar instead. - // - // They remain for compatibility with old code and will be changing/going away - // once the existing code is moved over to the menu bar. - //----------------------------------------------------------------------------- - - /// Places this menu in the menu bar of the application's main window. - /// @param owner The GuiCanvas that owns the PlatformWindow that this call is associated with - /// @param pos The relative position at which to place the menu. - /// @param title The name of the menu - void attachToMenuBar(GuiCanvas *owner, S32 pos, const char *title); - - /// Removes this menu from the menu bar. - void removeFromMenuBar(); - - //----------------------------------------------------------------------------- - - /// Called when the menu has been attached to the menu bar - void onAttachToMenuBar(GuiCanvas *canvas, S32 pos, const char *title); - - /// Called when the menu has been removed from the menu bar - void onRemoveFromMenuBar(GuiCanvas *canvas); - - /// Returns the position index of this menu on the bar. - S32 getPosOnMenuBar(); - - /// Returns true if this menu is attached to the menu bar - bool isAttachedToMenuBar() { return mCanvas != NULL; } - /// Displays this menu as a popup menu and blocks until the user has selected /// an item. /// @param canvas the owner to show this popup associated with @@ -159,6 +146,9 @@ public: /// implemented on a per-platform basis. void showPopup(GuiCanvas *owner, S32 x = -1, S32 y = -1); + void hidePopup(); + void hidePopupSubmenus(); + /// Returns true iff this menu contains an item that matches @p iD. /// implemented on a per-platform basis. /// TODO: factor out common code @@ -184,6 +174,11 @@ public: virtual bool onMessageReceived(StringTableEntry queue, const char* event, const char* data ); virtual bool onMessageObjectReceived(StringTableEntry queue, Message *msg ); + + bool isVisible() { return visible; } + void setVisible(bool isVis) { visible = isVis; } + + GuiMenuBar* getMenuBarCtrl(); }; #endif // _POPUPMENU_H_ diff --git a/Engine/source/platform/menus/menuBar.cpp b/Engine/source/platform/menus/menuBar.cpp deleted file mode 100644 index cb70838a8..000000000 --- a/Engine/source/platform/menus/menuBar.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "platform/menus/menuBar.h" -#include "platform/menus/popupMenu.h" -#include "gui/core/guiCanvas.h" -#include "console/engineAPI.h" - -//----------------------------------------------------------------------------- -// Constructor/Destructor -//----------------------------------------------------------------------------- - -MenuBar::MenuBar() -{ - createPlatformPopupMenuData(); - - mCanvas = NULL; -} - -MenuBar::~MenuBar() -{ - removeFromCanvas(); - - deletePlatformPopupMenuData(); -} - -IMPLEMENT_CONOBJECT(MenuBar); - -ConsoleDocClass( MenuBar, - "@brief Used for rendering platform menu bars\n\n" - "Internal use only\n\n" - "@internal" -); - -//----------------------------------------------------------------------------- -// Public Methods -//----------------------------------------------------------------------------- - -void MenuBar::addObject(SimObject *obj) -{ - Parent::addObject(obj); - updateMenuBar(dynamic_cast(obj)); -} - -void MenuBar::removeObject(SimObject *obj) -{ - Parent::removeObject(obj); - updateMenuBar(dynamic_cast(obj)); -} - -void MenuBar::insertObject(SimObject *obj, S32 pos) -{ - Parent::addObject(obj); - - if(pos >= size()) - pos = size() - 1; - - if(pos < size()) - { - if(pos < 0) pos = 0; - Parent::reOrder(obj, at(pos)); - } - updateMenuBar(dynamic_cast(obj)); -} - -void MenuBar::pushObject(SimObject *obj) -{ - Parent::pushObject(obj); - updateMenuBar(dynamic_cast(obj)); -} - -void MenuBar::popObject() -{ - Parent::popObject(); - updateMenuBar(); -} - -bool MenuBar::reOrder(SimObject *obj, SimObject *target /*= 0*/) -{ - bool ret = Parent::reOrder(obj, target); - if(ret) - updateMenuBar(dynamic_cast(obj)); - return ret; -} - -//----------------------------------------------------------------------------- -// Console Methods -//----------------------------------------------------------------------------- - -DefineConsoleMethod(MenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)") -{ - object->attachToCanvas(dynamic_cast(Sim::findObject(canvas)), pos); -} - -DefineConsoleMethod(MenuBar, removeFromCanvas, void, (), , "()") -{ - object->removeFromCanvas(); -} - -//----------------------------------------------------------------------------- - -DefineConsoleMethod(MenuBar, insert, void, (SimObject* pObject, S32 pos), ,"(object, pos) insert object at position") -{ - - if(pObject) - object->insertObject(pObject, pos); -} diff --git a/Engine/source/platform/menus/menuBar.h b/Engine/source/platform/menus/menuBar.h deleted file mode 100644 index 0e0e64602..000000000 --- a/Engine/source/platform/menus/menuBar.h +++ /dev/null @@ -1,71 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "console/simBase.h" - -#ifndef _MENUBAR_H_ -#define _MENUBAR_H_ - -// Forward Refs -class PlatformMenuBarData; -class PopupMenu; -class GuiCanvas; - -class MenuBar : public SimSet -{ - typedef SimSet Parent; - -protected: - PlatformMenuBarData *mData; - GuiCanvas *mCanvas; - - /// Update the native menu bar to ensure consistency with the set - void updateMenuBar(PopupMenu *menu = NULL); - - void createPlatformPopupMenuData(); - void deletePlatformPopupMenuData(); - -public: - MenuBar(); - virtual ~MenuBar(); - DECLARE_CONOBJECT(MenuBar); - - /// Attach this menu bar to the native menu bar - void attachToCanvas(GuiCanvas *owner, S32 pos); - /// Remove this menu bar from the native menu bar - void removeFromCanvas(); - - /// Returns true if this menu is attached to the menu bar - bool isAttachedToCanvas() { return mCanvas != NULL; } - - virtual void insertObject(SimObject *obj, S32 pos); - - // Overridden SimSet methods to ensure menu bar consistency when attached - virtual void addObject(SimObject *obj); - virtual void removeObject(SimObject *obj); - virtual void pushObject(SimObject *obj); - virtual void popObject(); - - virtual bool reOrder(SimObject *obj, SimObject *target = 0); -}; - -#endif // _MENUBAR_H_ diff --git a/Engine/source/platform/menus/popupMenu.cpp b/Engine/source/platform/menus/popupMenu.cpp deleted file mode 100644 index 7e8aad7ba..000000000 --- a/Engine/source/platform/menus/popupMenu.cpp +++ /dev/null @@ -1,269 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/menus/popupMenu.h" -#include "console/consoleTypes.h" -#include "console/engineAPI.h" -#include "gui/core/guiCanvas.h" -#include "core/util/safeDelete.h" - -static U32 sMaxPopupGUID = 0; -PopupMenuEvent PopupMenu::smPopupMenuEvent; -bool PopupMenu::smSelectionEventHandled = false; - -/// Event class used to remove popup menus from the event notification in a safe way -class PopUpNotifyRemoveEvent : public SimEvent -{ -public: - void process(SimObject *object) - { - PopupMenu::smPopupMenuEvent.remove((PopupMenu *)object, &PopupMenu::handleSelectEvent); - } -}; - -//----------------------------------------------------------------------------- -// Constructor/Destructor -//----------------------------------------------------------------------------- - -PopupMenu::PopupMenu() : mCanvas(NULL) -{ - createPlatformPopupMenuData(); - - mSubmenus = new SimSet; - mSubmenus->registerObject(); - - mBarTitle = StringTable->EmptyString(); - mIsPopup = false; - - mPopupGUID = sMaxPopupGUID++; -} - -PopupMenu::~PopupMenu() -{ - // This searches the menu bar so is safe to call for menus - // that aren't on it, since nothing will happen. - removeFromMenuBar(); - - SimSet::iterator i; - while((i = mSubmenus->begin()) != mSubmenus->end()) - { - (*i)->deleteObject(); - } - - mSubmenus->deleteObject(); - deletePlatformPopupMenuData(); - - PopupMenu::smPopupMenuEvent.remove(this, &PopupMenu::handleSelectEvent); -} - -IMPLEMENT_CONOBJECT(PopupMenu); - -ConsoleDocClass( PopupMenu, - "@brief PopupMenu represents a system menu.\n\n" - "You can add menu items to the menu, but there is no torque object associated " - "with these menu items, they exist only in a platform specific manner.\n\n" - "@note Internal use only\n\n" - "@internal" -); - - -//----------------------------------------------------------------------------- - -void PopupMenu::initPersistFields() -{ - addField("isPopup", TypeBool, Offset(mIsPopup, PopupMenu), "true if this is a pop-up/context menu. defaults to false."); - addField("barTitle", TypeCaseString, Offset(mBarTitle, PopupMenu), "the title of this menu when attached to a menu bar"); - - Parent::initPersistFields(); -} - -//----------------------------------------------------------------------------- - -bool PopupMenu::onAdd() -{ - if(! Parent::onAdd()) - return false; - - createPlatformMenu(); - - Con::executef(this, "onAdd"); - return true; -} - -void PopupMenu::onRemove() -{ - Con::executef(this, "onRemove"); - - Parent::onRemove(); -} - -//----------------------------------------------------------------------------- - -void PopupMenu::onMenuSelect() -{ - Con::executef(this, "onMenuSelect"); -} - -//----------------------------------------------------------------------------- - -void PopupMenu::handleSelectEvent(U32 popID, U32 command) -{ - if (popID == mPopupGUID && canHandleID(command)) - if (handleSelect(command)) - smSelectionEventHandled = true; -} - -//----------------------------------------------------------------------------- - -void PopupMenu::onAttachToMenuBar(GuiCanvas *canvas, S32 pos, const char *title) -{ - mCanvas = canvas; - - // Attached menus must be notified of menu events - smPopupMenuEvent.notify(this, &PopupMenu::handleSelectEvent); - - // Pass on to sub menus - for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i) - { - PopupMenu *mnu = dynamic_cast(*i); - if(mnu == NULL) - continue; - - mnu->onAttachToMenuBar(canvas, pos, title); - } - - // Call script - if(isProperlyAdded()) - Con::executef(this, "onAttachToMenuBar", Con::getIntArg(canvas ? canvas->getId() : 0), Con::getIntArg(pos), title); -} - -void PopupMenu::onRemoveFromMenuBar(GuiCanvas *canvas) -{ - mCanvas = NULL; - - // We are no longer interested in select events, remove ourselves from the notification list in a safe way - Sim::postCurrentEvent(this, new PopUpNotifyRemoveEvent()); - - // Pass on to sub menus - for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i) - { - PopupMenu *mnu = dynamic_cast(*i); - if(mnu == NULL) - continue; - - mnu->onRemoveFromMenuBar(canvas); - } - - // Call script - if(isProperlyAdded()) - Con::executef(this, "onRemoveFromMenuBar", Con::getIntArg(canvas ? canvas->getId() : 0)); -} - -//----------------------------------------------------------------------------- - -bool PopupMenu::onMessageReceived(StringTableEntry queue, const char* event, const char* data) -{ - return Con::executef(this, "onMessageReceived", queue, event, data); -} - - -bool PopupMenu::onMessageObjectReceived(StringTableEntry queue, Message *msg ) -{ - return Con::executef(this, "onMessageReceived", queue, Con::getIntArg(msg->getId())); -} - -//----------------------------------------------------------------------------- -// Console Methods -//----------------------------------------------------------------------------- - -DefineConsoleMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator, const char* cmd), ("", "", ""), "(pos[, title][, accelerator][, cmd])") -{ - return object->insertItem(pos, title, accelerator, cmd); -} - -DefineConsoleMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)") -{ - object->removeItem(pos); -} - -DefineConsoleMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, String subMenu), , "(pos, title, subMenu)") -{ - PopupMenu *mnu = dynamic_cast(Sim::findObject(subMenu)); - if(mnu == NULL) - { - Con::errorf("PopupMenu::insertSubMenu - Invalid PopupMenu object specified for submenu"); - return -1; - } - return object->insertSubMenu(pos, title, mnu); -} - -DefineConsoleMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator, const char *cmd), (""), "(pos, title[, accelerator][, cmd])") -{ - return object->setItem(pos, title, accelerator, cmd); -} - -//----------------------------------------------------------------------------- - -DefineConsoleMethod(PopupMenu, enableItem, void, (S32 pos, bool enabled), , "(pos, enabled)") -{ - object->enableItem(pos, enabled); -} - -DefineConsoleMethod(PopupMenu, checkItem, void, (S32 pos, bool checked), , "(pos, checked)") -{ - object->checkItem(pos, checked); -} - -DefineConsoleMethod(PopupMenu, checkRadioItem, void, (S32 firstPos, S32 lastPos, S32 checkPos), , "(firstPos, lastPos, checkPos)") -{ - object->checkRadioItem(firstPos, lastPos, checkPos); -} - -DefineConsoleMethod(PopupMenu, isItemChecked, bool, (S32 pos), , "(pos)") -{ - return object->isItemChecked(pos); -} - -DefineConsoleMethod(PopupMenu, getItemCount, S32, (), , "()") -{ - return object->getItemCount(); -} - -//----------------------------------------------------------------------------- - -DefineConsoleMethod(PopupMenu, attachToMenuBar, void, (const char * canvasName, S32 pos, const char * title), , "(GuiCanvas, pos, title)") -{ - object->attachToMenuBar(dynamic_cast(Sim::findObject(canvasName)), pos, title); -} - -DefineConsoleMethod(PopupMenu, removeFromMenuBar, void, (), , "()") -{ - object->removeFromMenuBar(); -} - -//----------------------------------------------------------------------------- - -DefineConsoleMethod(PopupMenu, showPopup, void, (const char * canvasName, S32 x, S32 y), ( -1, -1), "(Canvas,[x, y])") -{ - GuiCanvas *pCanvas = dynamic_cast(Sim::findObject(canvasName)); - object->showPopup(pCanvas, x, y); -} diff --git a/Engine/source/platformSDL/menus/PlatformSDLPopupMenuData.h b/Engine/source/platformSDL/menus/PlatformSDLPopupMenuData.h deleted file mode 100644 index 4911f5c10..000000000 --- a/Engine/source/platformSDL/menus/PlatformSDLPopupMenuData.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef PLATFORM_SDL_POPUPMENU_DATA_H -#define PLATFORM_SDL_POPUPMENU_DATA_H - -#include "core/util/tDictionary.h" - -class GuiMenuBar; -struct EventDescriptor; -class PopupMenu; -class MenuBar; - -struct PlatformPopupMenuData -{ - MenuBar *mMenuBar; - GuiMenuBar::Menu *mMenuGui; - - static const U8 mCheckedBitmapIdx = 0; - static Map mMenuMap; - - PlatformPopupMenuData() - { - mMenuBar = NULL; - mMenuGui = NULL; - } - - ~PlatformPopupMenuData() - { - - } - - void insertAccelerator(EventDescriptor &desc, U32 id); - void removeAccelerator(U32 id); - void setAccelleratorEnabled(U32 id, bool enabled); -}; - -#endif //PLATFORM_SDL_POPUPMENU_DATA_H \ No newline at end of file diff --git a/Engine/source/platformSDL/menus/guiPlatformGenericMenuBar.h b/Engine/source/platformSDL/menus/guiPlatformGenericMenuBar.h deleted file mode 100644 index b2129a8b1..000000000 --- a/Engine/source/platformSDL/menus/guiPlatformGenericMenuBar.h +++ /dev/null @@ -1,51 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#pragma once - -#include "gui/editor/guiMenuBar.h" -#include "platformSDL/menus/PlatformSDLPopupMenuData.h" -#include "platform/menus/popupMenu.h" - -class GuiPlatformGenericMenuBar : public GuiMenuBar -{ - typedef GuiMenuBar Parent; -public: - DECLARE_CONOBJECT(GuiPlatformGenericMenuBar); - - virtual void menuItemSelected(Menu *menu, MenuItem *item) - { - AssertFatal(menu && item, ""); - - PopupMenu *popupMenu = PlatformPopupMenuData::mMenuMap[menu]; - AssertFatal(popupMenu, ""); - - popupMenu->handleSelect(item->id); - - Parent::menuItemSelected(menu, item); - } - -protected: - /// menu id / item id - Map, String> mCmds; - -}; \ No newline at end of file diff --git a/Engine/source/platformSDL/menus/menuBarSDL.cpp b/Engine/source/platformSDL/menus/menuBarSDL.cpp deleted file mode 100644 index a0ddb2370..000000000 --- a/Engine/source/platformSDL/menus/menuBarSDL.cpp +++ /dev/null @@ -1,200 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/menus/menuBar.h" -#include "platform/menus/popupMenu.h" -#include "gui/core/guiCanvas.h" -#include "windowManager/platformWindowMgr.h" -#include "core/util/safeDelete.h" - -#include "windowManager/sdl/sdlWindow.h" -#include "gui/editor/guiMenuBar.h" - -#include "platformSDL/menus/PlatformSDLPopupMenuData.h" - -#include "platformSDL/menus/guiPlatformGenericMenuBar.h" - -#ifdef TORQUE_SDL - -//----------------------------------------------------------------------------- -// Platform Data -//----------------------------------------------------------------------------- - -// class PlatformMenuBarData -// { -// -// }; - -Map PlatformPopupMenuData::mMenuMap; - -IMPLEMENT_CONOBJECT(GuiPlatformGenericMenuBar); - -//----------------------------------------------------------------------------- -// MenuBar Methods -//----------------------------------------------------------------------------- - -void MenuBar::createPlatformPopupMenuData() -{ - mData = NULL; -} - -void MenuBar::deletePlatformPopupMenuData() -{ -// SAFE_DELETE(mData); -} - -//----------------------------------------------------------------------------- - -GuiPlatformGenericMenuBar* _FindMenuBarCtrl() -{ - GuiControl* control; - Sim::findObject("PlatformGenericMenubar", control); - AssertFatal(control, ""); - if( !control ) - return NULL; - - GuiPlatformGenericMenuBar* menuBar; - menuBar = dynamic_cast( control->findObjectByInternalName( StringTable->insert("menubar"), true) ); - AssertFatal(menuBar, ""); - return menuBar; -} - - -void MenuBar::updateMenuBar(PopupMenu *popupMenu /* = NULL */) -{ - //if(! isAttachedToCanvas()) - // return; - - if(!popupMenu) - return; - - GuiPlatformGenericMenuBar* menuBarGui = _FindMenuBarCtrl(); - popupMenu->mData->mMenuBar = this; - - String menuTitle = popupMenu->getBarTitle(); - - //Next, find out if we're still in the list of entries - SimSet::iterator itr = find(begin(), end(), popupMenu); - - GuiMenuBar::Menu* menuGui = menuBarGui->findMenu(menuTitle); - if (!menuGui) - { - //This is our first time setting this particular menu up, so we'll OK it. - if (itr == end()) - menuBarGui->attachToMenuBar(popupMenu->mData->mMenuGui); - else - menuBarGui->attachToMenuBar(popupMenu->mData->mMenuGui, itr - begin()); - } - else - { - //Not our first time through, so we're really updating it. - - //So, first, remove it from the menubar - menuBarGui->removeFromMenuBar(menuGui); - - //Next, find out if we're still in the list of entries - SimSet::iterator itr = find(begin(), end(), popupMenu); - - //if we're no longer in the list, we're pretty much done here - if (itr == end()) - return; - - //We're still here, so this is a valid menu for our current bar configuration, so add us back in. - menuBarGui->attachToMenuBar(menuGui, itr - begin()); - } -} - -//----------------------------------------------------------------------------- - -void MenuBar::attachToCanvas(GuiCanvas *owner, S32 pos) -{ - if(owner == NULL || isAttachedToCanvas()) - return; - - // This is set for popup menus in the onAttachToMenuBar() callback - mCanvas = owner; - - PlatformWindowSDL *pWindow = dynamic_cast(owner->getPlatformWindow()); - if(pWindow == NULL) - return; - - // Setup the native menu bar - GuiMenuBar *hWindowMenu = static_cast( pWindow->getMenuHandle() ); - if( hWindowMenu == NULL && !Journal::IsPlaying() ) - hWindowMenu = _FindMenuBarCtrl(); - - if(hWindowMenu) - { - pWindow->setMenuHandle( hWindowMenu ); - GuiControl *base = hWindowMenu->getParent(); - - while( base->getParent() ) - { - base = base->getParent(); - } - - mCanvas->setMenuBar( base ); - } - - for (S32 i = 0; i < size(); ++i) - { - PopupMenu *mnu = dynamic_cast(at(i)); - if (mnu == NULL) - { - Con::warnf("MenuBar::attachToMenuBar - Non-PopupMenu object in set"); - continue; - } - - if (mnu->isAttachedToMenuBar()) - mnu->removeFromMenuBar(); - - mnu->attachToMenuBar(owner, pos + i); - } - -} - -void MenuBar::removeFromCanvas() -{ - if (mCanvas == NULL || !isAttachedToCanvas()) - return; - - //_FindMenuBarCtrl()->clearMenus(); - - // Add the items - for (S32 i = 0; i < size(); ++i) - { - PopupMenu *mnu = dynamic_cast(at(i)); - if (mnu == NULL) - { - Con::warnf("MenuBar::removeFromMenuBar - Non-PopupMenu object in set"); - continue; - } - - mnu->removeFromMenuBar(); - } - - mCanvas->setMenuBar(NULL); - - mCanvas = NULL; -} - -#endif diff --git a/Engine/source/platformSDL/menus/popupMenuSDL.cpp b/Engine/source/platformSDL/menus/popupMenuSDL.cpp deleted file mode 100644 index 788d7c88e..000000000 --- a/Engine/source/platformSDL/menus/popupMenuSDL.cpp +++ /dev/null @@ -1,393 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifdef TORQUE_SDL - -#include "platform/menus/popupMenu.h" -#include "platform/menus/menuBar.h" -#include "console/consoleTypes.h" -#include "gui/core/guiCanvas.h" -#include "core/util/safeDelete.h" - -#include "sim/actionMap.h" -#include "platform/platformInput.h" - -#include "windowManager/sdl/sdlWindow.h" -#include "gui/editor/guiMenuBar.h" - -#include "platformSDL/menus/PlatformSDLPopupMenuData.h" -#include "console/engineAPI.h" - -#include "platformSDL/menus/guiPlatformGenericMenuBar.h" -#include "gui/editor/guiPopupMenuCtrl.h" - -////////////////////////////////////////////////////////////////////////// -// Platform Menu Data -////////////////////////////////////////////////////////////////////////// -GuiPlatformGenericMenuBar* findMenuBarCtrl() -{ - GuiControl* control; - Sim::findObject("PlatformGenericMenubar", control); - AssertFatal(control, ""); - if (!control) - return NULL; - - GuiPlatformGenericMenuBar* menuBar; - menuBar = dynamic_cast(control->findObjectByInternalName(StringTable->insert("menubar"), true)); - AssertFatal(menuBar, ""); - return menuBar; -} - -////////////////////////////////////////////////////////////////////////// - -void PlatformPopupMenuData::insertAccelerator(EventDescriptor &desc, U32 id) -{ - AssertFatal(0, ""); -} - -void PlatformPopupMenuData::removeAccelerator(U32 id) -{ - AssertFatal(0, ""); -} - -void PlatformPopupMenuData::setAccelleratorEnabled( U32 id, bool enabled ) -{ - AssertFatal(0, ""); -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::createPlatformPopupMenuData() -{ - mData = new PlatformPopupMenuData; -} - -void PopupMenu::deletePlatformPopupMenuData() -{ - SAFE_DELETE(mData); -} -void PopupMenu::createPlatformMenu() -{ - mData->mMenuGui = GuiMenuBar::sCreateMenu( getBarTitle(), getId() ); - PlatformPopupMenuData::mMenuMap[ mData->mMenuGui ] = this; -} - - -////////////////////////////////////////////////////////////////////////// -// Public Methods -////////////////////////////////////////////////////////////////////////// - -S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator, const char* cmd) -{ - GuiMenuBar::MenuItem *item = GuiMenuBar::findMenuItem( mData->mMenuGui, title ); - - //We'll make a special exception for the spacer items - if(item && dStrcmp(title, "")) - { - setItem( pos, title, accelerator, cmd); - return pos; - } - - item = GuiMenuBar::addMenuItem( mData->mMenuGui, title, pos, accelerator, -1, cmd ); - item->submenuParentMenu = this->mData->mMenuGui; - - return pos; -} - -S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu) -{ - GuiMenuBar::MenuItem *item = GuiMenuBar::addMenuItem( mData->mMenuGui, title, pos, "", -1, "" ); - item->isSubmenu = true; - item->submenu = submenu->mData->mMenuGui; - item->submenuParentMenu = this->mData->mMenuGui; - - return pos; -} - -bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator, const char* cmd) -{ - GuiMenuBar::MenuItem *item = NULL; - - item = GuiMenuBar::findMenuItem( mData->mMenuGui, title ); - - if(item) - { - item->id = pos; - item->cmd = cmd; - if( accelerator && accelerator[0] ) - item->accelerator = dStrdup( accelerator ); - else - item->accelerator = NULL; - return true; - } - - return false; -} - -void PopupMenu::removeItem(S32 itemPos) -{ - GuiMenuBar::MenuItem *item = GuiMenuBar::findMenuItem( mData->mMenuGui, String::ToString(itemPos) ); - if(item) - { - GuiMenuBar::removeMenuItem( mData->mMenuGui, item); - } -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::enableItem( S32 pos, bool enable ) -{ - GuiMenuBar::MenuItem *item = NULL; - for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem ) - { - if( item->id == pos) - item->enabled = enable; - } -} - -void PopupMenu::checkItem(S32 pos, bool checked) -{ - GuiMenuBar::MenuItem *item = NULL; - for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem ) - if(item->id == pos) - break; - - if( !item ) - return; - - if(checked && item->checkGroup != -1) - { - // first, uncheck everything in the group: - for( GuiMenuBar::MenuItem *itemWalk = mData->mMenuGui->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem ) - if( itemWalk->checkGroup == item->checkGroup && itemWalk->bitmapIndex == mData->mCheckedBitmapIdx ) - itemWalk->bitmapIndex = -1; - } - - item->bitmapIndex = checked ? mData->mCheckedBitmapIdx : -1; -} - -void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos) -{ - GuiMenuBar::MenuItem *item = NULL; - for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem ) - { - if(item->id >= firstPos && item->id <= lastPos) - { - item->bitmapIndex = (item->id == checkPos) ? mData->mCheckedBitmapIdx : -1; - } - } -} - -bool PopupMenu::isItemChecked(S32 pos) -{ - GuiMenuBar::MenuItem *item = NULL; - for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem ) - if(item->id == pos) - return item->bitmapIndex == mData->mCheckedBitmapIdx; - - return false; -} - -U32 PopupMenu::getItemCount() -{ - int count = 0; - for( GuiMenuBar::MenuItem *item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem ) - ++count; - - return count; -} - -////////////////////////////////////////////////////////////////////////// - -bool PopupMenu::canHandleID(U32 id) -{ - return true; -} - -bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */) -{ - return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(command), text ? text : "")); -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */) -{ - if(owner == NULL) - return; - - GuiControl* editorGui; - Sim::findObject("EditorGui", editorGui); - - if (editorGui) - { - GuiPopupMenuTextListCtrl* textList; - GuiPopupMenuBackgroundCtrl* backgroundCtrl; - Sim::findObject("PopUpMenuControl", backgroundCtrl); - - GuiControlProfile* profile; - Sim::findObject("GuiMenubarProfile", profile); - - if (!profile) - return; - - if (!backgroundCtrl) - { - textList = new GuiPopupMenuTextListCtrl(); - - textList->registerObject(); - - backgroundCtrl = new GuiPopupMenuBackgroundCtrl(textList); - - backgroundCtrl->registerObject("PopUpMenuControl"); - - textList->setControlProfile(profile); - - backgroundCtrl->addObject(textList); - } - else - { - textList = dynamic_cast(backgroundCtrl->first()); - } - - if (!backgroundCtrl || !textList) - return; - - owner->pushDialogControl(backgroundCtrl, 10); - - backgroundCtrl->setExtent(editorGui->getExtent()); - - textList->clear(); - textList->mMenu = mData->mMenuGui; - textList->mMenuBar = findMenuBarCtrl(); - textList->mPopup = this; - - S32 textWidth = 0, width = 0; - S32 acceleratorWidth = 0; - GFont *font = profile->mFont; - - Point2I maxBitmapSize = Point2I(0, 0); - - S32 numBitmaps = profile->mBitmapArrayRects.size(); - if (numBitmaps) - { - RectI *bitmapBounds = profile->mBitmapArrayRects.address(); - for (S32 i = 0; i < numBitmaps; i++) - { - if (bitmapBounds[i].extent.x > maxBitmapSize.x) - maxBitmapSize.x = bitmapBounds[i].extent.x; - if (bitmapBounds[i].extent.y > maxBitmapSize.y) - maxBitmapSize.y = bitmapBounds[i].extent.y; - } - } - - for (GuiMenuBar::MenuItem *walk = mData->mMenuGui->firstMenuItem; walk; walk = walk->nextMenuItem) - { - if (!walk->visible) - continue; - - S32 iTextWidth = font->getStrWidth(walk->text); - S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0; - - if (iTextWidth > textWidth) - textWidth = iTextWidth; - if (iAcceleratorWidth > acceleratorWidth) - acceleratorWidth = iAcceleratorWidth; - } - width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4; - - textList->setCellSize(Point2I(width, font->getHeight() + 2)); - textList->clearColumnOffsets(); - textList->addColumnOffset(-1); // add an empty column in for the bitmap index. - textList->addColumnOffset(maxBitmapSize.x + 1); - textList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4); - - U32 entryCount = 0; - - for (GuiMenuBar::MenuItem *walk = mData->mMenuGui->firstMenuItem; walk; walk = walk->nextMenuItem) - { - if (!walk->visible) - continue; - - char buf[512]; - - // If this menu item is a submenu, then set the isSubmenu to 2 to indicate - // an arrow should be drawn. Otherwise set the isSubmenu normally. - char isSubmenu = 1; - if (walk->isSubmenu) - isSubmenu = 2; - - char bitmapIndex = 1; - if (walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= profile->mBitmapArrayRects.size())) - bitmapIndex = walk->bitmapIndex + 2; - dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : ""); - textList->addEntry(entryCount, buf); - - if (!walk->enabled) - textList->setEntryActive(entryCount, false); - - entryCount++; - } - - Point2I pos = owner->getCursorPos(); - textList->setPosition(pos); - - //nudge in if we'd overshoot the screen - S32 widthDiff = (textList->getPosition().x + textList->getExtent().x) - backgroundCtrl->getWidth(); - if (widthDiff > 0) - { - Point2I popupPos = textList->getPosition(); - textList->setPosition(popupPos.x - widthDiff, popupPos.y); - } - } -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos, const char *title) -{ - if(owner == NULL || isAttachedToMenuBar()) - return; -} - -// New version of above for use by MenuBar class. Do not use yet. -void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos) -{ - if(owner == NULL || isAttachedToMenuBar()) - return; - - //mData->mMenuBar = owner->setMenuBar(); -} - -void PopupMenu::removeFromMenuBar() -{ - if(isAttachedToMenuBar()) - return; -} - -S32 PopupMenu::getPosOnMenuBar() -{ - - return 0; -} - -#endif diff --git a/Engine/source/platformWin32/menus/menuBarWin32.cpp b/Engine/source/platformWin32/menus/menuBarWin32.cpp deleted file mode 100644 index dfa103161..000000000 --- a/Engine/source/platformWin32/menus/menuBarWin32.cpp +++ /dev/null @@ -1,177 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platformWin32/platformWin32.h" -#include "platform/menus/menuBar.h" -#include "platform/menus/popupMenu.h" -#include "gui/core/guiCanvas.h" -#include "windowManager/platformWindowMgr.h" -#include "windowManager/win32/win32Window.h" -#include "core/util/safeDelete.h" - -//----------------------------------------------------------------------------- -// Platform Data -//----------------------------------------------------------------------------- - -// class PlatformMenuBarData -// { -// -// }; - -//----------------------------------------------------------------------------- -// MenuBar Methods -//----------------------------------------------------------------------------- - -#ifndef TORQUE_SDL - -void MenuBar::createPlatformPopupMenuData() -{ -// mData = new PlatformMenuBarData; - - // [tom, 6/4/2007] Nothing currently needed for win32 - mData = NULL; -} - -void MenuBar::deletePlatformPopupMenuData() -{ -// SAFE_DELETE(mData); -} - -//----------------------------------------------------------------------------- - -void MenuBar::updateMenuBar(PopupMenu *menu /* = NULL */) -{ - if(! isAttachedToCanvas()) - return; - - if(menu == NULL) - { - // [tom, 6/4/2007] Kludgetastic - GuiCanvas *oldCanvas = mCanvas; - S32 pos = -1; - PopupMenu *mnu = dynamic_cast(at(0)); - if(mnu) - pos = mnu->getPosOnMenuBar(); - - removeFromCanvas(); - attachToCanvas(oldCanvas, pos); - - return; - } - - menu->removeFromMenuBar(); - SimSet::iterator itr = find(begin(), end(), menu); - if(itr == end()) - return; - - menu->attachToMenuBar(mCanvas, itr - begin()); - - Win32Window *pWindow = dynamic_cast(mCanvas->getPlatformWindow()); - if(pWindow == NULL) - return; - - HWND hWindow = pWindow->getHWND(); - DrawMenuBar(hWindow); -} - -//----------------------------------------------------------------------------- - -void MenuBar::attachToCanvas(GuiCanvas *owner, S32 pos) -{ - if(owner == NULL || isAttachedToCanvas()) - return; - - // This is set for popup menus in the onAttachToMenuBar() callback - mCanvas = owner; - - Win32Window *pWindow = dynamic_cast(owner->getPlatformWindow()); - if(pWindow == NULL) - return; - - // Setup the native menu bar - HMENU hWindowMenu = pWindow->getMenuHandle(); - if(hWindowMenu == NULL && !Journal::IsPlaying()) - { - hWindowMenu = CreateMenu(); - if(hWindowMenu) - { - pWindow->setMenuHandle( hWindowMenu); - } - } - - // Add the items - for(S32 i = 0;i < size();++i) - { - PopupMenu *mnu = dynamic_cast(at(i)); - if(mnu == NULL) - { - Con::warnf("MenuBar::attachToMenuBar - Non-PopupMenu object in set"); - continue; - } - - if(mnu->isAttachedToMenuBar()) - mnu->removeFromMenuBar(); - - mnu->attachToMenuBar(owner, pos + i); - } - - HWND hWindow = pWindow->getHWND(); - SetMenu(hWindow, hWindowMenu); - DrawMenuBar(hWindow); - -} - -void MenuBar::removeFromCanvas() -{ - if(mCanvas == NULL || ! isAttachedToCanvas()) - return; - - Win32Window *pWindow = dynamic_cast(mCanvas->getPlatformWindow()); - if(pWindow == NULL) - return; - - // Setup the native menu bar - HMENU hWindowMenu = pWindow->getMenuHandle(); - if(hWindowMenu == NULL) - return; - - // Add the items - for(S32 i = 0;i < size();++i) - { - PopupMenu *mnu = dynamic_cast(at(i)); - if(mnu == NULL) - { - Con::warnf("MenuBar::removeFromMenuBar - Non-PopupMenu object in set"); - continue; - } - - mnu->removeFromMenuBar(); - } - - HWND hWindow = pWindow->getHWND(); - SetMenu(hWindow, NULL); - DrawMenuBar(hWindow); - - mCanvas = NULL; -} - -#endif diff --git a/Engine/source/platformWin32/menus/popupMenuWin32.cpp b/Engine/source/platformWin32/menus/popupMenuWin32.cpp deleted file mode 100644 index fc3170eeb..000000000 --- a/Engine/source/platformWin32/menus/popupMenuWin32.cpp +++ /dev/null @@ -1,746 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef TORQUE_SDL - -#include "platform/menus/popupMenu.h" -#include "platformWin32/platformWin32.h" -#include "console/engineAPI.h" -#include "console/consoleTypes.h" -#include "gui/core/guiCanvas.h" -#include "windowManager/platformWindowMgr.h" -#include "windowManager/win32/win32Window.h" -#include "core/util/safeDelete.h" - -#include "sim/actionMap.h" -#include "platform/platformInput.h" - -////////////////////////////////////////////////////////////////////////// -// Platform Menu Data -////////////////////////////////////////////////////////////////////////// - -struct PlatformPopupMenuData -{ - static U32 mLastPopupMenuID; - static const U32 PopupMenuIDRange; - - HMENU mMenu; - U32 mMenuID; - U32 mLastID; - - Win32Window::AcceleratorList mAccelerators; - Win32Window::AcceleratorList mDisabledAccelerators; - - PlatformPopupMenuData() - { - mMenu = NULL; - mMenuID = mLastPopupMenuID++; - mLastID = 0; - } - - ~PlatformPopupMenuData() - { - if(mMenu) - DestroyMenu(mMenu); - } - - void insertAccelerator(EventDescriptor &desc, U32 id); - void removeAccelerator(U32 id); - void setAccelleratorEnabled(U32 id, bool enabled); -}; - -U32 PlatformPopupMenuData::mLastPopupMenuID = 0; -const U32 PlatformPopupMenuData::PopupMenuIDRange = 100; - -////////////////////////////////////////////////////////////////////////// - -void PlatformPopupMenuData::insertAccelerator(EventDescriptor &desc, U32 id) -{ - if(desc.eventType != SI_KEY) - return; - - Win32Window::AcceleratorList::iterator i; - for(i = mAccelerators.begin();i != mAccelerators.end();++i) - { - if(i->mID == id) - { - // Update existing entry - i->mDescriptor.eventType = desc.eventType; - i->mDescriptor.eventCode = desc.eventCode; - i->mDescriptor.flags = desc.flags; - return; - } - - if(i->mDescriptor.eventType == desc.eventType && i->mDescriptor.eventCode == desc.eventCode && i->mDescriptor.flags == desc.flags) - { - // Already have a matching accelerator, don't add another one - return; - } - } - - Win32Window::Accelerator accel; - accel.mDescriptor = desc; - accel.mID = id; - mAccelerators.push_back(accel); -} - -void PlatformPopupMenuData::removeAccelerator(U32 id) -{ - Win32Window::AcceleratorList::iterator i; - for(i = mAccelerators.begin();i != mAccelerators.end();++i) - { - if(i->mID == id) - { - mAccelerators.erase(i); - return; - } - } -} - -void PlatformPopupMenuData::setAccelleratorEnabled( U32 id, bool enabled ) -{ - Win32Window::AcceleratorList *src = NULL; - Win32Window::AcceleratorList *dst = NULL; - - if ( enabled ) - { - src = &mDisabledAccelerators; - dst = &mAccelerators; - } - else - { - src = &mAccelerators; - dst = &mDisabledAccelerators; - } - - Win32Window::AcceleratorList::iterator i; - for ( i = src->begin(); i != src->end(); ++i ) - { - if ( i->mID == id ) - { - Win32Window::Accelerator tmp = *i; - src->erase( i ); - dst->push_back( tmp ); - return; - } - } -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::createPlatformPopupMenuData() -{ - mData = new PlatformPopupMenuData; -} - -void PopupMenu::deletePlatformPopupMenuData() -{ - SAFE_DELETE(mData); -} -void PopupMenu::createPlatformMenu() -{ - mData->mMenu = mIsPopup ? CreatePopupMenu() : CreateMenu(); - AssertFatal(mData->mMenu, "Unable to create menu"); - - MENUINFO mi = { 0 }; - mi.cbSize = sizeof(mi); - mi.fMask = MIM_MENUDATA; - mi.dwMenuData = (ULONG_PTR)this; - SetMenuInfo(mData->mMenu, &mi); -} - -////////////////////////////////////////////////////////////////////////// -// Public Methods -////////////////////////////////////////////////////////////////////////// - -S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator, const char *) -{ - Win32Window *pWindow = mCanvas ? dynamic_cast(mCanvas->getPlatformWindow()) : NULL; - bool isAttached = isAttachedToMenuBar(); - if(isAttached && pWindow == NULL) - return -1; - - MENUITEMINFOA mi = { 0 }; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_ID|MIIM_TYPE; - mi.wID = (mData->mMenuID * PlatformPopupMenuData::PopupMenuIDRange) + mData->mLastID + 1; - mData->mLastID++; - if(title && *title) - mi.fType = MFT_STRING; - else - mi.fType = MFT_SEPARATOR; - - char buf[1024]; - if(accelerator && *accelerator) - { - dSprintf(buf, sizeof(buf), "%s\t%s", title, accelerator); - - if(isAttached) - pWindow->removeAccelerators(mData->mAccelerators); - - // Build entry for accelerator table - EventDescriptor accelDesc; - if(ActionMap::createEventDescriptor(accelerator, &accelDesc)) - mData->insertAccelerator(accelDesc, mi.wID); - else - Con::errorf("PopupMenu::insertItem - Could not create event descriptor for accelerator \"%s\"", accelerator); - - if(isAttached) - pWindow->addAccelerators(mData->mAccelerators); - } - else - dSprintf(buf, sizeof(buf), "%s", title); - - mi.dwTypeData = (LPSTR)buf; - - if(InsertMenuItemA(mData->mMenu, pos, TRUE, &mi)) - { - if(isAttached) - { - HWND hWindow = pWindow->getHWND(); - DrawMenuBar(hWindow); - } - return mi.wID; - } - - return -1; -} - -S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu) -{ - Win32Window *pWindow = mCanvas ? dynamic_cast(mCanvas->getPlatformWindow()) : NULL; - bool isAttached = isAttachedToMenuBar(); - if(isAttached && pWindow == NULL) - return -1; - - for(S32 i = 0;i < mSubmenus->size();i++) - { - if(submenu == (*mSubmenus)[i]) - { - Con::errorf("PopupMenu::insertSubMenu - Attempting to add submenu twice"); - return -1; - } - } - - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_ID|MIIM_TYPE|MIIM_SUBMENU|MIIM_DATA; - mi.wID = (mData->mMenuID * PlatformPopupMenuData::PopupMenuIDRange) + mData->mLastID + 1; - if(title && *title) - mi.fType = MFT_STRING; - else - mi.fType = MFT_SEPARATOR; - mi.dwTypeData = (LPSTR)title; - mi.hSubMenu = submenu->mData->mMenu; - mi.dwItemData = (ULONG_PTR)submenu; - if(InsertMenuItemA(mData->mMenu, pos, TRUE, &mi)) - { - mSubmenus->addObject(submenu); - - if(isAttached) - { - pWindow->addAccelerators(submenu->mData->mAccelerators); - - HWND hWindow = pWindow->getHWND(); - DrawMenuBar(hWindow); - } - return mi.wID; - } - - return -1; -} - -bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator, const char *) -{ - Win32Window *pWindow = mCanvas ? dynamic_cast(mCanvas->getPlatformWindow()) : NULL; - bool isAttached = isAttachedToMenuBar(); - if(isAttached && pWindow == NULL) - return false; - - // Are we out of range? - if ( pos >= getItemCount() ) - return false; - - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_TYPE; - - if(title && *title) - mi.fType = MFT_STRING; - else - mi.fType = MFT_SEPARATOR; - - char buf[1024]; - if(accelerator && *accelerator) - { - dSprintf(buf, sizeof(buf), "%s\t%s", title, accelerator); - - if(isAttached) - pWindow->removeAccelerators(mData->mAccelerators); - - // Build entry for accelerator table - EventDescriptor accelDesc; - if(ActionMap::createEventDescriptor(accelerator, &accelDesc)) - mData->insertAccelerator(accelDesc, pos); - else - Con::errorf("PopupMenu::setItem - Could not create event descriptor for accelerator \"%s\"", accelerator); - - if(isAttached) - pWindow->addAccelerators(mData->mAccelerators); - } - else - dSprintf(buf, sizeof(buf), "%s", title); - - mi.dwTypeData = (LPSTR)buf; - - if(SetMenuItemInfoA(mData->mMenu, pos, TRUE, &mi)) - { - if(isAttached) - { - HWND hWindow = pWindow->getHWND(); - DrawMenuBar(hWindow); - } - - return true; - } - - return false; -} - -void PopupMenu::removeItem(S32 itemPos) -{ - Win32Window *pWindow = mCanvas ? dynamic_cast(mCanvas->getPlatformWindow()) : NULL; - bool isAttached = isAttachedToMenuBar(); - if(isAttached && pWindow == NULL) - return; - - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_DATA|MIIM_ID; - if(GetMenuItemInfoA(mData->mMenu, itemPos, TRUE, &mi)) - { - bool submenu = false; - - // Update list of submenus if this is a submenu - if(mi.fMask & MIIM_DATA) - { - PopupMenu *mnu = (PopupMenu *)mi.dwItemData; - if( mnu != NULL ) - { - if(isAttached) - pWindow->removeAccelerators(mnu->mData->mAccelerators); - mSubmenus->removeObject(mnu); - - submenu = true; - } - } - - if(! submenu) - { - // Update accelerators if this has an accelerator and wasn't a sub menu - for(S32 i = 0;i < mData->mAccelerators.size();++i) - { - if(mData->mAccelerators[i].mID == mi.wID) - { - if(isAttached) - pWindow->removeAccelerators(mData->mAccelerators); - - mData->mAccelerators.erase(i); - - if(isAttached) - pWindow->addAccelerators(mData->mAccelerators); - - break; - } - } - } - } - else - return; - - RemoveMenu(mData->mMenu, itemPos, MF_BYPOSITION); - - if(isAttached) - { - HWND hWindow = pWindow->getHWND(); - DrawMenuBar(hWindow); - } -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::enableItem( S32 pos, bool enable ) -{ - U32 flags = enable ? MF_ENABLED : MF_GRAYED; - EnableMenuItem( mData->mMenu, pos, MF_BYPOSITION|flags ); - - // Update accelerators. - - // NOTE: This really DOES need to happen. A disabled menu item - // should not still have an accelerator mapped to it. - // - // Unfortunately, the editors currently only set menu items - // enabled/disabled when the menu itself is selected which means our - // accelerators would be out of synch. - - /* - Win32Window *pWindow = mCanvas ? dynamic_cast( mCanvas->getPlatformWindow() ) : NULL; - bool isAttached = isAttachedToMenuBar(); - if ( isAttached && pWindow == NULL ) - return; - - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_DATA|MIIM_ID; - if ( !GetMenuItemInfoA( mData->mMenu, pos, TRUE, &mi) ) - return; - - if ( isAttached ) - pWindow->removeAccelerators( mData->mAccelerators ); - - mData->setAccelleratorEnabled( mi.wID, enable ); - - if ( isAttached ) - pWindow->addAccelerators( mData->mAccelerators ); - */ -} - -void PopupMenu::checkItem(S32 pos, bool checked) -{ -// U32 flags = checked ? MF_CHECKED : MF_UNCHECKED; -// CheckMenuItem(mData->mMenu, pos, MF_BYPOSITION|flags); - - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_STATE; - mi.fState = checked ? MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfoA(mData->mMenu, pos, TRUE, &mi); -} - -void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos) -{ - CheckMenuRadioItem(mData->mMenu, firstPos, lastPos, checkPos, MF_BYPOSITION); -} - -bool PopupMenu::isItemChecked(S32 pos) -{ - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_STATE; - if(GetMenuItemInfoA(mData->mMenu, pos, TRUE, &mi) && (mi.fState & MFS_CHECKED)) - return true; - return false; -} - -U32 PopupMenu::getItemCount() -{ - return GetMenuItemCount( mData->mMenu ); -} - -////////////////////////////////////////////////////////////////////////// - -bool PopupMenu::canHandleID(U32 id) -{ - for(S32 i = 0;i < mSubmenus->size();i++) - { - PopupMenu *subM = dynamic_cast((*mSubmenus)[i]); - if(subM == NULL) - continue; - - if(subM->canHandleID(id)) - return true; - } - - if(id >= mData->mMenuID * PlatformPopupMenuData::PopupMenuIDRange && - id < (mData->mMenuID+1) * PlatformPopupMenuData::PopupMenuIDRange) - { - return true; - } - - return false; -} - -bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */) -{ - // [tom, 8/20/2006] Pass off to a sub menu if it's for them - for(S32 i = 0;i < mSubmenus->size();i++) - { - PopupMenu *subM = dynamic_cast((*mSubmenus)[i]); - if(subM == NULL) - continue; - - if(subM->canHandleID(command)) - { - return subM->handleSelect(command, text); - } - } - - // [tom, 8/21/2006] Cheesey hack to find the position based on ID - char buf[512]; - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.dwTypeData = NULL; - - S32 numItems = GetMenuItemCount(mData->mMenu); - S32 pos = -1; - for(S32 i = 0;i < numItems;i++) - { - mi.fMask = MIIM_ID|MIIM_STRING|MIIM_STATE; - if(GetMenuItemInfoA(mData->mMenu, i, TRUE, &mi)) - { - if(mi.wID == command) - { - if(text == NULL) - { - mi.dwTypeData = buf; - mi.cch++; - GetMenuItemInfoA(mData->mMenu, i, TRUE, &mi); - - // [tom, 5/11/2007] Don't do anything if the menu item is disabled - if(mi.fState & MFS_DISABLED) - return false; - - text = StringTable->insert(mi.dwTypeData); - } - pos = i; - break; - } - } - } - - if(pos == -1) - { - Con::errorf("PopupMenu::handleSelect - Could not find menu item position for ID %d ... this shouldn't happen!", command); - return false; - } - - // [tom, 8/20/2006] Wasn't handled by a submenu, pass off to script - return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(pos), text ? text : "")); -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */) -{ - if( owner == NULL ) - { - Con::warnf("PopupMenu::showPopup - Invalid canvas supplied!"); - return; - } - - // [tom, 6/4/2007] showPopup() blocks until the menu is closed by the user, - // so the canvas pointer is not needed beyond the scope of this function - // when working with context menus. Setting mCanvas here will cause undesired - // behavior in relation to the menu bar. - - Win32Window *pWindow = dynamic_cast(owner->getPlatformWindow()); - if(pWindow == NULL) - return; - HWND hWindow = pWindow->getHWND(); - POINT p; - if(x == -1 && y == -1) - GetCursorPos(&p); - else - { - p.x = x; - p.y = y; - ClientToScreen(hWindow, &p); - } - - winState.renderThreadBlocked = true; - U32 opt = (int)TrackPopupMenu(mData->mMenu, TPM_NONOTIFY|TPM_RETURNCMD, p.x, p.y, 0, hWindow, NULL); - if(opt > 0) - handleSelect(opt, NULL); - winState.renderThreadBlocked = false; -} - -////////////////////////////////////////////////////////////////////////// - -void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos, const char *title) -{ - if(owner == NULL || isAttachedToMenuBar()) - return; - - // This is set for sub-menus in the onAttachToMenuBar() callback - mCanvas = owner; - - Win32Window *pWindow = dynamic_cast(owner->getPlatformWindow()); - if(pWindow == NULL) - return; - - HMENU hWindowMenu = pWindow->getMenuHandle(); - if(hWindowMenu == NULL) - { - hWindowMenu = CreateMenu(); - if(hWindowMenu) - { - pWindow->setMenuHandle( hWindowMenu); - } - } - - MENUITEMINFOA mii; - - mii.cbSize = sizeof(MENUITEMINFOA); - - mii.fMask = MIIM_STRING|MIIM_DATA; - mii.dwTypeData = (LPSTR)title; - mii.fMask |= MIIM_ID; - mii.wID = mData->mMenuID; - mii.fMask |= MIIM_SUBMENU; - mii.hSubMenu = mData->mMenu; - mii.dwItemData = (ULONG_PTR)this; - - InsertMenuItemA(hWindowMenu, pos, TRUE, &mii); - - HWND hWindow = pWindow->getHWND(); - DrawMenuBar(hWindow); - - pWindow->addAccelerators(mData->mAccelerators); - - // Add accelerators for sub menus - for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i) - { - PopupMenu *submenu = dynamic_cast(*i); - if(submenu == NULL) - continue; - - pWindow->addAccelerators(submenu->mData->mAccelerators); - } - - onAttachToMenuBar(owner, pos, title); -} - -// New version of above for use by MenuBar class. Do not use yet. -void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos) -{ - Win32Window *pWindow = dynamic_cast(owner->getPlatformWindow()); - if(pWindow == NULL) - return; - - //When playing a journal, the system menu is not actually shown - if (Journal::IsPlaying()) - { - onAttachToMenuBar(owner, pos, mBarTitle); - return; - } - - HMENU hWindowMenu = pWindow->getMenuHandle(); - - MENUITEMINFOA mii; - - mii.cbSize = sizeof(MENUITEMINFOA); - - mii.fMask = MIIM_STRING|MIIM_DATA; - mii.dwTypeData = (LPSTR)mBarTitle; - mii.fMask |= MIIM_ID; - mii.wID = mData->mMenuID; - mii.fMask |= MIIM_SUBMENU; - mii.hSubMenu = mData->mMenu; - mii.dwItemData = (ULONG_PTR)this; - - InsertMenuItemA(hWindowMenu, pos, TRUE, &mii); - - pWindow->addAccelerators(mData->mAccelerators); - - // Add accelerators for sub menus (have to do this here as it's platform specific) - for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i) - { - PopupMenu *submenu = dynamic_cast(*i); - if(submenu == NULL) - continue; - - pWindow->addAccelerators(submenu->mData->mAccelerators); - } - - onAttachToMenuBar(owner, pos, mBarTitle); -} - -void PopupMenu::removeFromMenuBar() -{ - S32 pos = getPosOnMenuBar(); - if(pos == -1) - return; - - Win32Window *pWindow = mCanvas ? dynamic_cast(mCanvas->getPlatformWindow()) : NULL; - if(pWindow == NULL) - return; - - HMENU hMenuHandle = pWindow->getMenuHandle(); - if(!hMenuHandle) - return; - - RemoveMenu(hMenuHandle, pos, MF_BYPOSITION); - - HWND hWindow = pWindow->getHWND(); - - DrawMenuBar(hWindow); - - pWindow->removeAccelerators(mData->mAccelerators); - - // Remove accelerators for sub menus - for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i) - { - PopupMenu *submenu = dynamic_cast(*i); - if(submenu == NULL) - continue; - - pWindow->removeAccelerators(submenu->mData->mAccelerators); - } - - onRemoveFromMenuBar(mCanvas); -} - -S32 PopupMenu::getPosOnMenuBar() -{ - if(mCanvas == NULL) - return -1; - - Win32Window *pWindow = mCanvas ? dynamic_cast(mCanvas->getPlatformWindow()) : NULL; - if(pWindow == NULL) - return -1; - - HMENU hMenuHandle = pWindow->getMenuHandle(); - S32 numItems = GetMenuItemCount(hMenuHandle); - S32 pos = -1; - for(S32 i = 0;i < numItems;i++) - { - MENUITEMINFOA mi; - mi.cbSize = sizeof(mi); - mi.fMask = MIIM_DATA; - if(GetMenuItemInfoA(hMenuHandle, i, TRUE, &mi)) - { - if(mi.fMask & MIIM_DATA) - { - PopupMenu *mnu = (PopupMenu *)mi.dwItemData; - if(mnu == this) - { - pos = i; - break; - } - } - } - } - - return pos; -} - -#endif \ No newline at end of file diff --git a/Engine/source/windowManager/sdl/sdlWindow.cpp b/Engine/source/windowManager/sdl/sdlWindow.cpp index a48e3743d..149825b98 100644 --- a/Engine/source/windowManager/sdl/sdlWindow.cpp +++ b/Engine/source/windowManager/sdl/sdlWindow.cpp @@ -27,7 +27,6 @@ #include "windowManager/sdl/sdlWindowMgr.h" #include "windowManager/sdl/sdlCursorController.h" #include "platformSDL/sdlInput.h" -#include "platform/menus/popupMenu.h" #include "platform/platformInput.h" #include "gfx/gfxDevice.h" diff --git a/Templates/BaseGame/game/tools/gui/guiDialogs.ed.cs b/Templates/BaseGame/game/tools/gui/guiDialogs.ed.cs index 696b98975..f2de82d96 100644 --- a/Templates/BaseGame/game/tools/gui/guiDialogs.ed.cs +++ b/Templates/BaseGame/game/tools/gui/guiDialogs.ed.cs @@ -35,5 +35,4 @@ exec("./GuiEaseEditDlg.ed.cs"); exec("./guiObjectInspector.ed.cs"); exec("./uvEditor.ed.gui"); exec("./objectSelection.ed.cs"); -exec("./guiPlatformGenericMenubar.ed.cs"); exec("./postFxManager.gui"); \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.cs b/Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.cs deleted file mode 100644 index 089b0b8fa..000000000 --- a/Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.cs +++ /dev/null @@ -1,19 +0,0 @@ -if(isClass(GuiPlatformGenericMenuBar)) -{ - exec("./guiPlatformGenericMenubar.ed.gui"); -} -else -{ - %guiContent = new GuiControl(PlatformGenericMenubar) { - profile = "GuiModelessDialogProfile"; - - new GuiControl() - { - internalName = "menubar"; - extent = "1024 20"; - minExtent = "320 20"; - horizSizing = "width"; - profile = "GuiMenuBarProfile"; - }; - }; -} \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.gui b/Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.gui deleted file mode 100644 index 8d2cbcd74..000000000 --- a/Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.gui +++ /dev/null @@ -1,14 +0,0 @@ -//--- OBJECT WRITE BEGIN --- -%guiContent = new GuiControl(PlatformGenericMenubar) { - profile = "GuiModelessDialogProfile"; - - new GuiPlatformGenericMenuBar() - { - internalName = "menubar"; - extent = "1024 20"; - minExtent = "320 20"; - horizSizing = "width"; - profile = "GuiMenuBarProfile"; - }; -}; -//--- OBJECT WRITE END --- \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs index 1305ae170..83317d0d8 100644 --- a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs +++ b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs @@ -66,9 +66,13 @@ function GuiEditCanvas::onCreateMenu(%this) } // Menu bar - %this.menuBar = new MenuBar() + %this.menuBar = new GuiMenuBar(GuiEditorMenubar) { dynamicItemInsertPos = 3; + extent = "1024 20"; + minExtent = "320 20"; + horizSizing = "width"; + profile = "GuiMenuBarProfile"; new PopupMenu() { diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs index f6e88eece..800229c8d 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs @@ -2043,7 +2043,7 @@ function EWorldEditor::syncGui( %this ) %this.syncToolPalette(); EditorTree.update(); - Editor.getUndoManager().updateUndoMenu( EditorGui.menuBar-->EditMenu ); + Editor.getUndoManager().updateUndoMenu( EditorGui.findMenu("Edit") ); EditorGuiStatusBar.setSelectionObjectsByCount( %this.getSelectionSize() ); EWTreeWindow-->LockSelection.setStateOn( %this.getSelectionLockCount() > 0 ); diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs b/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs index dbe978cab..b225d3534 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs @@ -110,9 +110,13 @@ function EditorGui::buildMenus(%this) }; // Menu bar - %this.menuBar = new MenuBar(WorldEditorMenubar) + %this.menuBar = new GuiMenuBar(WorldEditorMenubar) { dynamicItemInsertPos = 3; + extent = "1024 20"; + minExtent = "320 20"; + horizSizing = "width"; + profile = "GuiMenuBarProfile"; }; // File Menu @@ -158,7 +162,7 @@ function EditorGui::buildMenus(%this) %fileMenu.appendItem("Exit Level" TAB "" TAB "EditorExitMission();"); %fileMenu.appendItem("Quit" TAB %quitShortcut TAB "EditorQuitGame();"); - %this.menuBar.insert(%fileMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%fileMenu); // Edit Menu %editMenu = new PopupMenu() @@ -187,7 +191,7 @@ function EditorGui::buildMenus(%this) item[15] = "Game Options..." TAB "" TAB "Canvas.pushDialog(optionsDlg);"; item[16] = "PostEffect Manager" TAB "" TAB "Canvas.pushDialog(PostFXManager);"; }; - %this.menuBar.insert(%editMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%editMenu); // View Menu %viewMenu = new PopupMenu() @@ -201,7 +205,7 @@ function EditorGui::buildMenus(%this) item[ 0 ] = "Visibility Layers" TAB "Alt V" TAB "VisibilityDropdownToggle();"; item[ 1 ] = "Show Grid in Ortho Views" TAB %cmdCtrl @ "-Shift-Alt G" TAB "EditorGui.toggleOrthoGrid();"; }; - %this.menuBar.insert(%viewMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%viewMenu); // Camera Menu %cameraMenu = new PopupMenu() @@ -229,7 +233,7 @@ function EditorGui::buildMenus(%this) Item[15] = "Manage Bookmarks..." TAB "Ctrl-Shift B" TAB "EditorGui.toggleCameraBookmarkWindow();"; item[16] = "Jump to Bookmark" TAB %this.cameraBookmarksMenu; }; - %this.menuBar.insert(%cameraMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%cameraMenu); // Editors Menu %editorsMenu = new PopupMenu() @@ -246,7 +250,7 @@ function EditorGui::buildMenus(%this) //item[4] = "Terrain Painter" TAB "F4" TAB TerrainPainterPlugin; //item[5] = "-"; }; - %this.menuBar.insert(%editorsMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%editorsMenu); // Lighting Menu %lightingMenu = new PopupMenu() @@ -263,7 +267,7 @@ function EditorGui::buildMenus(%this) // NOTE: The light managers will be inserted as the // last menu items in EditorLightingMenu::onAdd(). }; - %this.menuBar.insert(%lightingMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%lightingMenu); // Tools Menu %toolsMenu = new PopupMenu() @@ -278,7 +282,7 @@ function EditorGui::buildMenus(%this) item[2] = "Torque SimView" TAB "" TAB "tree();"; item[3] = "Make Selected a Mesh" TAB "" TAB "makeSelectedAMesh();"; }; - %this.menuBar.insert(%toolsMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%toolsMenu); // Help Menu %helpMenu = new PopupMenu() @@ -293,7 +297,7 @@ function EditorGui::buildMenus(%this) item[2] = "Offline Reference Guide..." TAB "" TAB "shellexecute(EWorldEditor.documentationReference);"; item[3] = "Torque 3D Forums..." TAB "" TAB "gotoWebPage(EWorldEditor.forumURL);"; }; - %this.menuBar.insert(%helpMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%helpMenu); // Menus that are added/removed dynamically (temporary) @@ -398,9 +402,9 @@ function EditorGui::setMenuDefaultState(%this) if(! isObject(%this.menuBar)) return 0; - for(%i = 0;%i < %this.menuBar.getCount();%i++) + for(%i = 0;%i < %this.menuBar.getMenuCount();%i++) { - %menu = %this.menuBar.getObject(%i); + %menu = %this.menuBar.getMenu(%i); %menu.setupDefaultState(); } @@ -414,9 +418,10 @@ function EditorGui::findMenu(%this, %name) if(! isObject(%this.menuBar)) return 0; - for(%i = 0;%i < %this.menuBar.getCount();%i++) + + for(%i = 0; %i < %this.menuBar.getMenuCount(); %i++) { - %menu = %this.menuBar.getObject(%i); + %menu = %this.menuBar.getMenu(%i); if(%name $= %menu.barTitle) return %menu; diff --git a/Templates/Full/game/tools/gui/guiDialogs.ed.cs b/Templates/Full/game/tools/gui/guiDialogs.ed.cs index db09e8570..dc6b4e3a3 100644 --- a/Templates/Full/game/tools/gui/guiDialogs.ed.cs +++ b/Templates/Full/game/tools/gui/guiDialogs.ed.cs @@ -35,4 +35,3 @@ exec("./GuiEaseEditDlg.ed.cs"); exec("./guiObjectInspector.ed.cs"); exec("./uvEditor.ed.gui"); exec("./objectSelection.ed.cs"); -exec("./guiPlatformGenericMenubar.ed.cs"); diff --git a/Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.cs b/Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.cs deleted file mode 100644 index 089b0b8fa..000000000 --- a/Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.cs +++ /dev/null @@ -1,19 +0,0 @@ -if(isClass(GuiPlatformGenericMenuBar)) -{ - exec("./guiPlatformGenericMenubar.ed.gui"); -} -else -{ - %guiContent = new GuiControl(PlatformGenericMenubar) { - profile = "GuiModelessDialogProfile"; - - new GuiControl() - { - internalName = "menubar"; - extent = "1024 20"; - minExtent = "320 20"; - horizSizing = "width"; - profile = "GuiMenuBarProfile"; - }; - }; -} \ No newline at end of file diff --git a/Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.gui b/Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.gui deleted file mode 100644 index 8d2cbcd74..000000000 --- a/Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.gui +++ /dev/null @@ -1,14 +0,0 @@ -//--- OBJECT WRITE BEGIN --- -%guiContent = new GuiControl(PlatformGenericMenubar) { - profile = "GuiModelessDialogProfile"; - - new GuiPlatformGenericMenuBar() - { - internalName = "menubar"; - extent = "1024 20"; - minExtent = "320 20"; - horizSizing = "width"; - profile = "GuiMenuBarProfile"; - }; -}; -//--- OBJECT WRITE END --- \ No newline at end of file diff --git a/Templates/Full/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs b/Templates/Full/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs index 1305ae170..83317d0d8 100644 --- a/Templates/Full/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs +++ b/Templates/Full/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs @@ -66,9 +66,13 @@ function GuiEditCanvas::onCreateMenu(%this) } // Menu bar - %this.menuBar = new MenuBar() + %this.menuBar = new GuiMenuBar(GuiEditorMenubar) { dynamicItemInsertPos = 3; + extent = "1024 20"; + minExtent = "320 20"; + horizSizing = "width"; + profile = "GuiMenuBarProfile"; new PopupMenu() { diff --git a/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs index bc1905292..535d00880 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs @@ -2017,7 +2017,7 @@ function EWorldEditor::syncGui( %this ) %this.syncToolPalette(); EditorTree.update(); - Editor.getUndoManager().updateUndoMenu( EditorGui.menuBar-->EditMenu ); + Editor.getUndoManager().updateUndoMenu( EditorGui.findMenu("Edit") ); EditorGuiStatusBar.setSelectionObjectsByCount( %this.getSelectionSize() ); EWTreeWindow-->LockSelection.setStateOn( %this.getSelectionLockCount() > 0 ); diff --git a/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs b/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs index dbe978cab..b225d3534 100644 --- a/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs +++ b/Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs @@ -110,9 +110,13 @@ function EditorGui::buildMenus(%this) }; // Menu bar - %this.menuBar = new MenuBar(WorldEditorMenubar) + %this.menuBar = new GuiMenuBar(WorldEditorMenubar) { dynamicItemInsertPos = 3; + extent = "1024 20"; + minExtent = "320 20"; + horizSizing = "width"; + profile = "GuiMenuBarProfile"; }; // File Menu @@ -158,7 +162,7 @@ function EditorGui::buildMenus(%this) %fileMenu.appendItem("Exit Level" TAB "" TAB "EditorExitMission();"); %fileMenu.appendItem("Quit" TAB %quitShortcut TAB "EditorQuitGame();"); - %this.menuBar.insert(%fileMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%fileMenu); // Edit Menu %editMenu = new PopupMenu() @@ -187,7 +191,7 @@ function EditorGui::buildMenus(%this) item[15] = "Game Options..." TAB "" TAB "Canvas.pushDialog(optionsDlg);"; item[16] = "PostEffect Manager" TAB "" TAB "Canvas.pushDialog(PostFXManager);"; }; - %this.menuBar.insert(%editMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%editMenu); // View Menu %viewMenu = new PopupMenu() @@ -201,7 +205,7 @@ function EditorGui::buildMenus(%this) item[ 0 ] = "Visibility Layers" TAB "Alt V" TAB "VisibilityDropdownToggle();"; item[ 1 ] = "Show Grid in Ortho Views" TAB %cmdCtrl @ "-Shift-Alt G" TAB "EditorGui.toggleOrthoGrid();"; }; - %this.menuBar.insert(%viewMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%viewMenu); // Camera Menu %cameraMenu = new PopupMenu() @@ -229,7 +233,7 @@ function EditorGui::buildMenus(%this) Item[15] = "Manage Bookmarks..." TAB "Ctrl-Shift B" TAB "EditorGui.toggleCameraBookmarkWindow();"; item[16] = "Jump to Bookmark" TAB %this.cameraBookmarksMenu; }; - %this.menuBar.insert(%cameraMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%cameraMenu); // Editors Menu %editorsMenu = new PopupMenu() @@ -246,7 +250,7 @@ function EditorGui::buildMenus(%this) //item[4] = "Terrain Painter" TAB "F4" TAB TerrainPainterPlugin; //item[5] = "-"; }; - %this.menuBar.insert(%editorsMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%editorsMenu); // Lighting Menu %lightingMenu = new PopupMenu() @@ -263,7 +267,7 @@ function EditorGui::buildMenus(%this) // NOTE: The light managers will be inserted as the // last menu items in EditorLightingMenu::onAdd(). }; - %this.menuBar.insert(%lightingMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%lightingMenu); // Tools Menu %toolsMenu = new PopupMenu() @@ -278,7 +282,7 @@ function EditorGui::buildMenus(%this) item[2] = "Torque SimView" TAB "" TAB "tree();"; item[3] = "Make Selected a Mesh" TAB "" TAB "makeSelectedAMesh();"; }; - %this.menuBar.insert(%toolsMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%toolsMenu); // Help Menu %helpMenu = new PopupMenu() @@ -293,7 +297,7 @@ function EditorGui::buildMenus(%this) item[2] = "Offline Reference Guide..." TAB "" TAB "shellexecute(EWorldEditor.documentationReference);"; item[3] = "Torque 3D Forums..." TAB "" TAB "gotoWebPage(EWorldEditor.forumURL);"; }; - %this.menuBar.insert(%helpMenu, %this.menuBar.getCount()); + %this.menuBar.insert(%helpMenu); // Menus that are added/removed dynamically (temporary) @@ -398,9 +402,9 @@ function EditorGui::setMenuDefaultState(%this) if(! isObject(%this.menuBar)) return 0; - for(%i = 0;%i < %this.menuBar.getCount();%i++) + for(%i = 0;%i < %this.menuBar.getMenuCount();%i++) { - %menu = %this.menuBar.getObject(%i); + %menu = %this.menuBar.getMenu(%i); %menu.setupDefaultState(); } @@ -414,9 +418,10 @@ function EditorGui::findMenu(%this, %name) if(! isObject(%this.menuBar)) return 0; - for(%i = 0;%i < %this.menuBar.getCount();%i++) + + for(%i = 0; %i < %this.menuBar.getMenuCount(); %i++) { - %menu = %this.menuBar.getObject(%i); + %menu = %this.menuBar.getMenu(%i); if(%name $= %menu.barTitle) return %menu;