⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guimenubar.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

#include "console/consoleTypes.h"
#include "console/console.h"
#include "dgl/dgl.h"
#include "gui/core/guiCanvas.h"
#include "gui/core/guiDefaultControlRender.h"
#include "gui/controls/guiTextListCtrl.h"
#include "sim/actionMap.h"
#include "gui/editor/guiMenuBar.h"

// menu bar:
// basic idea - fixed height control bar at the top of a window, placed and sized in gui editor
// menu text for menus or menu items should not begin with a digit
// all menus can be removed via the clearMenus() console command
// each menu is added via the addMenu(menuText, menuId) console command
// each menu is added with a menu id
// menu items are added to menus via that addMenuItem(menu, menuItemText, menuItemId, accelerator, checkGroup) console command
// each menu item is added with a menu item id and an optional accelerator
// menu items are initially enabled, but can be disabled/re-enabled via the setMenuItemEnable(menu,menuItem,bool)
// menu text can be set via the setMenuText(menu, newMenuText) console method
// menu item text can be set via the setMenuItemText console method
// menu items can be removed via the removeMenuItem(menu, menuItem) console command
// menu items can be cleared via the clearMenuItems(menu) console command
// menus can be hidden or shown via the setMenuVisible(menu, bool) console command
// menu items can be hidden or shown via the setMenuItemVisible(menu, menuItem, bool) console command
// menu items can be check'd via the setMenuItemChecked(menu, menuItem, bool) console command
//    if the bool is true, any other items in that menu item's check group become unchecked.
//
// menu items can have a bitmap set on them via the setMenuItemBitmap(menu, menuItem, bitmapIndex)
//    passing -1 for the bitmap index will result in no bitmap being shown
//    the index paramater is an index into the bitmap array of the associated profile
//    this can be used, for example, to display a check next to a selected menu item
//    bitmap indices are actually multiplied by 3 when indexing into the bitmap
//    since bitmaps have normal, selected and disabled states.
//
// menus can be removed via the removeMenu console command
// specification arguments for menus and menu items can be either the id or the text of the menu or menu item
// adding the menu item "-" will add an un-selectable seperator to the menu
// callbacks:
// when a menu is clicked, before it is displayed, the menu calls its onMenuSelect(menuId, menuText) method -
//    this allows the callback to enable/disable menu items, or add menu items in a context-sensitive way
// when a menu item is clicked, the menu removes itself from display, then calls onMenuItemSelect(menuId, menuText, menuItemId, menuItemText)

// the initial implementation does not support:
//    hierarchal menus
//    keyboard accelerators on menu text (i.e. via alt-key combos)

//------------------------------------------------------------------------------

IMPLEMENT_CONOBJECT(GuiMenuBar);

//------------------------------------------------------------------------------
// console methods
//------------------------------------------------------------------------------

ConsoleMethod(GuiMenuBar, clearMenus, void, 2, 2, "() - clears all the menus from the menu bar.")
{
   object->clearMenus();
}

ConsoleMethod(GuiMenuBar, addMenu, void, 4, 4, "(string menuText, int menuId) - adds a new menu to the menu bar.")
{
   if(dIsdigit(argv[2][0]))
   {
      Con::errorf("Cannot add menu %s (id = %s).  First character of a menu's text cannot be a digit.", argv[2], argv[3]);
      return;
   }
   object->addMenu(argv[2], dAtoi(argv[3]));
}

ConsoleMethod(GuiMenuBar, addMenuItem, void, 5, 7, "(string menu, string menuItemText, int menuItemId, string accelerator = NULL, int checkGroup = -1) - adds a menu item to the specified menu.  The menu argument can be either the text of a menu or its id.")
{
   if(dIsdigit(argv[3][0]))
   {
      Con::errorf("Cannot add menu item %s (id = %s).  First character of a menu item's text cannot be a digit.", argv[3], argv[4]);
      return;
   }
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for addMenuItem.", argv[2]);
      return;
   }
   object->addMenuItem(menu, argv[3], dAtoi(argv[4]), argc == 5 ? "" : argv[5], argc < 7 ? -1 : dAtoi(argv[6]));
}

ConsoleMethod(GuiMenuBar, setMenuItemEnable, void, 5, 5, "(string menu, string menuItem, bool enabled) - sets the menu item to enabled or disabled based on the enable parameter.  The specified menu and menu item can either be text or ids.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for setMenuItemEnable.", argv[2]);
      return;
   }
   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
   if(!menuItem)
   {
      Con::errorf("Cannot find menu item %s for setMenuItemEnable.", argv[3]);
      return;
   }
   menuItem->enabled = dAtob(argv[4]);
}

