popupMenu.cpp

Engine/source/gui/editor/popupMenu.cpp

More...

Classes:

class

Event class used to remove popup menus from the event notification in a safe way.

Public Variables

Public Functions

ConsoleDocClass(PopupMenu , "@brief <a href="/coding/class/classpopupmenu/">PopupMenu</a> represents <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> system <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu.\n\n</a>" "You can add menu items <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the menu, but there is no torque object associated " "with these menu items, they exist only in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> platform specific <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manner.\n\n</a>" " @note Internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only\n\n</a>" " @internal" )
DefineEngineMethod(PopupMenu , checkItem , void , (S32 pos, bool checked) , "(pos, checked)" )
DefineEngineMethod(PopupMenu , checkRadioItem , void , (S32 firstPos, S32 lastPos, S32 checkPos) , "(firstPos, lastPos, checkPos)" )
DefineEngineMethod(PopupMenu , clearItems , void , () , "()" )
DefineEngineMethod(PopupMenu , enableItem , void , (S32 pos, bool enabled) , "(pos, enabled)" )
DefineEngineMethod(PopupMenu , getItemCount , S32 , () , "()" )
DefineEngineMethod(PopupMenu , getItemText , const char * , (S32 pos) , "(pos)" )
DefineEngineMethod(PopupMenu , insertItem , S32 , (S32 pos, const char *title, const char *accelerator, const char *cmd, S32 bitmapIndex) , ("", "", "", -1) , "(pos[, title][, accelerator][, cmd][, bitmapIndex])" )
DefineEngineMethod(PopupMenu , insertSubMenu , S32 , (S32 pos, String title, String subMenu) , "(pos, title, subMenu)" )
DefineEngineMethod(PopupMenu , isItemChecked , bool , (S32 pos) , "(pos)" )
DefineEngineMethod(PopupMenu , removeItem , void , (S32 pos) , "(pos)" )
DefineEngineMethod(PopupMenu , setItem , bool , (S32 pos, const char *title, const char *accelerator, const char *cmd) , ("") , "(pos, title[, accelerator][, cmd])" )
DefineEngineMethod(PopupMenu , showPopup , void , (const char *canvasName, S32 x, S32 y) , (-1, -1) , "(Canvas,[x, y])" )

Detailed Description

Public Variables

U32 sMaxPopupGUID 

Public Functions

