guiMenuBar.cpp
Engine/source/gui/editor/guiMenuBar.cpp
Public Functions
ConsoleDocClass(GuiMenuBar , "@brief GUI Control which displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> horizontal bar with individual drop-down menu items. Each menu item may also have submenu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguimenubar/">GuiMenuBar</a>(newMenuBar)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " Padding = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "// Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bar\n</a>" "newMenuBar.addMenu(0,\"New Menu\");\n\n" "// Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the New <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Menu\n</a>" "newMenuBar.addMenuItem(0,\"New Menu Item\",0,\"n\",-1);\n\n" "// Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> submenu item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the New Menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Item\n</a>" "newMenuBar.addSubmenuItem(0,1,\"New Submenu Item\",0,\"s\",-1);\n" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCore\n</a>" )
DefineEngineMethod(GuiMenuBar , attachToCanvas , void , (const char *canvas, S32 pos) , "(GuiCanvas, pos)" )
DefineEngineMethod(GuiMenuBar , findMenu , S32 , (const char *barTitle) , ("") , "(barTitle)" )
DefineEngineMethod(GuiMenuBar , getMenu , S32 , (S32 index) , (0) , "(Index)" )
DefineEngineMethod(GuiMenuBar , getMenuCount , S32 , () , "()" )
DefineEngineMethod(GuiMenuBar , insert , void , (SimObject *pObject, S32 pos) , (nullAsType< SimObject * >(), -1) , "(object, pos) insert object at position" )
DefineEngineMethod(GuiMenuBar , removeFromCanvas , void , () , "()" )
IMPLEMENT_CALLBACK(GuiMenuBar , onMenuItemSelect , void , (S32 menuId, const char *menuText, S32 menuItemId, const char *menuItemText) , (menuId, menuText, menuItemId, menuItemText) , "@brief Called whenever an item in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selected.\n\n</a>" "@param menuId Index <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the menu which contains the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n</a>" "@param menuText Text of the menu which contains the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n\n</a>" "@param menuItemId Index <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n</a>" "@param menuItemText Text of the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// A menu item has been selected, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "GuiMenuBar::onMenuItemSelect(%this,%menuId,%menuText,%menuItemId,%menuItemText)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run when the callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" )
IMPLEMENT_CALLBACK(GuiMenuBar , onMenuSelect , void , (S32 menuId, const char *menuText) , (menuId, menuText) , "@brief Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selected.\n\n</a>" "@param menuId Index <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the clicked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu\n</a>" "@param menuText Text of the clicked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// A menu has been selected, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "GuiMenuBar::onMenuSelect(%this,%menuId,%menuText)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run when the callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" )
IMPLEMENT_CALLBACK(GuiMenuBar , onMouseInMenu , void , (bool isInMenu) , (isInMenu) , "@brief Called whenever the mouse enters, or persists is in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu.\n\n</a>" " @param isInMenu True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the mouse has entered the menu, otherwise is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">false.\n</a>" " @note To receive this callback, call setProcessTicks(true) on the menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bar.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Mouse enters or persists within the menu, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "GuiMenuBar::onMouseInMenu(%this,%hasLeftMenu)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run when the callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" )
Detailed Description
Public Functions
ConsoleDocClass(GuiMenuBar , "@brief GUI Control which displays <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> horizontal bar with individual drop-down menu items. Each menu item may also have submenu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">items.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguimenubar/">GuiMenuBar</a>(newMenuBar)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " Padding = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "// Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bar\n</a>" "newMenuBar.addMenu(0,\"New Menu\");\n\n" "// Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the New <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Menu\n</a>" "newMenuBar.addMenuItem(0,\"New Menu Item\",0,\"n\",-1);\n\n" "// Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> submenu item <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the New Menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Item\n</a>" "newMenuBar.addSubmenuItem(0,1,\"New Submenu Item\",0,\"s\",-1);\n" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiCore\n</a>" )
DefineEngineMethod(GuiMenuBar , attachToCanvas , void , (const char *canvas, S32 pos) , "(GuiCanvas, pos)" )
DefineEngineMethod(GuiMenuBar , findMenu , S32 , (const char *barTitle) , ("") , "(barTitle)" )
DefineEngineMethod(GuiMenuBar , getMenu , S32 , (S32 index) , (0) , "(Index)" )
DefineEngineMethod(GuiMenuBar , getMenuCount , S32 , () , "()" )
DefineEngineMethod(GuiMenuBar , insert , void , (SimObject *pObject, S32 pos) , (nullAsType< SimObject * >(), -1) , "(object, pos) insert object at position" )
DefineEngineMethod(GuiMenuBar , removeFromCanvas , void , () , "()" )
IMPLEMENT_CALLBACK(GuiMenuBar , onMenuItemSelect , void , (S32 menuId, const char *menuText, S32 menuItemId, const char *menuItemText) , (menuId, menuText, menuItemId, menuItemText) , "@brief Called whenever an item in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selected.\n\n</a>" "@param menuId Index <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the menu which contains the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n</a>" "@param menuText Text of the menu which contains the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n\n</a>" "@param menuItemId Index <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n</a>" "@param menuItemText Text of the selected menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">item\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// A menu item has been selected, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "GuiMenuBar::onMenuItemSelect(%this,%menuId,%menuText,%menuItemId,%menuItemText)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run when the callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" )
IMPLEMENT_CALLBACK(GuiMenuBar , onMenuSelect , void , (S32 menuId, const char *menuText) , (menuId, menuText) , "@brief Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> menu is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selected.\n\n</a>" "@param menuId Index <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the clicked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu\n</a>" "@param menuText Text of the clicked <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// A menu has been selected, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "GuiMenuBar::onMenuSelect(%this,%menuId,%menuText)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run when the callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" )
IMPLEMENT_CALLBACK(GuiMenuBar , onMouseInMenu , void , (bool isInMenu) , (isInMenu) , "@brief Called whenever the mouse enters, or persists is in the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu.\n\n</a>" " @param isInMenu True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the mouse has entered the menu, otherwise is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">false.\n</a>" " @note To receive this callback, call setProcessTicks(true) on the menu <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bar.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Mouse enters or persists within the menu, causing the callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occur.\n</a>" "GuiMenuBar::onMouseInMenu(%this,%hasLeftMenu)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Code <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> run when the callback <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">occurs\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiTickCtrl\n\n</a>" )
IMPLEMENT_CONOBJECT(GuiMenuBar )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "gui/editor/guiMenuBar.h" 26 27#include "console/consoleTypes.h" 28#include "console/console.h" 29#include "gui/core/guiCanvas.h" 30#include "gui/core/guiDefaultControlRender.h" 31#include "gui/controls/guiTextListCtrl.h" 32#include "sim/actionMap.h" 33#include "gfx/gfxDevice.h" 34#include "gfx/gfxDrawUtil.h" 35#include "gfx/primBuilder.h" 36#include "console/engineAPI.h" 37#include "gui/editor/guiPopupMenuCtrl.h" 38 39// menu bar: 40// basic idea - fixed height control bar at the top of a window, placed and sized in gui editor 41// menu text for menus or menu items should not begin with a digit 42// all menus can be removed via the clearMenus() console command 43// each menu is added via the addMenu(menuText, menuId) console command 44// each menu is added with a menu id 45// menu items are added to menus via that addMenuItem(menu, menuItemText, menuItemId, accelerator, checkGroup) console command 46// each menu item is added with a menu item id and an optional accelerator 47// menu items are initially enabled, but can be disabled/re-enabled via the setMenuItemEnable(menu,menuItem,bool) 48// menu text can be set via the setMenuText(menu, newMenuText) console method 49// menu item text can be set via the setMenuItemText console method 50// menu items can be removed via the removeMenuItem(menu, menuItem) console command 51// menu items can be cleared via the clearMenuItems(menu) console command 52// menus can be hidden or shown via the setMenuVisible(menu, bool) console command 53// menu items can be hidden or shown via the setMenuItemVisible(menu, menuItem, bool) console command 54// menu items can be check'd via the setMenuItemChecked(menu, menuItem, bool) console command 55// if the bool is true, any other items in that menu item's check group become unchecked. 56// 57// menu items can have a bitmap set on them via the setMenuItemBitmap(menu, menuItem, bitmapIndex) 58// passing -1 for the bitmap index will result in no bitmap being shown 59// the index paramater is an index into the bitmap array of the associated profile 60// this can be used, for example, to display a check next to a selected menu item 61// bitmap indices are actually multiplied by 3 when indexing into the bitmap 62// since bitmaps have normal, selected and disabled states. 63// 64// menus can be removed via the removeMenu console command 65// specification arguments for menus and menu items can be either the id or the text of the menu or menu item 66// adding the menu item "-" will add an un-selectable seperator to the menu 67// callbacks: 68// when a menu is clicked, before it is displayed, the menu calls its onMenuSelect(menuId, menuText) method - 69// this allows the callback to enable/disable menu items, or add menu items in a context-sensitive way 70// when a menu item is clicked, the menu removes itself from display, then calls onMenuItemSelect(menuId, menuText, menuItemId, menuItemText) 71 72// the initial implementation does not support: 73// hierarchal menus 74// keyboard accelerators on menu text (i.e. via alt-key combos) 75 76//------------------------------------------------------------------------------ 77 78IMPLEMENT_CONOBJECT(GuiMenuBar); 79 80ConsoleDocClass( GuiMenuBar, 81 "@brief GUI Control which displays a horizontal bar with individual drop-down menu items. Each menu item may also have submenu items.\n\n" 82 83 "@tsexample\n" 84 "new GuiMenuBar(newMenuBar)\n" 85 "{\n" 86 " Padding = \"0\";\n" 87 " //Properties not specific to this control have been omitted from this example.\n" 88 "};\n\n" 89 "// Add a menu to the menu bar\n" 90 "newMenuBar.addMenu(0,\"New Menu\");\n\n" 91 "// Add a menu item to the New Menu\n" 92 "newMenuBar.addMenuItem(0,\"New Menu Item\",0,\"n\",-1);\n\n" 93 "// Add a submenu item to the New Menu Item\n" 94 "newMenuBar.addSubmenuItem(0,1,\"New Submenu Item\",0,\"s\",-1);\n" 95 "@endtsexample\n\n" 96 97 "@see GuiTickCtrl\n\n" 98 99 "@ingroup GuiCore\n" 100); 101 102IMPLEMENT_CALLBACK( GuiMenuBar, onMouseInMenu, void, (bool isInMenu),( isInMenu ), 103 "@brief Called whenever the mouse enters, or persists is in the menu.\n\n" 104 "@param isInMenu True if the mouse has entered the menu, otherwise is false.\n" 105 "@note To receive this callback, call setProcessTicks(true) on the menu bar.\n" 106 "@tsexample\n" 107 "// Mouse enters or persists within the menu, causing the callback to occur.\n" 108 "GuiMenuBar::onMouseInMenu(%this,%hasLeftMenu)\n" 109 "{\n" 110 " // Code to run when the callback occurs\n" 111 "}\n" 112 "@endtsexample\n\n" 113 "@see GuiTickCtrl\n\n" 114); 115 116IMPLEMENT_CALLBACK( GuiMenuBar, onMenuSelect, void, ( S32 menuId, const char* menuText ),( menuId , menuText ), 117 "@brief Called whenever a menu is selected.\n\n" 118 "@param menuId Index id of the clicked menu\n" 119 "@param menuText Text of the clicked menu\n\n" 120 "@tsexample\n" 121 "// A menu has been selected, causing the callback to occur.\n" 122 "GuiMenuBar::onMenuSelect(%this,%menuId,%menuText)\n" 123 "{\n" 124 " // Code to run when the callback occurs\n" 125 "}\n" 126 "@endtsexample\n\n" 127 "@see GuiTickCtrl\n\n" 128); 129 130IMPLEMENT_CALLBACK( GuiMenuBar, onMenuItemSelect, void, ( S32 menuId, const char* menuText, S32 menuItemId, const char* menuItemText ), 131 ( menuId, menuText, menuItemId, menuItemText ), 132 "@brief Called whenever an item in a menu is selected.\n\n" 133 "@param menuId Index id of the menu which contains the selected menu item\n" 134 "@param menuText Text of the menu which contains the selected menu item\n\n" 135 "@param menuItemId Index id of the selected menu item\n" 136 "@param menuItemText Text of the selected menu item\n\n" 137 "@tsexample\n" 138 "// A menu item has been selected, causing the callback to occur.\n" 139 "GuiMenuBar::onMenuItemSelect(%this,%menuId,%menuText,%menuItemId,%menuItemText)\n" 140 "{\n" 141 " // Code to run when the callback occurs\n" 142 "}\n" 143 "@endtsexample\n\n" 144 "@see GuiTickCtrl\n\n" 145); 146 147//------------------------------------------------------------------------------ 148// console methods 149//------------------------------------------------------------------------------ 150 151/*DefineEngineMethod( GuiMenuBar, clearMenus, void, (),, 152 "@brief Clears all the menus from the menu bar.\n\n" 153 "@tsexample\n" 154 "// Inform the GuiMenuBar control to clear all menus from itself.\n" 155 "%thisGuiMenuBar.clearMenus();\n" 156 "@endtsexample\n\n" 157 "@see GuiTickCtrl") 158{ 159 object->clearMenus(); 160} 161 162DefineEngineMethod( GuiMenuBar, setMenuMargins, void, (S32 horizontalMargin, S32 verticalMargin, S32 bitmapToTextSpacing),, 163 "@brief Sets the menu rendering margins: horizontal, vertical, bitmap spacing.\n\n" 164 "Detailed description\n\n" 165 "@param horizontalMargin Number of pixels on the left and right side of a menu's text.\n" 166 "@param verticalMargin Number of pixels on the top and bottom of a menu's text.\n" 167 "@param bitmapToTextSpacing Number of pixels between a menu's bitmap and text.\n" 168 "@tsexample\n" 169 "// Define the horizontalMargin\n" 170 "%horizontalMargin = \"5\";\n\n" 171 "// Define the verticalMargin\n" 172 "%verticalMargin = \"5\";\n\n" 173 "// Define the bitmapToTextSpacing\n" 174 "%bitmapToTextSpacing = \"12\";\n\n" 175 "// Inform the GuiMenuBar control to set its margins based on the defined values.\n" 176 "%thisGuiMenuBar.setMenuMargins(%horizontalMargin,%verticalMargin,%bitmapToTextSpacing);\n" 177 "@endtsexample\n\n" 178 "@see GuiTickCtrl") 179{ 180 object->mHorizontalMargin = horizontalMargin; 181 object->mVerticalMargin = verticalMargin; 182 object->mBitmapMargin = bitmapToTextSpacing; 183} 184 185DefineEngineMethod(GuiMenuBar, addMenu, void, (const char* menuText, S32 menuId),, 186 "@brief Adds a new menu to the menu bar.\n\n" 187 "@param menuText Text to display for the new menu item.\n" 188 "@param menuId ID for the new menu item.\n" 189 "@tsexample\n" 190 "// Define the menu text\n" 191 "%menuText = \"New Menu\";\n\n" 192 "// Define the menu ID.\n" 193 "%menuId = \"2\";\n\n" 194 "// Inform the GuiMenuBar control to add the new menu\n" 195 "%thisGuiMenuBar.addMenu(%menuText,%menuId);\n" 196 "@endtsexample\n\n" 197 "@see GuiTickCtrl") 198{ 199 if(dIsdigit(menuText[0])) 200 { 201 Con::errorf("Cannot add menu %s (id = %s). First character of a menu's text cannot be a digit.", menuText, menuId); 202 return; 203 } 204 object->addMenu(menuText, menuId); 205} 206 207DefineEngineMethod(GuiMenuBar, addMenuItem, void, (const char* targetMenu, const char* menuItemText, S32 menuItemId, const char* accelerator, int checkGroup, const char *cmd), 208 ("","",0,nullAsType<const char*>(),-1,""), 209 "@brief Adds a menu item to the specified menu. The menu argument can be either the text of a menu or its id.\n\n" 210 "@param menu Menu name or menu Id to add the new item to.\n" 211 "@param menuItemText Text for the new menu item.\n" 212 "@param menuItemId Id for the new menu item.\n" 213 "@param accelerator Accelerator key for the new menu item.\n" 214 "@param checkGroup Check group to include this menu item in.\n" 215 "@tsexample\n" 216 "// Define the menu we wish to add the item to\n" 217 "%targetMenu = \"New Menu\"; or %menu = \"4\";\n\n" 218 "// Define the text for the new menu item\n" 219 "%menuItemText = \"Menu Item\";\n\n" 220 "// Define the id for the new menu item\n" 221 "%menuItemId = \"3\";\n\n" 222 "// Set the accelerator key to toggle this menu item with\n" 223 "%accelerator = \"n\";\n\n" 224 "// Define the Check Group that this menu item will be in, if we want it to be in a check group. -1 sets it in no check group.\n" 225 "%checkGroup = \"4\";\n\n" 226 "// Inform the GuiMenuBar control to add the new menu item with the defined fields\n" 227 "%thisGuiMenuBar.addMenuItem(%menu,%menuItemText,%menuItemId,%accelerator,%checkGroup);\n" 228 "@endtsexample\n\n" 229 "@see GuiTickCtrl") 230{ 231 if(dIsdigit(menuItemText[0])) 232 { 233 Con::errorf("Cannot add menu item %s (id = %s). First character of a menu item's text cannot be a digit.", menuItemText, menuItemId); 234 return; 235 } 236 GuiMenuBar::Menu *menu = object->findMenu(targetMenu); 237 if(!menu) 238 { 239 Con::errorf("Cannot find menu %s for addMenuItem.", targetMenu); 240 return; 241 } 242 object->addMenuItem(menu, menuItemText, menuItemId, accelerator != NULL ? accelerator : "", checkGroup == -1 ? -1 : checkGroup, cmd); 243} 244 245DefineEngineMethod(GuiMenuBar, setMenuItemEnable, void, (const char* menuTarget, const char* menuItemTarget, bool enabled),, 246 "@brief sets the menu item to enabled or disabled based on the enable parameter.\n" 247 "The specified menu and menu item can either be text or ids.\n\n" 248 "Detailed description\n\n" 249 "@param menuTarget Menu to work in\n" 250 "@param menuItemTarget The menu item inside of the menu to enable or disable\n" 251 "@param enabled Boolean enable / disable value.\n" 252 "@tsexample\n" 253 "// Define the menu\n" 254 "%menu = \"New Menu\"; or %menu = \"4\";\n\n" 255 "// Define the menu item\n" 256 "%menuItem = \"New Menu Item\"; or %menuItem = \"2\";\n\n" 257 "// Define the enabled state\n" 258 "%enabled = \"true\";\n\n" 259 "// Inform the GuiMenuBar control to set the enabled state of the requested menu item\n" 260 "%thisGuiMenuBar.setMenuItemEnable(%menu,%menuItme,%enabled);\n" 261 "@endtsexample\n\n" 262 "@see GuiTickCtrl") 263{ 264 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 265 if(!menu) 266 { 267 Con::errorf("Cannot find menu %s for setMenuItemEnable.", menuTarget); 268 return; 269 } 270 GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget); 271 if(!menuItem) 272 { 273 Con::errorf("Cannot find menu item %s for setMenuItemEnable.", menuItemTarget); 274 return; 275 } 276 menuItem->enabled = enabled; 277} 278 279DefineEngineMethod(GuiMenuBar, setCheckmarkBitmapIndex, void, (S32 bitmapindex),, 280 "@brief Sets the menu bitmap index for the check mark image.\n\n" 281 "@param bitmapIndex Bitmap index for the check mark image.\n" 282 "@tsexample\n" 283 "// Define the bitmap index\n" 284 "%bitmapIndex = \"2\";\n\n" 285 "// Inform the GuiMenuBar control of the proper bitmap index for the check mark image\n" 286 "%thisGuiMenuBar.setCheckmarkBitmapIndex(%bitmapIndex);\n" 287 "@endtsexample\n\n" 288 "@see GuiTickCtrl") 289{ 290 object->mCheckmarkBitmapIndex = bitmapindex; 291} 292 293DefineEngineMethod(GuiMenuBar, setMenuItemChecked, void, (const char* menuTarget, const char* menuItemTarget, bool checked),, 294 "@brief Sets the menu item bitmap to a check mark, which by default is the first element in\n" 295 "the bitmap array (although this may be changed with setCheckmarkBitmapIndex()).\n" 296 "Any other menu items in the menu with the same check group become unchecked if they are checked.\n\n" 297 "@param menuTarget Menu to work in\n" 298 "@param menuItem Menu item to affect\n" 299 "@param checked Whether we are setting it to checked or not\n" 300 "@tsexample\n" 301 "" 302 "@endtsexample\n\n" 303 "@return If not void, return value and description\n\n" 304 "@see References") 305{ 306 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 307 if(!menu) 308 { 309 Con::errorf("Cannot find menu %s for setMenuItemChecked.", menuTarget); 310 return; 311 } 312 GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget); 313 if(!menuItem) 314 { 315 Con::errorf("Cannot find menu item %s for setMenuItemChecked.", menuItemTarget); 316 return; 317 } 318 if(checked && menuItem->checkGroup != -1) 319 { 320 // first, uncheck everything in the group: 321 for(GuiMenuBar::MenuItem *itemWalk = menu->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem) 322 if(itemWalk->checkGroup == menuItem->checkGroup && itemWalk->bitmapIndex == object->mCheckmarkBitmapIndex) 323 itemWalk->bitmapIndex = -1; 324 } 325 menuItem->bitmapIndex = checked ? object->mCheckmarkBitmapIndex : -1; 326} 327 328DefineEngineMethod(GuiMenuBar, setMenuText, void, (const char* menuTarget, const char* newMenuText),, 329 "@brief Sets the text of the specified menu to the new string.\n\n" 330 "@param menuTarget Menu to affect\n" 331 "@param newMenuText New menu text\n" 332 "@tsexample\n" 333 "// Define the menu to affect" 334 "%menu = \"New Menu\"; or %menu = \"3\";\n\n" 335 "// Define the text to change the menu to\n" 336 "%newMenuText = \"Still a New Menu\";\n\n" 337 "// Inform the GuiMenuBar control to change the defined menu to the defined text\n" 338 "%thisGuiMenuBar.setMenuText(%menu,%newMenuText);\n" 339 "@endtsexample\n\n" 340 "@see GuiTickCtrl") 341{ 342 if(dIsdigit(menuTarget[0])) 343 { 344 Con::errorf("Cannot name menu %s to %s. First character of a menu's text cannot be a digit.", menuTarget, newMenuText); 345 return; 346 } 347 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 348 if(!menu) 349 { 350 Con::errorf("Cannot find menu %s for setMenuText.", menuTarget); 351 return; 352 } 353 dFree(menu->text); 354 menu->text = dStrdup(newMenuText); 355 object->menuBarDirty = true; 356} 357 358DefineEngineMethod(GuiMenuBar, setMenuBitmapIndex, void, (const char* menuTarget, S32 bitmapindex, bool bitmaponly, bool drawborder),, 359 "@brief Sets the bitmap index for the menu and toggles rendering only the bitmap.\n\n" 360 "@param menuTarget Menu to affect\n" 361 "@param bitmapindex Bitmap index to set for the menu\n" 362 "@param bitmaponly If true, only the bitmap will be rendered\n" 363 "@param drawborder If true, a border will be drawn around the menu.\n" 364 "@tsexample\n" 365 "// Define the menuTarget to affect\n" 366 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 367 "// Set the bitmap index\n" 368 "%bitmapIndex = \"5\";\n\n" 369 "// Set if we are only to render the bitmap or not\n" 370 "%bitmaponly = \"true\";\n\n" 371 "// Set if we are rendering a border or not\n" 372 "%drawborder = \"true\";\n\n" 373 "// Inform the GuiMenuBar of the bitmap and rendering changes\n" 374 "%thisGuiMenuBar.setMenuBitmapIndex(%menuTarget,%bitmapIndex,%bitmapOnly,%drawBorder);\n" 375 "@endtsexample\n\n" 376 "@see GuiTickCtrl") 377{ 378 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 379 if(!menu) 380 { 381 Con::errorf("Cannot find menu %s for setMenuBitmapIndex.", menuTarget); 382 return; 383 } 384 385 menu->bitmapIndex = bitmapindex; 386 menu->drawBitmapOnly = bitmaponly; 387 menu->drawBorder = drawborder; 388 389 object->menuBarDirty = true; 390} 391 392DefineEngineMethod(GuiMenuBar, setMenuVisible, void, (const char* menuTarget, bool visible),, 393 "@brief Sets the whether or not to display the specified menu.\n\n" 394 "@param menuTarget Menu item to affect\n" 395 "@param visible Whether the menu item will be visible or not\n" 396 "@tsexample\n" 397 "// Define the menu to work with\n" 398 "%menuTarget = \"New Menu\"; or %menuTarget = \"4\";\n\n" 399 "// Define if the menu should be visible or not\n" 400 "%visible = \"true\";\n\n" 401 "// Inform the GuiMenuBar control of the new visibility state for the defined menu\n" 402 "%thisGuiMenuBar.setMenuVisible(%menuTarget,%visible);\n" 403 "@endtsexample\n\n" 404 "@see GuiTickCtrl") 405{ 406 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 407 if(!menu) 408 { 409 Con::errorf("Cannot find menu %s for setMenuVisible.", menuTarget); 410 return; 411 } 412 menu->visible = visible; 413 object->menuBarDirty = true; 414 object->setUpdate(); 415} 416 417DefineEngineMethod(GuiMenuBar, setMenuItemText, void, (const char* menuTarget, const char* menuItemTarget, const char* newMenuItemText),, 418 "@brief Sets the text of the specified menu item to the new string.\n\n" 419 "@param menuTarget Menu to affect\n" 420 "@param menuItem Menu item in the menu to change the text at\n" 421 "@param newMenuItemText New menu text\n" 422 "@tsexample\n" 423 "// Define the menuTarget\n" 424 "%menuTarget = \"New Menu\"; or %menuTarget = \"4\";\n\n" 425 "// Define the menuItem\n" 426 "%menuItem = \"New Menu Item\"; or %menuItem = \"2\";\n\n" 427 "// Define the new text for the menu item\n" 428 "%newMenuItemText = \"Very New Menu Item\";\n\n" 429 "// Inform the GuiMenuBar control to change the defined menu item with the new text\n" 430 "%thisGuiMenuBar.setMenuItemText(%menuTarget,%menuItem,%newMenuItemText);\n" 431 "@endtsexample\n\n" 432 "@see GuiTickCtrl") 433{ 434 if(dIsdigit(newMenuItemText[0])) 435 { 436 Con::errorf("Cannot name menu item %s to %s. First character of a menu item's text cannot be a digit.", menuItemTarget, newMenuItemText); 437 return; 438 } 439 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 440 if(!menu) 441 { 442 Con::errorf("Cannot find menu %s for setMenuItemText.", menuTarget); 443 return; 444 } 445 GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget); 446 if(!menuItem) 447 { 448 Con::errorf("Cannot find menu item %s for setMenuItemText.", menuItemTarget); 449 return; 450 } 451 dFree(menuItem->text); 452 menuItem->text = dStrdup(newMenuItemText); 453} 454 455DefineEngineMethod(GuiMenuBar, setMenuItemVisible, void, (const char* menuTarget, const char* menuItemTarget, bool isVisible),, 456 "@brief Brief Description.\n\n" 457 "Detailed description\n\n" 458 "@param menuTarget Menu to affect the menu item in\n" 459 "@param menuItem Menu item to affect\n" 460 "@param isVisible Visible state to set the menu item to.\n" 461 "@tsexample\n" 462 "// Define the menuTarget\n" 463 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 464 "// Define the menuItem\n" 465 "%menuItem = \"New Menu Item\"; or %menuItem = \"2\";\n\n" 466 "// Define the visibility state\n" 467 "%isVisible = \"true\";\n\n" 468 "// Inform the GuiMenuBarControl of the visibility state of the defined menu item\n" 469 "%thisGuiMenuBar.setMenuItemVisible(%menuTarget,%menuItem,%isVisible);\n" 470 "@endtsexample\n\n" 471 "@see GuiTickCtrl") 472{ 473 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 474 if(!menu) 475 { 476 Con::errorf("Cannot find menu %s for setMenuItemVisible.", menuTarget); 477 return; 478 } 479 GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget); 480 if(!menuItem) 481 { 482 Con::errorf("Cannot find menu item %s for setMenuItemVisible.", menuItemTarget); 483 return; 484 } 485 menuItem->visible = isVisible; 486} 487 488DefineEngineMethod(GuiMenuBar, setMenuItemBitmap, void, (const char* menuTarget, const char* menuItemTarget, S32 bitmapIndex),, 489 "@brief Sets the specified menu item bitmap index in the bitmap array. Setting the item's index to -1 will remove any bitmap.\n\n" 490 "@param menuTarget Menu to affect the menuItem in\n" 491 "@param menuItem Menu item to affect\n" 492 "@param bitmapIndex Bitmap index to set the menu item to\n" 493 "@tsexample\n" 494 "// Define the menuTarget\n" 495 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 496 "// Define the menuItem\"\n" 497 "%menuItem = \"New Menu Item\"; or %menuItem = \"2\";\n\n" 498 "// Define the bitmapIndex\n" 499 "%bitmapIndex = \"6\";\n\n" 500 "// Inform the GuiMenuBar control to set the menu item to the defined bitmap\n" 501 "%thisGuiMenuBar.setMenuItemBitmap(%menuTarget,%menuItem,%bitmapIndex);\n" 502 "@endtsexample\n\n" 503 "@see GuiTickCtrl") 504{ 505 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 506 if(!menu) 507 { 508 Con::errorf("Cannot find menu %s for setMenuItemBitmap.", menuTarget); 509 return; 510 } 511 GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget); 512 if(!menuItem) 513 { 514 Con::errorf("Cannot find menu item %s for setMenuItemBitmap.", menuItemTarget); 515 return; 516 } 517 menuItem->bitmapIndex = bitmapIndex; 518} 519 520DefineEngineMethod(GuiMenuBar, removeMenuItem, void, (const char* menuTarget, const char* menuItemTarget),, 521 "@brief Removes the specified menu item from the menu.\n\n" 522 "@param menuTarget Menu to affect the menu item in\n" 523 "@param menuItem Menu item to affect\n" 524 "@tsexample\n" 525 "// Define the menuTarget\n" 526 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 527 "// Define the menuItem\n" 528 "%menuItem = \"New Menu Item\"; or %menuItem = \"5\";\n\n" 529 "// Request the GuiMenuBar control to remove the define menu item\n" 530 "%thisGuiMenuBar.removeMenuItem(%menuTarget,%menuItem);\n\n" 531 "@endtsexample\n\n" 532 "@see GuiTickCtrl") 533{ 534 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 535 if(!menu) 536 { 537 Con::errorf("Cannot find menu %s for removeMenuItem.", menuTarget); 538 return; 539 } 540 GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget); 541 if(!menuItem) 542 { 543 Con::errorf("Cannot find menu item %s for removeMenuItem.", menuItemTarget); 544 return; 545 } 546 object->removeMenuItem(menu, menuItem); 547} 548 549DefineEngineMethod(GuiMenuBar, clearMenuItems, void, (const char* menuTarget),, 550 "@brief Removes all the menu items from the specified menu.\n\n" 551 "@param menuTarget Menu to remove all items from\n" 552 "@tsexample\n" 553 "// Define the menuTarget\n" 554 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 555 "// Inform the GuiMenuBar control to clear all menu items from the defined menu\n" 556 "%thisGuiMenuBar.clearMenuItems(%menuTarget);\n" 557 "@endtsexample\n\n" 558 "@see GuiTickCtrl") 559{ 560 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 561 if(!menu) 562 { 563 //Con::errorf("Cannot find menu %s for clearMenuItems.", menuTarget); 564 return; 565 } 566 object->clearMenuItems(menu); 567} 568 569DefineEngineMethod( GuiMenuBar, removeMenu, void, (const char* menuTarget),, 570 "@brief Removes the specified menu from the menu bar.\n\n" 571 "@param menuTarget Menu to remove from the menu bar\n" 572 "@tsexample\n" 573 "// Define the menuTarget\n" 574 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 575 "// Inform the GuiMenuBar to remove the defined menu from the menu bar\n" 576 "%thisGuiMenuBar.removeMenu(%menuTarget);\n" 577 "@endtsexample\n\n" 578 "@see GuiTickCtrl") 579{ 580 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 581 if(!menu) 582 { 583 //Con::errorf("Cannot find menu %s for removeMenu.", menuTarget); 584 return; 585 } 586 object->clearMenuItems(menu); 587 object->menuBarDirty = true; 588} 589 590//------------------------------------------------------------------------------ 591// Submenu console methods 592//------------------------------------------------------------------------------ 593 594DefineEngineMethod(GuiMenuBar, setMenuItemSubmenuState, void, (const char* menuTarget, const char* menuItem, bool isSubmenu),, 595 "@brief Sets the given menu item to be a submenu.\n\n" 596 "@param menuTarget Menu to affect a submenu in\n" 597 "@param menuItem Menu item to affect\n" 598 "@param isSubmenu Whether or not the menuItem will become a subMenu or not\n" 599 "@tsexample\n" 600 "// Define the menuTarget\n" 601 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 602 "// Define the menuItem\n" 603 "%menuItem = \"New Menu Item\"; or %menuItem = \"5\";\n\n" 604 "// Define whether or not the Menu Item is a sub menu or not\n" 605 "%isSubmenu = \"true\";\n\n" 606 "// Inform the GuiMenuBar control to set the defined menu item to be a submenu or not.\n" 607 "%thisGuiMenuBar.setMenuItemSubmenuState(%menuTarget,%menuItem,%isSubmenu);\n" 608 "@endtsexample\n\n" 609 "@see GuiTickCtrl") 610{ 611 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 612 if(!menu) 613 { 614 Con::errorf("Cannot find menu %s for setMenuItemSubmenuState.", menuTarget); 615 return; 616 } 617 618 GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, menuItem); 619 if(!menuitem) 620 { 621 Con::errorf("Cannot find menuitem %s for setMenuItemSubmenuState.", menuItem); 622 return; 623 } 624 625 menuitem->isSubmenu = isSubmenu; 626} 627 628DefineEngineMethod(GuiMenuBar, addSubmenuItem, void, (const char* menuTarget, const char* menuItem, const char* submenuItemText, 629 int submenuItemId, const char* accelerator, int checkGroup),, 630 "@brief Adds a menu item to the specified menu. The menu argument can be either the text of a menu or its id.\n\n" 631 "@param menuTarget Menu to affect a submenu in\n" 632 "@param menuItem Menu item to affect\n" 633 "@param submenuItemText Text to show for the new submenu\n" 634 "@param submenuItemId Id for the new submenu\n" 635 "@param accelerator Accelerator key for the new submenu\n" 636 "@param checkGroup Which check group the new submenu should be in, or -1 for none.\n" 637 "@tsexample\n" 638 "// Define the menuTarget\n" 639 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 640 "// Define the menuItem\n" 641 "%menuItem = \"New Menu Item\"; or %menuItem = \"5\";\n\n" 642 "// Define the text for the new submenu\n" 643 "%submenuItemText = \"New Submenu Item\";\n\n" 644 "// Define the id for the new submenu\n" 645 "%submenuItemId = \"4\";\n\n" 646 "// Define the accelerator key for the new submenu\n" 647 "%accelerator = \"n\";\n\n" 648 "// Define the checkgroup for the new submenu\n" 649 "%checkgroup = \"7\";\n\n" 650 "// Request the GuiMenuBar control to add the new submenu with the defined information\n" 651 "%thisGuiMenuBar.addSubmenuItem(%menuTarget,%menuItem,%submenuItemText,%submenuItemId,%accelerator,%checkgroup);\n" 652 "@endtsexample\n\n" 653 "@see GuiTickCtrl\n") 654{ 655 if(dIsdigit(submenuItemText[0])) 656 { 657 Con::errorf("Cannot add submenu item %s (id = %s). First character of a menu item's text cannot be a digit.", submenuItemText, submenuItemId); 658 return; 659 } 660 661 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 662 if(!menu) 663 { 664 Con::errorf("Cannot find menu %s for addMenuItem.", menuTarget); 665 return; 666 } 667 668 GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, menuItem); 669 if(!menuitem) 670 { 671 Con::errorf("Cannot find menuitem %s for addSubmenuItem.", menuItem); 672 return; 673 } 674 675 object->addSubmenuItem(menu, menuitem, submenuItemText, submenuItemId, !accelerator ? "" : accelerator, checkGroup == -1 ? -1 : checkGroup); 676} 677 678DefineEngineMethod(GuiMenuBar, clearSubmenuItems, void, (const char* menuTarget, const char* menuItem),, 679 "@brief Removes all the menu items from the specified submenu.\n\n" 680 "@param menuTarget Menu to affect a submenu in\n" 681 "@param menuItem Menu item to affect\n" 682 "@tsexample\n" 683 "// Define the menuTarget\n" 684 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 685 "// Define the menuItem\n" 686 "%menuItem = \"New Menu Item\"; or %menuItem = \"5\";\n\n" 687 "// Inform the GuiMenuBar to remove all submenu items from the defined menu item\n" 688 "%thisGuiMenuBar.clearSubmenuItems(%menuTarget,%menuItem);\n\n" 689 "@endtsexample\n\n" 690 "@see GuiControl") 691{ 692 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 693 if(!menu) 694 { 695 Con::errorf("Cannot find menu %s for clearSubmenuItems.", menuTarget); 696 return; 697 } 698 699 GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, menuItem); 700 if(!menuitem) 701 { 702 Con::errorf("Cannot find menuitem %s for clearSubmenuItems.", menuItem); 703 return; 704 } 705 706 object->clearSubmenuItems(menuitem); 707} 708 709DefineEngineMethod(GuiMenuBar, setSubmenuItemChecked, void, (const char* menuTarget, const char* menuItemTarget, const char* submenuItemText, bool checked),, 710 "@brief Sets the menu item bitmap to a check mark, which by default is the first element in the\n" 711 "bitmap array (although this may be changed with setCheckmarkBitmapIndex()).\n" 712 "Any other menu items in the menu with the same check group become unchecked if they are checked.\n\n" 713 "@param menuTarget Menu to affect a submenu in\n" 714 "@param menuItem Menu item to affect\n" 715 "@param submenuItemText Text to show for submenu\n" 716 "@param checked Whether or not this submenu item will be checked.\n" 717 "@tsexample\n" 718 "// Define the menuTarget\n" 719 "%menuTarget = \"New Menu\"; or %menuTarget = \"3\";\n\n" 720 "// Define the menuItem\n" 721 "%menuItem = \"New Menu Item\"; or %menuItem = \"5\";\n\n" 722 "// Define the text for the new submenu\n" 723 "%submenuItemText = \"Submenu Item\";\n\n" 724 "// Define if this submenu item should be checked or not\n" 725 "%checked = \"true\";\n\n" 726 "// Inform the GuiMenuBar control to set the checked state of the defined submenu item\n" 727 "%thisGuiMenuBar.setSubmenuItemChecked(%menuTarget,%menuItem,%submenuItemText,%checked);\n" 728 "@endtsexample\n\n" 729 "@return If not void, return value and description\n\n" 730 "@see References") 731{ 732 // Find the parent menu 733 GuiMenuBar::Menu *menu = object->findMenu(menuTarget); 734 if(!menu) 735 { 736 Con::errorf("Cannot find menu %s for setSubmenuItemChecked.", menuTarget); 737 return; 738 } 739 740 // Find the parent menu item 741 GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget); 742 if(!menuItem) 743 { 744 Con::errorf("Cannot find menu item %s for setSubmenuItemChecked.", menuItemTarget); 745 return; 746 } 747 748 // Find the submenu item 749 GuiMenuBar::MenuItem *submenuItem = object->findSubmenuItem(menu, menuItemTarget, submenuItemText); 750 if(!submenuItem) 751 { 752 Con::errorf("Cannot find submenu item %s for setSubmenuItemChecked.", submenuItemText); 753 return; 754 } 755 756 if(checked && submenuItem->checkGroup != -1) 757 { 758 // first, uncheck everything in the group: 759 for(GuiMenuBar::MenuItem *itemWalk = menuItem->submenu->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem) 760 if(itemWalk->checkGroup == submenuItem->checkGroup && itemWalk->bitmapIndex == object->mCheckmarkBitmapIndex) 761 itemWalk->bitmapIndex = -1; 762 } 763 submenuItem->bitmapIndex = checked ? object->mCheckmarkBitmapIndex : -1; 764} 765 766//------------------------------------------------------------------------------ 767// menu management methods 768//------------------------------------------------------------------------------ 769GuiMenuBar::Menu* GuiMenuBar::sCreateMenu(const char *menuText, U32 menuId) 770{ 771 // allocate the menu 772 Menu *newMenu = new Menu; 773 newMenu->text = dStrdup(menuText); 774 newMenu->id = menuId; 775 newMenu->nextMenu = NULL; 776 newMenu->firstMenuItem = NULL; 777 newMenu->visible = true; 778 779 // Menu bitmap variables 780 newMenu->bitmapIndex = -1; 781 newMenu->drawBitmapOnly = false; 782 newMenu->drawBorder = true; 783 784 return newMenu; 785} 786 787void GuiMenuBar::addMenu(GuiMenuBar::Menu *newMenu, S32 pos) 788{ 789 // add it to the menu list 790 menuBarDirty = true; 791 if (pos == -1) 792 mMenuList.push_back(newMenu); 793 else 794 mMenuList.insert(pos, newMenu); 795} 796 797void GuiMenuBar::addMenu(const char *menuText, U32 menuId) 798{ 799 Menu *newMenu = sCreateMenu(menuText, menuId); 800 801 addMenu(newMenu); 802} 803 804GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu) 805{ 806 if(dIsdigit(menu[0])) 807 { 808 U32 id = dAtoi(menu); 809 for (U32 i = 0; i < mMenuList.size(); ++i) 810 if (id == mMenuList[i].id) 811 return mMenuList[i]; 812 return NULL; 813 } 814 else 815 { 816 for (U32 i = 0; i < mMenuList.size(); ++i) 817 if (!dStricmp(menu, mMenuList[i].text)) 818 return mMenuList[i]; 819 return NULL; 820 } 821} 822 823GuiMenuBar::MenuItem *GuiMenuBar::findMenuItem(Menu *menu, const char *menuItem) 824{ 825 if(dIsdigit(menuItem[0])) 826 { 827 U32 id = dAtoi(menuItem); 828 for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem) 829 if(id == walk->id) 830 return walk; 831 return NULL; 832 } 833 else 834 { 835 for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem) 836 if(!dStricmp(menuItem, walk->text)) 837 return walk; 838 return NULL; 839 } 840} 841 842void GuiMenuBar::removeMenu(Menu *menu) 843{ 844 menuBarDirty = true; 845 clearMenuItems(menu); 846 847 for (U32 i = 0; i < mMenuList.size(); ++i) 848 { 849 if (mMenuList[i] == menu) 850 { 851 mMenuList.erase(i); 852 break; 853 } 854 } 855} 856 857void GuiMenuBar::removeMenuItem(Menu *menu, MenuItem *menuItem) 858{ 859 for(MenuItem **walk = &menu->firstMenuItem; *walk; walk = &(*walk)->nextMenuItem) 860 { 861 if(*walk == menuItem) 862 { 863 *walk = menuItem->nextMenuItem; 864 break; 865 } 866 } 867 868 // If this is a submenu, then be sure to clear the submenu's items 869 if(menuItem->isSubmenu) 870 { 871 clearSubmenuItems(menuItem); 872 } 873 874 dFree(menuItem->text); 875 dFree(menuItem->accelerator); 876 delete menuItem; 877} 878 879GuiMenuBar::MenuItem* GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup, const char *cmd ) 880{ 881 // allocate the new menu item 882 MenuItem *newMenuItem = new MenuItem; 883 newMenuItem->text = dStrdup(text); 884 if(accelerator[0]) 885 newMenuItem->accelerator = dStrdup(accelerator); 886 else 887 newMenuItem->accelerator = NULL; 888 newMenuItem->cmd = cmd; 889 newMenuItem->id = id; 890 newMenuItem->checkGroup = checkGroup; 891 newMenuItem->nextMenuItem = NULL; 892 newMenuItem->acceleratorIndex = 0; 893 newMenuItem->enabled = text[0] != '-'; 894 newMenuItem->visible = true; 895 newMenuItem->bitmapIndex = -1; 896 897 // Default to not having a submenu 898 newMenuItem->isSubmenu = false; 899 newMenuItem->submenu = NULL; 900 newMenuItem->submenuParentMenu = NULL; 901 902 // link it into the menu's menu item list 903 if(menu) 904 { 905 MenuItem **walk = &menu->firstMenuItem; 906 while(*walk) 907 walk = &(*walk)->nextMenuItem; 908 *walk = newMenuItem; 909 } 910 911 return newMenuItem; 912} 913 914GuiMenuBar::MenuItem* GuiMenuBar::addMenuItem(Menu *menu, MenuItem* newMenuItem) 915{ 916 // link it into the menu's menu item list 917 if(menu) 918 { 919 MenuItem **walk = &menu->firstMenuItem; 920 while(*walk) 921 walk = &(*walk)->nextMenuItem; 922 *walk = newMenuItem; 923 } 924 925 return newMenuItem; 926} 927 928void GuiMenuBar::clearMenuItems(Menu *menu) 929{ 930 while(menu->firstMenuItem) 931 removeMenuItem(menu, menu->firstMenuItem); 932} 933 934void GuiMenuBar::clearMenus() 935{ 936 mMenuList.clear(); 937} 938 939void GuiMenuBar::attachToMenuBar(Menu* menu, S32 pos) 940{ 941 addMenu(menu, pos); 942} 943 944void GuiMenuBar::removeFromMenuBar(Menu* menu) 945{ 946 menuBarDirty = true; 947 948 for (U32 i = 0; i < mMenuList.size(); ++i) 949 { 950 if (mMenuList[i] == menu) 951 { 952 mMenuList.erase(i); 953 break; 954 } 955 } 956} 957 958//------------------------------------------------------------------------------ 959// Submenu methods 960//------------------------------------------------------------------------------ 961 962// This method will return the MenuItem class of of a submenu's menu item given 963// its parent menu and parent menuitem. If the menuitem ID is used, then the submenu 964// ID must also be used. 965GuiMenuBar::MenuItem *GuiMenuBar::findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem) 966{ 967 if(dIsdigit(menuItem[0])) 968 { 969 // Search by ID 970 U32 id = dAtoi(menuItem); 971 for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem) 972 if(id == walk->id) 973 { 974 if(walk->isSubmenu && walk->submenu) 975 { 976 return GuiMenuBar::findMenuItem(walk->submenu, submenuItem); 977 } 978 return NULL; 979 } 980 return NULL; 981 } 982 else 983 { 984 // Search by name 985 for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem) 986 if(!dStricmp(menuItem, walk->text)) 987 { 988 if(walk->isSubmenu && walk->submenu) 989 { 990 return GuiMenuBar::findMenuItem(walk->submenu, submenuItem); 991 } 992 return NULL; 993 } 994 return NULL; 995 } 996} 997 998GuiMenuBar::MenuItem* GuiMenuBar::findSubmenuItem(MenuItem *menuItem, const char *submenuItem) 999{ 1000 if( !menuItem->isSubmenu ) 1001 return NULL; 1002 1003 return GuiMenuBar::findMenuItem( menuItem->submenu, submenuItem ); 1004} 1005 1006// Add a menuitem to the given submenu 1007void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup) 1008{ 1009 // Check that the given menu item supports a submenu 1010 if(submenu && !submenu->isSubmenu) 1011 { 1012 Con::errorf("GuiMenuBar::addSubmenuItem: Attempting to add menuitem '%s' to an invalid submenu",text); 1013 return; 1014 } 1015 1016 // allocate the new menu item 1017 MenuItem *newMenuItem = new MenuItem; 1018 newMenuItem->text = dStrdup(text); 1019 if(accelerator[0]) 1020 newMenuItem->accelerator = dStrdup(accelerator); 1021 else 1022 newMenuItem->accelerator = NULL; 1023 newMenuItem->id = id; 1024 newMenuItem->checkGroup = checkGroup; 1025 newMenuItem->nextMenuItem = NULL; 1026 newMenuItem->acceleratorIndex = 0; 1027 newMenuItem->enabled = (dStrlen(text) > 1 || text[0] != '-'); 1028 newMenuItem->visible = true; 1029 newMenuItem->bitmapIndex = -1; 1030 1031 // Default to not having a submenu 1032 newMenuItem->isSubmenu = false; 1033 newMenuItem->submenu = NULL; 1034 1035 // Point back to the submenu's menu 1036 newMenuItem->submenuParentMenu = menu; 1037 1038 // link it into the menu's menu item list 1039 MenuItem **walk = &submenu->submenu->firstMenuItem; 1040 while(*walk) 1041 walk = &(*walk)->nextMenuItem; 1042 *walk = newMenuItem; 1043} 1044 1045void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, MenuItem *newMenuItem ) 1046{ 1047 AssertFatal( submenu && newMenuItem, ""); 1048 1049 // Point back to the submenu's menu 1050 newMenuItem->submenuParentMenu = menu; 1051 1052 // link it into the menu's menu item list 1053 MenuItem **walk = &submenu->submenu->firstMenuItem; 1054 while(*walk) 1055 walk = &(*walk)->nextMenuItem; 1056 *walk = newMenuItem; 1057} 1058 1059// Remove a submenu item 1060void GuiMenuBar::removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem) 1061{ 1062 // Check that the given menu item supports a submenu 1063 if(menuItem && !menuItem->isSubmenu) 1064 { 1065 Con::errorf("GuiMenuBar::removeSubmenuItem: Attempting to remove submenuitem '%s' from an invalid submenu",submenuItem->text); 1066 return; 1067 } 1068 1069 GuiMenuBar::removeMenuItem(menuItem->submenu, submenuItem); 1070} 1071 1072// Clear all menuitems from a submenu 1073void GuiMenuBar::clearSubmenuItems(MenuItem *menuitem) 1074{ 1075 // Check that the given menu item supports a submenu 1076 if(menuitem && !menuitem->isSubmenu) 1077 { 1078 Con::errorf("GuiMenuBar::clearSubmenuItems: Attempting to clear an invalid submenu"); 1079 return; 1080 } 1081 1082 while(menuitem->submenu->firstMenuItem) 1083 removeSubmenuItem(menuitem, menuitem->submenu->firstMenuItem); 1084} 1085*/ 1086//------------------------------------------------------------------------------ 1087// initialization, input and render methods 1088//------------------------------------------------------------------------------ 1089 1090GuiMenuBar::GuiMenuBar() 1091{ 1092 //mMenuList.clear(); 1093 menuBarDirty = true; 1094 mouseDownMenu = NULL; 1095 mouseOverMenu = NULL; 1096 mCurAcceleratorIndex = 0; 1097 mPadding = 0; 1098 1099 mCheckmarkBitmapIndex = 0; // Default to the first image in the bitmap array for the check mark 1100 1101 mHorizontalMargin = 6; // Default number of pixels on the left and right side of a manu's text 1102 mVerticalMargin = 1; // Default number of pixels on the top and bottom of a menu's text 1103 mBitmapMargin = 2; // Default number of pixels between a menu's bitmap and text 1104 1105 mMenubarHeight = 20; 1106 1107 // Added: 1108 mouseDownSubmenu = NULL; 1109 mouseOverSubmenu = NULL; 1110 1111 mMouseInMenu = false; 1112 1113 setProcessTicks(false); 1114} 1115 1116void GuiMenuBar::onRemove() 1117{ 1118 GuiPopupMenuBackgroundCtrl* backgroundCtrl; 1119 if (Sim::findObject("PopUpMenuControl", backgroundCtrl)) 1120 { 1121 if (backgroundCtrl->mMenuBarCtrl == this) 1122 backgroundCtrl->mMenuBarCtrl = nullptr; 1123 } 1124 1125 Parent::onRemove(); 1126} 1127 1128void GuiMenuBar::initPersistFields() 1129{ 1130 addField("padding", TypeS32, Offset( mPadding, GuiMenuBar ),"Extra padding to add to the bounds of the control.\n"); 1131 1132 addField("menubarHeight", TypeS32, Offset(mMenubarHeight, GuiMenuBar), "Sets the height of the menubar when attached to the canvas.\n"); 1133 1134 Parent::initPersistFields(); 1135} 1136 1137bool GuiMenuBar::onWake() 1138{ 1139 if(!Parent::onWake()) 1140 return false; 1141 mProfile->constructBitmapArray(); // if a bitmap was specified... 1142 maxBitmapSize.set(0,0); 1143 S32 numBitmaps = mProfile->mBitmapArrayRects.size(); 1144 if(numBitmaps) 1145 { 1146 RectI *bitmapBounds = mProfile->mBitmapArrayRects.address(); 1147 for(S32 i = 0; i < numBitmaps; i++) 1148 { 1149 if(bitmapBounds[i].extent.x > maxBitmapSize.x) 1150 maxBitmapSize.x = bitmapBounds[i].extent.x; 1151 if(bitmapBounds[i].extent.y > maxBitmapSize.y) 1152 maxBitmapSize.y = bitmapBounds[i].extent.y; 1153 } 1154 } 1155 return true; 1156} 1157 1158void GuiMenuBar::addObject(SimObject* object) 1159{ 1160 PopupMenu* popup = dynamic_cast<PopupMenu*>(object); 1161 1162 if (!popup) 1163 { 1164 //if it's not a popup, handle it normally 1165 Parent::addObject(object); 1166 } 1167 else 1168 { 1169 //otherwise, if it IS a popup, don't add it as a child object, but instead just insert it as a menu entry 1170 insert(object, -1); 1171 } 1172} 1173 1174GuiMenuBar::MenuEntry *GuiMenuBar::findHitMenu(Point2I mousePoint) 1175{ 1176 Point2I pos = globalToLocalCoord(mousePoint); 1177 1178 for (U32 i = 0; i < mMenuList.size(); ++i) 1179 { 1180 if (mMenuList[i].visible && mMenuList[i].bounds.pointInRect(pos)) 1181 return &mMenuList[i]; 1182 } 1183 1184 return NULL; 1185} 1186 1187void GuiMenuBar::onPreRender() 1188{ 1189 setHeight(mMenubarHeight); 1190 1191 Parent::onPreRender(); 1192 if (menuBarDirty) 1193 { 1194 menuBarDirty = false; 1195 U32 curX = mPadding; 1196 for (U32 i = 0; i < mMenuList.size(); ++i) 1197 { 1198 if (!mMenuList[i].visible) 1199 continue; 1200 1201 // Bounds depends on if there is a bitmap to be drawn or not 1202 if (mMenuList[i].bitmapIndex == -1) 1203 { 1204 // Text only 1205 mMenuList[i].bounds.set(curX, 0, mProfile->mFont->getStrWidth(mMenuList[i].text) + (mHorizontalMargin * 2), getHeight() - (mVerticalMargin * 2)); 1206 1207 } 1208 else 1209 { 1210 // Will the bitmap and text be draw? 1211 if (!mMenuList[i].drawBitmapOnly) 1212 { 1213 // Draw the bitmap and the text 1214 RectI *bitmapBounds = mProfile->mBitmapArrayRects.address(); 1215 mMenuList[i].bounds.set(curX, 0, bitmapBounds[mMenuList[i].bitmapIndex].extent.x + mProfile->mFont->getStrWidth(mMenuList[i].text) + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2)); 1216 1217 } 1218 else 1219 { 1220 // Only the bitmap will be drawn 1221 RectI *bitmapBounds = mProfile->mBitmapArrayRects.address(); 1222 mMenuList[i].bounds.set(curX, 0, bitmapBounds[mMenuList[i].bitmapIndex].extent.x + mBitmapMargin + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2)); 1223 } 1224 } 1225 1226 curX += mMenuList[i].bounds.extent.x; 1227 } 1228 mouseOverMenu = NULL; 1229 mouseDownMenu = NULL; 1230 } 1231} 1232 1233void GuiMenuBar::checkMenuMouseMove(const GuiEvent &event) 1234{ 1235 MenuEntry *hit = findHitMenu(event.mousePoint); 1236 if(hit && hit != mouseDownMenu) 1237 { 1238 // gotta close out the current menu... 1239 mouseDownMenu->popupMenu->hidePopup(); 1240 1241 mouseOverMenu = mouseDownMenu = hit; 1242 setUpdate(); 1243 onAction(); 1244 } 1245} 1246 1247void GuiMenuBar::onMouseMove(const GuiEvent &event) 1248{ 1249 MenuEntry *hit = findHitMenu(event.mousePoint); 1250 1251 if (mouseDownMenu != nullptr && hit != nullptr) 1252 { 1253 //we have a standing click, so just update and go 1254 mouseDownMenu = mouseOverMenu = hit; 1255 setUpdate(); 1256 onAction(); 1257 1258 return; 1259 } 1260 1261 mouseOverMenu = hit; 1262 setUpdate(); 1263} 1264 1265void GuiMenuBar::onMouseEnter(const GuiEvent &event) 1266{ 1267 onMouseInMenu_callback(true); 1268 mMouseInMenu = true; 1269} 1270 1271void GuiMenuBar::onMouseLeave(const GuiEvent &event) 1272{ 1273 if(mouseOverMenu) 1274 setUpdate(); 1275 1276 mouseOverMenu = NULL; 1277 mMouseInMenu = false; 1278} 1279 1280void GuiMenuBar::onMouseDragged(const GuiEvent &event) 1281{ 1282} 1283 1284void GuiMenuBar::onMouseDown(const GuiEvent &event) 1285{ 1286} 1287 1288void GuiMenuBar::onMouseUp(const GuiEvent &event) 1289{ 1290 mouseDownMenu = mouseOverMenu = findHitMenu(event.mousePoint); 1291 setUpdate(); 1292 onAction(); 1293} 1294 1295void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect) 1296{ 1297 Point2I extent = getExtent(); 1298 1299 RectI ctrlRect(offset, extent); 1300 1301 GFXDrawUtil* drawUtil = GFX->getDrawUtil(); 1302 1303 //if opaque, fill the update rect with the fill color 1304 if (mProfile->mOpaque) 1305 drawUtil->drawRectFill(RectI(offset, extent), mProfile->mFillColor); 1306 1307 //if there's a border, draw the border 1308 if (mProfile->mBorder) 1309 renderBorder(ctrlRect, mProfile); 1310 1311 for (U32 i = 0; i < mMenuList.size(); ++i) 1312 { 1313 if (!mMenuList[i].visible) 1314 continue; 1315 1316 ColorI fontColor = mProfile->mFontColor; 1317 RectI bounds = mMenuList[i].bounds; 1318 bounds.point += offset; 1319 1320 Point2I start; 1321 1322 start.x = mMenuList[i].bounds.point.x + mHorizontalMargin; 1323 start.y = mMenuList[i].bounds.point.y + (mMenuList[i].bounds.extent.y - mProfile->mFont->getHeight()) / 2; 1324 1325 // Draw the border 1326 if (mMenuList[i].drawBorder) 1327 { 1328 RectI highlightBounds = bounds; 1329 highlightBounds.inset(1, 1); 1330 if (&mMenuList[i] == mouseDownMenu) 1331 renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL); 1332 else if (&mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL) 1333 renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL); 1334 } 1335 1336 // Do we draw a bitmap? 1337 if (mMenuList[i].bitmapIndex != -1) 1338 { 1339 S32 index = mMenuList[i].bitmapIndex * 3; 1340 if (&mMenuList[i] == mouseDownMenu) 1341 ++index; 1342 else if (&mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL) 1343 index += 2; 1344 1345 RectI rect = mProfile->mBitmapArrayRects[index]; 1346 1347 Point2I bitmapstart(start); 1348 bitmapstart.y = mMenuList[i].bounds.point.y + (mMenuList[i].bounds.extent.y - rect.extent.y) / 2; 1349 1350 drawUtil->clearBitmapModulation(); 1351 drawUtil->drawBitmapSR(mProfile->mTextureObject, offset + bitmapstart, rect); 1352 1353 // Should we also draw the text? 1354 if (!mMenuList[i].drawBitmapOnly) 1355 { 1356 start.x += mBitmapMargin; 1357 drawUtil->setBitmapModulation(fontColor); 1358 drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i].text, mProfile->mFontColors); 1359 } 1360 } 1361 else 1362 { 1363 drawUtil->setBitmapModulation(fontColor); 1364 drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i].text, mProfile->mFontColors); 1365 } 1366 } 1367 1368 renderChildControls(offset, updateRect); 1369} 1370 1371void GuiMenuBar::buildWindowAcceleratorMap(WindowInputGenerator &inputGenerator) 1372{ 1373 // ok, accelerator map is cleared... 1374 // add all our keys: 1375 mCurAcceleratorIndex = 1; 1376 1377 for (U32 i = 0; i < mMenuList.size(); ++i) 1378 { 1379 for (U32 item = 0; item < mMenuList[i].popupMenu->mMenuItems.size(); item++) 1380 { 1381 if (!mMenuList[i].popupMenu->mMenuItems[item].mAccelerator) 1382 { 1383 mMenuList[i].popupMenu->mMenuItems[item].mAccelerator = 0; 1384 continue; 1385 } 1386 1387 EventDescriptor accelEvent; 1388 ActionMap::createEventDescriptor(mMenuList[i].popupMenu->mMenuItems[item].mAccelerator, &accelEvent); 1389 1390 //now we have a modifier, and a key, add them to the canvas 1391 inputGenerator.addAcceleratorKey(this, mMenuList[i].popupMenu->mMenuItems[item].mCMD, accelEvent.eventCode, accelEvent.flags); 1392 1393 mMenuList[i].popupMenu->mMenuItems[item].mAcceleratorIndex = mCurAcceleratorIndex; 1394 mCurAcceleratorIndex++; 1395 } 1396 } 1397} 1398 1399void GuiMenuBar::removeWindowAcceleratorMap( WindowInputGenerator &inputGenerator ) 1400{ 1401 inputGenerator.removeAcceleratorKeys( this ); 1402} 1403 1404void GuiMenuBar::acceleratorKeyPress(U32 index) 1405{ 1406 // loop through all the menus 1407 // and find the item that corresponds to the accelerator index 1408 for (U32 i = 0; i < mMenuList.size(); ++i) 1409 { 1410 if (!mMenuList[i].visible) 1411 continue; 1412 1413 for(U32 item = 0; item < mMenuList[i].popupMenu->mMenuItems.size(); item++) 1414 { 1415 if(mMenuList[i].popupMenu->mMenuItems[item].mAcceleratorIndex == index) 1416 { 1417 // first, call the script callback for menu selection: 1418 onMenuSelect_callback(mMenuList[i].popupMenu->getId(), mMenuList[i].text); 1419 return; 1420 } 1421 } 1422 } 1423} 1424 1425void GuiMenuBar::onSleep() 1426{ 1427 Parent::onSleep(); 1428} 1429 1430//------------------------------------------------------------------------------ 1431void GuiMenuBar::onAction() 1432{ 1433 if(!mouseDownMenu) 1434 return; 1435 1436 mouseDownMenu->popupMenu->hidePopup(); 1437 1438 // first, call the script callback for menu selection: 1439 onMenuSelect_callback(mouseDownMenu->popupMenu->getId(), mouseDownMenu->text); 1440 1441 mouseDownMenu->popupMenu->mMenuBarCtrl = this; 1442 1443 GuiCanvas *root = getRoot(); 1444 Point2I pos = Point2I(mouseDownMenu->bounds.point.x, mouseDownMenu->bounds.point.y + mouseDownMenu->bounds.extent.y); 1445 mouseDownMenu->popupMenu->showPopup(root, pos.x, pos.y); 1446} 1447 1448// Process a tick 1449void GuiMenuBar::processTick() 1450{ 1451 if(mMouseInMenu) 1452 onMouseInMenu_callback(true); 1453} 1454 1455void GuiMenuBar::insert(SimObject* pObject, S32 pos) 1456{ 1457 PopupMenu* menu = dynamic_cast<PopupMenu*>(pObject); 1458 if (menu == nullptr) 1459 return; 1460 1461 MenuEntry newMenu; 1462 newMenu.pos = pos >= mMenuList.size() || pos == -1 ? pos = mMenuList.size() : pos; 1463 newMenu.drawBitmapOnly = false; 1464 newMenu.drawBorder = true; 1465 newMenu.bitmapIndex = -1; 1466 newMenu.text = menu->mBarTitle; 1467 newMenu.visible = true; 1468 newMenu.popupMenu = menu; 1469 1470 if (pos >= mMenuList.size() || pos == -1) 1471 mMenuList.push_back(newMenu); 1472 else 1473 mMenuList.insert(pos, newMenu); 1474} 1475 1476PopupMenu* GuiMenuBar::getMenu(U32 index) 1477{ 1478 if (index >= mMenuList.size()) 1479 return nullptr; 1480 1481 return mMenuList[index].popupMenu; 1482} 1483 1484PopupMenu* GuiMenuBar::findMenu(String barTitle) 1485{ 1486 for (U32 i = 0; i < mMenuList.size(); i++) 1487 { 1488 if (String::ToLower(mMenuList[i].text) == String::ToLower(barTitle)) 1489 return mMenuList[i].popupMenu; 1490 } 1491 1492 return nullptr; 1493} 1494 1495//----------------------------------------------------------------------------- 1496// Console Methods 1497//----------------------------------------------------------------------------- 1498DefineEngineMethod(GuiMenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)") 1499{ 1500 GuiCanvas* canv = dynamic_cast<GuiCanvas*>(Sim::findObject(canvas)); 1501 if (canv) 1502 { 1503 canv->setMenuBar(object); 1504 } 1505} 1506 1507DefineEngineMethod(GuiMenuBar, removeFromCanvas, void, (), , "()") 1508{ 1509 GuiCanvas* canvas = object->getRoot(); 1510 1511 if(canvas) 1512 canvas->setMenuBar(nullptr); 1513} 1514 1515DefineEngineMethod(GuiMenuBar, getMenuCount, S32, (), , "()") 1516{ 1517 return object->getMenuListCount(); 1518} 1519 1520DefineEngineMethod(GuiMenuBar, getMenu, S32, (S32 index), (0), "(Index)") 1521{ 1522 return object->getMenu(index)->getId(); 1523} 1524 1525//----------------------------------------------------------------------------- 1526DefineEngineMethod(GuiMenuBar, insert, void, (SimObject* pObject, S32 pos), (nullAsType<SimObject*>(), -1), "(object, pos) insert object at position") 1527{ 1528 object->insert(pObject, pos); 1529} 1530 1531DefineEngineMethod(GuiMenuBar, findMenu, S32, (const char* barTitle), (""), "(barTitle)") 1532{ 1533 PopupMenu* menu = object->findMenu(barTitle); 1534 1535 if (menu) 1536 return menu->getId(); 1537 else 1538 return 0; 1539} 1540