ConsoleMethod(GuiMenuBar, setMenuItemChecked, void, 5, 5, "(string menu, string menuItem, bool checked) - sets the menu item bitmap to a check mark, which must be the first element in the bitmap array.  Any other menu items in the menu with the same check group become unchecked if they are checked.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for setMenuItemChecked.", argv[2]);
      return;
   }
   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
   if(!menuItem)
   {
      Con::errorf("Cannot find menu item %s for setMenuItemChecked.", argv[3]);
      return;
   }
   bool checked = dAtob(argv[4]);
   if(checked && menuItem->checkGroup != -1)
   {
      // first, uncheck everything in the group:
      for(GuiMenuBar::MenuItem *itemWalk = menu->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem)
         if(itemWalk->checkGroup == menuItem->checkGroup && itemWalk->bitmapIndex == 0)
            itemWalk->bitmapIndex = -1;
   }
   menuItem->bitmapIndex = checked ? 0 : -1;
}

ConsoleMethod(GuiMenuBar, setMenuText, void, 4, 4, "(string menu, string newMenuText) - sets the text of the specified menu to the new string.")
{
   if(dIsdigit(argv[3][0]))
   {
      Con::errorf("Cannot name menu %s to %s.  First character of a menu's text cannot be a digit.", argv[2], argv[3]);
      return;
   }
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for setMenuText.", argv[2]);
      return;
   }
   dFree(menu->text);
   menu->text = dStrdup(argv[3]);
   object->menuBarDirty = true;
}

ConsoleMethod(GuiMenuBar, setMenuVisible, void, 4, 4, "(string menu, bool visible) - sets the whether or not to display the specified menu.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for setMenuVisible.", argv[2]);
      return;
   }
   menu->visible = dAtob(argv[3]);
   object->menuBarDirty = true;
   object->setUpdate();
}

ConsoleMethod(GuiMenuBar, setMenuItemText, void, 5, 5, "(string menu, string menuItem, string newMenuItemText) - sets the text of the specified menu item to the new string.")
{
   if(dIsdigit(argv[4][0]))
   {
      Con::errorf("Cannot name menu item %s to %s.  First character of a menu item's text cannot be a digit.", argv[3], argv[4]);
      return;
   }
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for setMenuItemText.", argv[2]);
      return;
   }
   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
   if(!menuItem)
   {
      Con::errorf("Cannot find menu item %s for setMenuItemText.", argv[3]);
      return;
   }
   dFree(menuItem->text);
   menuItem->text = dStrdup(argv[4]);
}

ConsoleMethod(GuiMenuBar, setMenuItemVisible, void, 5, 5, "(string menu, string menuItem, bool isVisible) - sets the specified menu item to be either visible or not.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for setMenuItemVisible.", argv[2]);
      return;
   }
   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
   if(!menuItem)
   {
      Con::errorf("Cannot find menu item %s for setMenuItemVisible.", argv[3]);
      return;
   }
   menuItem->visible = dAtob(argv[4]);
}

ConsoleMethod(GuiMenuBar, setMenuItemBitmap, void, 5, 5, "(string menu, string menuItem, int bitmapIndex) - sets the specified menu item bitmap index in the bitmap array.  Setting the item's index to -1 will remove any bitmap.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for setMenuItemBitmap.", argv[2]);
      return;
   }
   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
   if(!menuItem)
   {
      Con::errorf("Cannot find menu item %s for setMenuItemBitmap.", argv[3]);
      return;
   }
   menuItem->bitmapIndex = dAtoi(argv[4]);
}

ConsoleMethod(GuiMenuBar, removeMenuItem, void, 4, 4, "(string menu, string menuItem) - removes the specified menu item from the menu.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for removeMenuItem.", argv[2]);
      return;
   }
   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, argv[3]);
   if(!menuItem)
   {
      Con::errorf("Cannot find menu item %s for removeMenuItem.", argv[3]);
      return;
   }
   object->removeMenuItem(menu, menuItem);
}

ConsoleMethod(GuiMenuBar, clearMenuItems, void, 3, 3, "(string menu) - removes all the menu items from the specified menu.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for clearMenuItems.", argv[2]);
      return;
   }
   object->clearMenuItems(menu);
}

ConsoleMethod(GuiMenuBar, removeMenu, void, 3, 3, "(string menu) - removes the specified menu from the menu bar.")
{
   GuiMenuBar::Menu *menu = object->findMenu(argv[2]);
   if(!menu)
   {
      Con::errorf("Cannot find menu %s for removeMenu.", argv[2]);
      return;
   }
   object->clearMenuItems(menu);
   object->menuBarDirty = true;
}

//------------------------------------------------------------------------------
// menu management methods
//------------------------------------------------------------------------------