ConsoleDocClass(PopupMenu , "@brief <a href="/coding/class/classpopupmenu/">PopupMenu</a> represents <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> system <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">menu.\n\n</a>" "You can add menu items <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the menu, but there is no torque object associated " "with these menu items, they exist only in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> platform specific <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manner.\n\n</a>" " @note Internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only\n\n</a>" " @internal" )

DefineEngineMethod(PopupMenu , checkItem , void , (S32 pos, bool checked) , "(pos, checked)" )

DefineEngineMethod(PopupMenu , checkRadioItem , void , (S32 firstPos, S32 lastPos, S32 checkPos) , "(firstPos, lastPos, checkPos)" )

DefineEngineMethod(PopupMenu , clearItems , void , () , "()" )

DefineEngineMethod(PopupMenu , enableItem , void , (S32 pos, bool enabled) , "(pos, enabled)" )

DefineEngineMethod(PopupMenu , getItemCount , S32 , () , "()" )

DefineEngineMethod(PopupMenu , getItemText , const char * , (S32 pos) , "(pos)" )

DefineEngineMethod(PopupMenu , insertItem , S32 , (S32 pos, const char *title, const char *accelerator, const char *cmd, S32 bitmapIndex) , ("", "", "", -1) , "(pos[, title][, accelerator][, cmd][, bitmapIndex])" )

DefineEngineMethod(PopupMenu , insertSubMenu , S32 , (S32 pos, String title, String subMenu) , "(pos, title, subMenu)" )

DefineEngineMethod(PopupMenu , isItemChecked , bool , (S32 pos) , "(pos)" )

DefineEngineMethod(PopupMenu , removeItem , void , (S32 pos) , "(pos)" )

DefineEngineMethod(PopupMenu , setItem , bool , (S32 pos, const char *title, const char *accelerator, const char *cmd) , ("") , "(pos, title[, accelerator][, cmd])" )

DefineEngineMethod(PopupMenu , showPopup , void , (const char *canvasName, S32 x, S32 y) , (-1, -1) , "(Canvas,[x, y])" )

IMPLEMENT_CONOBJECT(PopupMenu )

  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#include "gui/editor/popupMenu.h"
 24#include "console/consoleTypes.h"
 25#include "console/engineAPI.h"
 26#include "gui/core/guiCanvas.h"
 27#include "core/util/safeDelete.h"
 28#include "gui/editor/guiPopupMenuCtrl.h"
 29#include "gui/editor/guiMenuBar.h"
 30
 31static U32 sMaxPopupGUID = 0;
 32PopupMenuEvent PopupMenu::smPopupMenuEvent;
 33bool PopupMenu::smSelectionEventHandled = false;
 34
 35/// Event class used to remove popup menus from the event notification in a safe way
 36class PopUpNotifyRemoveEvent : public SimEvent
 37{   
 38public:
 39   void process(SimObject *object)
 40   {
 41      PopupMenu::smPopupMenuEvent.remove((PopupMenu *)object, &PopupMenu::handleSelectEvent);
 42   }
 43};
 44
 45//-----------------------------------------------------------------------------
 46// Constructor/Destructor
 47//-----------------------------------------------------------------------------
 48PopupMenu::PopupMenu()
 49{
 50   mMenuItems = NULL;
 51   mMenuBarCtrl = nullptr;
 52
 53   mBarTitle = StringTable->EmptyString();
 54   mBounds = RectI(0, 0, 64, 64);
 55   mVisible = false;
 56
 57   mBitmapIndex = -1;
 58   mDrawBitmapOnly = false;
 59   mDrawBorder = false;
 60
 61   mTextList = nullptr;
 62
 63   mIsSubmenu = false;
 64
 65   mRadioSelection = true;
 66}
 67
 68PopupMenu::~PopupMenu()
 69{
 70   PopupMenu::smPopupMenuEvent.remove(this, &PopupMenu::handleSelectEvent);
 71}
 72
 73IMPLEMENT_CONOBJECT(PopupMenu);
 74
 75ConsoleDocClass( PopupMenu,
 76   "@brief PopupMenu represents a system menu.\n\n"
 77   "You can add menu items to the menu, but there is no torque object associated "
 78   "with these menu items, they exist only in a  platform specific manner.\n\n"
 79   "@note Internal use only\n\n"
 80   "@internal"
 81);
 82
 83//-----------------------------------------------------------------------------
 84void PopupMenu::initPersistFields()
 85{
 86   Parent::initPersistFields();
 87
 88   addField("barTitle", TypeCaseString, Offset(mBarTitle, PopupMenu), "");
 89   addField("radioSelection", TypeBool, Offset(mRadioSelection, PopupMenu), "");
 90   addField("visible", TypeBool, Offset(mVisible, PopupMenu), "");
 91}
 92
 93//-----------------------------------------------------------------------------
 94bool PopupMenu::onAdd()
 95{
 96   if(! Parent::onAdd())
 97      return false;
 98
 99   Con::executef(this, "onAdd");
100   return true;
101}
102
103void PopupMenu::onRemove()
104{
105   Con::executef(this, "onRemove");
106
107   Parent::onRemove();
108}
109
110//-----------------------------------------------------------------------------
111void PopupMenu::onMenuSelect()
112{
113   Con::executef(this, "onMenuSelect");
114}
115
116//-----------------------------------------------------------------------------
117void PopupMenu::handleSelectEvent(U32 popID, U32 command)
118{  
119}
120
121//-----------------------------------------------------------------------------
122bool PopupMenu::onMessageReceived(StringTableEntry queue, const char* event, const char* data)
123{
124   return Con::executef(this, "onMessageReceived", queue, event, data);
125}
126
127bool PopupMenu::onMessageObjectReceived(StringTableEntry queue, Message *msg )
128{
129   return Con::executef(this, "onMessageReceived", queue, Con::getIntArg(msg->getId()));
130}
131
132//////////////////////////////////////////////////////////////////////////
133// Platform Menu Data
134//////////////////////////////////////////////////////////////////////////
135GuiMenuBar* PopupMenu::getMenuBarCtrl()
136{
137   return mMenuBarCtrl;
138}
139
140//////////////////////////////////////////////////////////////////////////
141// Public Methods
142//////////////////////////////////////////////////////////////////////////
143S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator, const char* cmd, S32 bitmapIndex)
144{
145   String titleString = title;
146
147   MenuItem newItem;
148   newItem.mID = pos;
149   newItem.mText = titleString;
150   newItem.mCMD = cmd;
151   newItem.mBitmapIndex = bitmapIndex;
152
153   if (titleString.isEmpty() || titleString == String("-"))
154      newItem.mIsSpacer = true;
155   else
156      newItem.mIsSpacer = false;
157
158   if (accelerator[0])
159      newItem.mAccelerator = dStrdup(accelerator);
160   else
161      newItem.mAccelerator = NULL;
162
163   newItem.mVisible = true;
164   newItem.mIsChecked = false;
165   newItem.mAcceleratorIndex = 0;
166   newItem.mEnabled = !newItem.mIsSpacer;
167
168   newItem.mIsSubmenu = false;
169   newItem.mSubMenu = nullptr;
170   newItem.mSubMenuParentMenu = nullptr;
171
172   mMenuItems.push_back(newItem);
173
174   return pos;
175}
176
177S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu)
178{
179   S32 itemPos = insertItem(pos, title, "", "");
180
181   mMenuItems[itemPos].mIsSubmenu = true;
182   mMenuItems[itemPos].mSubMenu = submenu;
183   mMenuItems[itemPos].mSubMenuParentMenu = this;
184
185   submenu->mIsSubmenu = true;
186
187   return itemPos;
188}
189
190bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator, const char* cmd)
191{
192   String titleString = title;
193
194   for (U32 i = 0; i < mMenuItems.size(); i++)
195   {
196      if (mMenuItems[i].mText == titleString)
197      {
198         mMenuItems[i].mID = pos;
199         mMenuItems[i].mCMD = cmd;
200         
201         if (accelerator && accelerator[0])
202            mMenuItems[i].mAccelerator = dStrdup(accelerator);
203         else
204            mMenuItems[i].mAccelerator = NULL;
205         return true;
206      }
207   }
208   
209   return false;
210}
211
212void PopupMenu::removeItem(S32 itemPos)
213{
214   if (mMenuItems.empty() || mMenuItems.size() < itemPos || itemPos < 0)
215      return;
216
217   mMenuItems.erase(itemPos);
218}
219
220//////////////////////////////////////////////////////////////////////////
221void PopupMenu::enableItem(S32 pos, bool enable)
222{
223   if (mMenuItems.empty() || mMenuItems.size() < pos || pos < 0)
224      return;
225
226   mMenuItems[pos].mEnabled = enable;
227}
228
229void PopupMenu::checkItem(S32 pos, bool checked)
230{
231   if (mMenuItems.empty() || mMenuItems.size() < pos || pos < 0)
232      return;
233
234   if (checked && mMenuItems[pos].mCheckGroup != -1 && mRadioSelection)
235   {
236      // first, uncheck everything in the group:
237      for (U32 i = 0; i < mMenuItems.size(); i++)
238         if (mMenuItems[i].mCheckGroup == mMenuItems[pos].mCheckGroup && mMenuItems[i].mIsChecked)
239            mMenuItems[i].mIsChecked = false;
240   }
241
242   mMenuItems[pos].mIsChecked = checked;
243}
244
245void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos)
246{
247   for (U32 i = 0; i < mMenuItems.size(); i++)
248   {
249      if (mMenuItems[i].mID >= firstPos && mMenuItems[i].mID <= lastPos)
250      {
251         mMenuItems[i].mIsChecked = false;
252      }
253   }
254}
255
256bool PopupMenu::isItemChecked(S32 pos)
257{
258   if (mMenuItems.empty() || mMenuItems.size() < pos || pos < 0)
259      return false;
260
261   return mMenuItems[pos].mIsChecked;
262}
263
264U32 PopupMenu::getItemCount()
265{
266   return mMenuItems.size();
267}
268
269void PopupMenu::clearItems()
270{
271   mMenuItems.clear();
272}
273
274String PopupMenu::getItemText(S32 pos)
275{
276   if (mMenuItems.empty() || mMenuItems.size() < pos || pos < 0)
277      return String::EmptyString;
278
279   return mMenuItems[pos].mText;
280}
281
282//////////////////////////////////////////////////////////////////////////
283bool PopupMenu::canHandleID(U32 id)
284{
285   return true;
286}
287
288bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */)
289{
290   return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(command), text ? text : ""));
291}
292
293//////////////////////////////////////////////////////////////////////////
294void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */)
295{
296   if (owner == NULL)
297      return;
298
299   GuiPopupMenuBackgroundCtrl* backgroundCtrl;
300   Sim::findObject("PopUpMenuControl", backgroundCtrl);
301
302   GuiControlProfile* profile;
303   Sim::findObject("ToolsGuiMenuBarProfile", profile);
304
305   if (!profile)
306      return;
307
308   if (mTextList == nullptr)
309   {
310      mTextList = new GuiPopupMenuTextListCtrl();
311      mTextList->registerObject();
312      mTextList->setControlProfile(profile);
313      mTextList->mRowHeightPadding = 5;
314
315      mTextList->mPopup = this;
316      mTextList->mMenuBar = getMenuBarCtrl();
317   }
318
319   if (!backgroundCtrl)
320   {
321      backgroundCtrl = new GuiPopupMenuBackgroundCtrl();
322
323      backgroundCtrl->registerObject("PopUpMenuControl");
324   }
325
326   if (!backgroundCtrl || !mTextList)
327      return;
328
329   if (!mIsSubmenu)
330   {
331      //if we're a 'parent' menu, then tell the background to clear out all existing other popups
332
333      backgroundCtrl->clearPopups();
334   }
335
336   //find out if we're doing a first-time add
337   S32 popupIndex = backgroundCtrl->findPopupMenu(this);
338
339   if (popupIndex == -1)
340   {
341      backgroundCtrl->addObject(mTextList);
342      backgroundCtrl->mPopups.push_back(this);
343   }
344
345   mTextList->mBackground = backgroundCtrl;
346
347   owner->pushDialogControl(backgroundCtrl, 10);
348
349   //Set the background control's menubar, if any, and if it's not already set
350   if(backgroundCtrl->mMenuBarCtrl == nullptr)
351      backgroundCtrl->mMenuBarCtrl = getMenuBarCtrl();
352
353   backgroundCtrl->setExtent(owner->getExtent());
354
355   mTextList->clear();
356
357   S32 textWidth = 0, width = 0;
358   S32 acceleratorWidth = 0;
359   GFont *font = profile->mFont;
360
361   Point2I maxBitmapSize = Point2I(0, 0);
362
363   S32 numBitmaps = profile->mBitmapArrayRects.size();
364   if (numBitmaps)
365   {
366      RectI *bitmapBounds = profile->mBitmapArrayRects.address();
367      for (S32 i = 0; i < numBitmaps; i++)
368      {
369         if (bitmapBounds[i].extent.x > maxBitmapSize.x)
370            maxBitmapSize.x = bitmapBounds[i].extent.x;
371         if (bitmapBounds[i].extent.y > maxBitmapSize.y)
372            maxBitmapSize.y = bitmapBounds[i].extent.y;
373      }
374   }
375
376   for (U32 i = 0; i < mMenuItems.size(); i++)
377   {
378      if (!mMenuItems[i].mVisible)
379         continue;
380
381      S32 iTextWidth = font->getStrWidth(mMenuItems[i].mText.c_str());
382      S32 iAcceleratorWidth = mMenuItems[i].mAccelerator ? font->getStrWidth(mMenuItems[i].mAccelerator) : 0;
383
384      if (iTextWidth > textWidth)
385         textWidth = iTextWidth;
386      if (iAcceleratorWidth > acceleratorWidth)
387         acceleratorWidth = iAcceleratorWidth;
388   }
389
390   width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
391
392   mTextList->setCellSize(Point2I(width, font->getHeight() + 2));
393   mTextList->clearColumnOffsets();
394   mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
395   mTextList->addColumnOffset(maxBitmapSize.x + 1);
396   mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
397
398   U32 entryCount = 0;
399
400   for (U32 i = 0; i < mMenuItems.size(); i++)
401   {
402      if (!mMenuItems[i].mVisible)
403         continue;
404
405      char buf[512];
406
407      //  If this menu item is a submenu, then set the isSubmenu to 2 to indicate
408      // an arrow should be drawn.  Otherwise set the isSubmenu normally.
409      char isSubmenu = 1;
410      if (mMenuItems[i].mIsSubmenu)
411         isSubmenu = 2;
412
413      char bitmapIndex = 1;
414      if (mMenuItems[i].mBitmapIndex >= 0 && (mMenuItems[i].mBitmapIndex * 3 <= profile->mBitmapArrayRects.size()))
415         bitmapIndex = mMenuItems[i].mBitmapIndex + 2;
416
417      dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, mMenuItems[i].mText.c_str(), mMenuItems[i].mAccelerator ? mMenuItems[i].mAccelerator : "");
418      mTextList->addEntry(entryCount, buf);
419
420      if (!mMenuItems[i].mEnabled)
421         mTextList->setEntryActive(entryCount, false);
422
423      entryCount++;
424   }
425
426   Point2I pos = Point2I::Zero;
427
428   if (x == -1 && y == -1)
429      pos = owner->getCursorPos();
430   else
431      pos = Point2I(x, y);
432
433   mTextList->setPosition(pos);
434
435   //nudge in if we'd overshoot the screen
436   S32 widthDiff = (mTextList->getPosition().x + mTextList->getExtent().x) - backgroundCtrl->getWidth();
437   if (widthDiff > 0)
438   {
439      Point2I popupPos = mTextList->getPosition();
440      mTextList->setPosition(popupPos.x - widthDiff, popupPos.y);
441   }
442
443   //If we'd overshoot the screen vertically, just mirror the axis so we're above the mouse
444   S32 heightDiff = (mTextList->getPosition().y + mTextList->getExtent().y) - backgroundCtrl->getHeight();
445   if (heightDiff > 0)
446   {
447      Point2I popupPos = mTextList->getPosition();
448      mTextList->setPosition(popupPos.x, popupPos.y - mTextList->getExtent().y);
449   }
450
451
452   mTextList->setHidden(false);
453
454   mVisible = true;
455}
456
457void PopupMenu::hidePopup()
458{
459   if (mTextList)
460   {
461      mTextList->setHidden(true);
462   }
463
464   hidePopupSubmenus();
465
466   mVisible = false;
467}
468
469void PopupMenu::hidePopupSubmenus()
470{
471   for (U32 i = 0; i < mMenuItems.size(); i++)
472   {
473      if (mMenuItems[i].mSubMenu != nullptr)
474         mMenuItems[i].mSubMenu->hidePopup();
475   }
476}
477
478//-----------------------------------------------------------------------------
479// Console Methods
480//-----------------------------------------------------------------------------
481DefineEngineMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator, const char* cmd, S32 bitmapIndex), ("", "", "", -1), "(pos[, title][, accelerator][, cmd][, bitmapIndex])")
482{
483   return object->insertItem(pos, title, accelerator, cmd, bitmapIndex);
484}
485
486DefineEngineMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)")
487{
488   object->removeItem(pos);
489}
490
491DefineEngineMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, String subMenu), , "(pos, title, subMenu)")
492{
493   PopupMenu *mnu = dynamic_cast<PopupMenu *>(Sim::findObject(subMenu));
494   if(mnu == NULL)
495   {
496      Con::errorf("PopupMenu::insertSubMenu - Invalid PopupMenu object specified for submenu");
497      return -1;
498   }
499   return object->insertSubMenu(pos, title, mnu);
500}
501
502DefineEngineMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator, const char *cmd), (""), "(pos, title[, accelerator][, cmd])")
503{
504   return object->setItem(pos, title, accelerator, cmd);
505}
506
507//-----------------------------------------------------------------------------
508
509DefineEngineMethod(PopupMenu, enableItem, void, (S32 pos, bool enabled), , "(pos, enabled)")
510{
511   object->enableItem(pos, enabled);
512}
513
514DefineEngineMethod(PopupMenu, checkItem, void, (S32 pos, bool checked), , "(pos, checked)")
515{
516   object->checkItem(pos, checked);
517}
518
519DefineEngineMethod(PopupMenu, getItemText, const char*, (S32 pos), , "(pos)")
520{
521   return object->getItemText(pos).c_str();
522}
523
524
525DefineEngineMethod(PopupMenu, checkRadioItem, void, (S32 firstPos, S32 lastPos, S32 checkPos), , "(firstPos, lastPos, checkPos)")
526{
527   object->checkRadioItem(firstPos, lastPos, checkPos);
528}
529
530DefineEngineMethod(PopupMenu, isItemChecked, bool, (S32 pos), , "(pos)")
531{
532   return object->isItemChecked(pos);
533}
534
535DefineEngineMethod(PopupMenu, getItemCount, S32, (), , "()")
536{
537   return object->getItemCount();
538}
539
540DefineEngineMethod(PopupMenu, clearItems, void, (), , "()")
541{
542   return object->clearItems();
543}
544
545//-----------------------------------------------------------------------------
546DefineEngineMethod(PopupMenu, showPopup, void, (const char * canvasName, S32 x, S32 y), ( -1, -1), "(Canvas,[x, y])")
547{
548   GuiCanvas *pCanvas = dynamic_cast<GuiCanvas*>(Sim::findObject(canvasName));
549   object->showPopup(pCanvas, x, y);
550}
551