Refactors the Popup menus and GuiMenuBars to remove unneeded duplication and platform-specific/deprecated code.

This commit is contained in:
Areloch 2017-11-11 01:21:48 -06:00
parent fafc2929e0
commit 2ca6af8e48
29 changed files with 1343 additions and 5870 deletions

View file

@ -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<GuiMenuBar*>(oldMenuBar->findObjectByInternalName( ste, true));
if( menu )
menu->removeWindowAcceleratorMap( *getPlatformWindow()->getInputGenerator() );
GuiMenuBar* oldMenu = dynamic_cast<GuiMenuBar*>(oldMenuBar);
GuiMenuBar* newMenu = dynamic_cast<GuiMenuBar*>(mMenuBarCtrl);
menu = !mMenuBarCtrl ? NULL : dynamic_cast<GuiMenuBar*>(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<const GuiControl*>(menu), "");
AssertFatal( dynamic_cast<const GuiControl*>(menu), "");*/
const U32 yOffset = static_cast<const GuiControl*>(menu)->getExtent().y;
newPos.y += yOffset;
newExt.y -= yOffset;
const U32 yOffset = static_cast<const GuiMenuBar*>(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()

View file

@ -210,6 +210,7 @@ public:
virtual void onRemove();
void setMenuBar(SimObject *obj);
SimObject* getMenuBar() { return mMenuBarCtrl; }
static void initPersistFields();

File diff suppressed because it is too large Load diff

View file

@ -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<Menu*> mMenuList;
Menu *mouseDownMenu;
Menu *mouseOverMenu;
StringTableEntry text;
PopupMenu* popupMenu;
};
Vector<MenuEntry> 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

View file

@ -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));
}
}
}

View file

@ -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<PopupMenu*> mPopups;
GuiMenuBar* mMenuBarCtrl;
};
#endif

View file

@ -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<PopupMenu *>(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<GuiCanvas*>(Sim::findObject(canvasName));
object->showPopup(pCanvas, x, y);
}

View file

@ -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<GuiCanvas> mCanvas;
Vector<MenuItem> 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_

View file

@ -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<PopupMenu *>(obj));
}
void MenuBar::removeObject(SimObject *obj)
{
Parent::removeObject(obj);
updateMenuBar(dynamic_cast<PopupMenu *>(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<PopupMenu *>(obj));
}
void MenuBar::pushObject(SimObject *obj)
{
Parent::pushObject(obj);
updateMenuBar(dynamic_cast<PopupMenu *>(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<PopupMenu *>(obj));
return ret;
}
//-----------------------------------------------------------------------------
// Console Methods
//-----------------------------------------------------------------------------
DefineConsoleMethod(MenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)")
{
object->attachToCanvas(dynamic_cast<GuiCanvas*>(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);
}

View file

@ -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_

View file

@ -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<PopupMenu *>(*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<PopupMenu *>(*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<PopupMenu *>(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<GuiCanvas*>(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<GuiCanvas*>(Sim::findObject(canvasName));
object->showPopup(pCanvas, x, y);
}

View file

@ -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<GuiMenuBar::Menu*, PopupMenu*> 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

View file

@ -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<CompoundKey<U32, U32>, String> mCmds;
};

View file

@ -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<GuiMenuBar::Menu*, PopupMenu*> 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<GuiPlatformGenericMenuBar*>( 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<PlatformWindowSDL*>(owner->getPlatformWindow());
if(pWindow == NULL)
return;
// Setup the native menu bar
GuiMenuBar *hWindowMenu = static_cast<GuiMenuBar*>( 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<PopupMenu *>(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<PopupMenu *>(at(i));
if (mnu == NULL)
{
Con::warnf("MenuBar::removeFromMenuBar - Non-PopupMenu object in set");
continue;
}
mnu->removeFromMenuBar();
}
mCanvas->setMenuBar(NULL);
mCanvas = NULL;
}
#endif

View file

@ -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<GuiPlatformGenericMenuBar*>(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<GuiPopupMenuTextListCtrl*>(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

View file

@ -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<PopupMenu *>(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<Win32Window*>(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<Win32Window*>(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<PopupMenu *>(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<Win32Window*>(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<PopupMenu *>(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

View file

@ -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<Win32Window*>(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<Win32Window*>(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<Win32Window*>(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<Win32Window*>(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<Win32Window*>( 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<PopupMenu *>((*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<PopupMenu *>((*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<Win32Window*>(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<Win32Window*>(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<PopupMenu *>(*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<Win32Window*>(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<PopupMenu *>(*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<Win32Window*>(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<PopupMenu *>(*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<Win32Window*>(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

View file

@ -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"

View file

@ -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");

View file

@ -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";
};
};
}

View file

@ -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 ---

View file

@ -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()
{

View file

@ -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 );

View file

@ -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;

View file

@ -35,4 +35,3 @@ exec("./GuiEaseEditDlg.ed.cs");
exec("./guiObjectInspector.ed.cs");
exec("./uvEditor.ed.gui");
exec("./objectSelection.ed.cs");
exec("./guiPlatformGenericMenubar.ed.cs");

View file

@ -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";
};
};
}

View file

@ -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 ---

View file

@ -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()
{

File diff suppressed because it is too large Load diff