void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
{
   // allocate the menu
   Menu *newMenu = new Menu;
   newMenu->text = dStrdup(menuText);
   newMenu->id = menuId;
   newMenu->nextMenu = NULL;
   newMenu->firstMenuItem = NULL;
   newMenu->visible = true;

   // add it to the menu list
   menuBarDirty = true;
   Menu **walk;
	for(walk = &menuList; *walk; walk = &(*walk)->nextMenu)
      ;
   *walk = newMenu;
}

GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu)
{
	if(dIsdigit(menu[0]))
	{
		U32 id = dAtoi(menu);
		for(Menu *walk = menuList; walk; walk = walk->nextMenu)
			if(id == walk->id)
				return walk;
		return NULL;
	}
	else
	{
		for(Menu *walk = menuList; walk; walk = walk->nextMenu)
			if(!dStricmp(menu, walk->text))
				return walk;
		return NULL;
	}
}

GuiMenuBar::MenuItem *GuiMenuBar::findMenuItem(Menu *menu, const char *menuItem)
{
   if(dIsdigit(menuItem[0]))
   {
      U32 id = dAtoi(menuItem);
      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
         if(id == walk->id)
            return walk;
      return NULL;
   }
   else
   {
      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
         if(!dStricmp(menuItem, walk->text))
            return walk;
      return NULL;
   }
}

void GuiMenuBar::removeMenu(Menu *menu)
{
   menuBarDirty = true;
   clearMenuItems(menu);
   for(Menu **walk = &menuList; *walk; walk = &(*walk)->nextMenu)
   {
      if(*walk == menu)
      {
         *walk = menu->nextMenu;
         break;
      }
   }
   dFree(menu->text);
   delete menu;
}

void GuiMenuBar::removeMenuItem(Menu *menu, MenuItem *menuItem)
{
   for(MenuItem **walk = &menu->firstMenuItem; *walk; walk = &(*walk)->nextMenuItem)
   {
      if(*walk == menuItem)
      {
         *walk = menuItem->nextMenuItem;
         break;
      }
   }
   dFree(menuItem->text);
   dFree(menuItem->accelerator);
   delete menuItem;
}

void GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup)
{
   // allocate the new menu item
   MenuItem *newMenuItem = new MenuItem;
   newMenuItem->text = dStrdup(text);
   if(accelerator[0])
      newMenuItem->accelerator = dStrdup(accelerator);
   else
      newMenuItem->accelerator = NULL;
   newMenuItem->id = id;
   newMenuItem->checkGroup = checkGroup;
   newMenuItem->nextMenuItem = NULL;
   newMenuItem->acceleratorIndex = 0;
   newMenuItem->enabled = text[0] != '-';
   newMenuItem->visible = true;
   newMenuItem->bitmapIndex = -1;

   // link it into the menu's menu item list
   MenuItem **walk = &menu->firstMenuItem;
   while(*walk)
      walk = &(*walk)->nextMenuItem;
   *walk = newMenuItem;

}

void GuiMenuBar::clearMenuItems(Menu *menu)
{
   while(menu->firstMenuItem)
      removeMenuItem(menu, menu->firstMenuItem);
}

void GuiMenuBar::clearMenus()
{
   while(menuList)
      removeMenu(menuList);
}

//------------------------------------------------------------------------------
// initialization, input and render methods
//------------------------------------------------------------------------------

GuiMenuBar::GuiMenuBar()
{
	menuList = NULL;
   menuBarDirty = true;
   mouseDownMenu = NULL;
   mouseOverMenu = NULL;
   mCurAcceleratorIndex = 0;
   mBackground = NULL;
}

bool GuiMenuBar::onWake()
{
   if(!Parent::onWake())
      return false;
   mProfile->constructBitmapArray();  // if a bitmap was specified...
   maxBitmapSize.set(0,0);
   S32 numBitmaps = mProfile->mBitmapArrayRects.size();
   if(numBitmaps)
   {
      RectI *bitmapBounds = mProfile->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;
      }
   }
   return true;
}

GuiMenuBar::Menu *GuiMenuBar::findHitMenu(Point2I mousePoint)
{
   Point2I pos = globalToLocalCoord(mousePoint);

   for(Menu *walk = menuList; walk; walk = walk->nextMenu)
      if(walk->visible && walk->bounds.pointInRect(pos))
         return walk;
   return NULL;
}

void GuiMenuBar::onPreRender()
{
   Parent::onPreRender();
   if(menuBarDirty)
   {
      menuBarDirty = false;
      U32 curX = 0;
      for(Menu *walk = menuList; walk; walk = walk->nextMenu)
      {
         if(!walk->visible)
            continue;
         walk->bounds.set(curX, 1, mProfile->mFont->getStrWidth((const UTF8 *)walk->text) + 12, mBounds.extent.y - 2);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -