MyGUI  3.2.1
MyGUI_MenuControl.cpp
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #include "MyGUI_Precompiled.h"
00008 #include "MyGUI_MenuControl.h"
00009 #include "MyGUI_ResourceSkin.h"
00010 #include "MyGUI_MenuItem.h"
00011 #include "MyGUI_ImageBox.h"
00012 #include "MyGUI_MenuBar.h"
00013 #include "MyGUI_WidgetManager.h"
00014 #include "MyGUI_LayerManager.h"
00015 #include "MyGUI_ControllerManager.h"
00016 #include "MyGUI_InputManager.h"
00017 #include "MyGUI_Gui.h"
00018 #include "MyGUI_RenderManager.h"
00019 
00020 namespace MyGUI
00021 {
00022 
00023     const float POPUP_MENU_SPEED_COEF = 3.0f;
00024 
00025     MenuControl::MenuControl() :
00026         mHideByAccept(true),
00027         mMenuDropMode(false),
00028         mIsMenuDrop(true),
00029         mHideByLostKey(false),
00030         mResizeToContent(true),
00031         mShutdown(false),
00032         mVerticalAlignment(true),
00033         mDistanceButton(0),
00034         mPopupAccept(false),
00035         mOwner(nullptr),
00036         mAnimateSmooth(false),
00037         mChangeChildSkin(false),
00038         mClient(nullptr),
00039         mInternalCreateChild(false)
00040     {
00041     }
00042 
00043     void MenuControl::initialiseOverride()
00044     {
00045         Base::initialiseOverride();
00046 
00047         // инициализируем овнера
00048         Widget* parent = getParent();
00049         if (parent)
00050         {
00051             mOwner = parent->castType<MenuItem>(false);
00052             if (!mOwner)
00053             {
00054                 Widget* client = parent;
00055                 parent = client->getParent();
00056                 if (parent && parent->getClientWidget())
00057                 {
00058                     mOwner = parent->castType<MenuItem>(false);
00059                 }
00060             }
00061         }
00062 
00063         // FIXME нам нужен фокус клавы
00064         setNeedKeyFocus(true);
00065 
00067         assignWidget(mClient, "Client");
00068         if (mClient != nullptr)
00069         {
00070             setWidgetClient(mClient);
00071         }
00072 
00073         //OBSOLETE
00074         if (isUserString("SkinLine"))
00075         {
00076             mItemNormalSkin = getUserString("SkinLine");
00077             mItemPopupSkin = mItemNormalSkin;
00078         }
00079 
00080         if (isUserString("SeparatorSkin"))
00081             mItemSeparatorSkin = getUserString("SeparatorSkin");
00082 
00083         if (isUserString("NormalSkin"))
00084             mItemNormalSkin = getUserString("NormalSkin");
00085 
00086         if (isUserString("PopupSkin"))
00087             mItemPopupSkin = getUserString("PopupSkin");
00088 
00089         if (isUserString("DistanceButton"))
00090             mDistanceButton = utility::parseValue<int>(getUserString("DistanceButton"));
00091 
00092         if (isUserString("SubMenuSkin"))
00093             mSubMenuSkin = getUserString("SubMenuSkin");
00094 
00095         if (isUserString("SubMenuLayer"))
00096             mSubMenuLayer = getUserString("SubMenuLayer");
00097 
00098         // FIXME добавленно, так как шетдаун вызывается и при смене скина
00099         mShutdown = false;
00100     }
00101 
00102     void MenuControl::shutdownOverride()
00103     {
00104         mShutdown = true;
00105 
00106         if (mOwner != nullptr)
00107             mOwner->getMenuCtrlParent()->_notifyDeletePopup(mOwner);
00108 
00109         Base::shutdownOverride();
00110     }
00111 
00112     void MenuControl::onWidgetCreated(Widget* _widget)
00113     {
00114         Base::onWidgetCreated(_widget);
00115 
00116         MenuItem* child = _widget->castType<MenuItem>(false);
00117         if (child != nullptr && !mInternalCreateChild)
00118         {
00119             _wrapItem(child, mItemsInfo.size(), "", MenuItemType::Normal, "", Any::Null);
00120         }
00121     }
00122 
00123     MenuItem* MenuControl::insertItemAt(size_t _index, const UString& _name, MenuItemType _type, const std::string& _id, Any _data)
00124     {
00125         MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "MenuControl::insertItemAt");
00126         if (_index == ITEM_NONE) _index = mItemsInfo.size();
00127 
00128         mInternalCreateChild = true;
00129         MenuItem* item = _getClientWidget()->createWidget<MenuItem>(getSkinByType(_type), IntCoord(), Align::Default);
00130         mInternalCreateChild = false;
00131         _wrapItem(item, _index, _name, _type, _id, _data);
00132 
00133         return item;
00134     }
00135 
00136     void MenuControl::removeItemAt(size_t _index)
00137     {
00138         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::removeItemAt");
00139 
00140         if (mItemsInfo[_index].submenu)
00141         {
00142             WidgetManager::getInstance().destroyWidget(mItemsInfo[_index].submenu);
00143             mItemsInfo[_index].submenu = nullptr;
00144         }
00145         WidgetManager::getInstance().destroyWidget(mItemsInfo[_index].item);
00146     }
00147 
00148     void MenuControl::removeAllItems()
00149     {
00150         while (!mItemsInfo.empty())
00151         {
00152             if (mItemsInfo.back().submenu)
00153             {
00154                 WidgetManager::getInstance().destroyWidget(mItemsInfo.back().submenu);
00155                 mItemsInfo.back().submenu = nullptr;
00156             }
00157             WidgetManager::getInstance().destroyWidget(mItemsInfo.back().item);
00158         }
00159     }
00160 
00161     const UString& MenuControl::getItemNameAt(size_t _index)
00162     {
00163         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemNameAt");
00164         return mItemsInfo[_index].name;
00165     }
00166 
00167     void MenuControl::update()
00168     {
00169         IntSize size;
00170 
00171         if (mVerticalAlignment)
00172         {
00173             for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter)
00174             {
00175                 IntSize contentSize = iter->item->_getContentSize();
00176                 iter->item->setCoord(0, size.height, _getClientWidget()->getWidth(), contentSize.height);
00177                 size.height += contentSize.height + mDistanceButton;
00178 
00179                 if (contentSize.width > size.width)
00180                     size.width = contentSize.width;
00181             }
00182             if (!mItemsInfo.empty())
00183                 size.height -= mDistanceButton;
00184         }
00185         else
00186         {
00187             int maxHeight = 0;
00188             for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter)
00189             {
00190                 IntSize contentSize = iter->item->_getContentSize();
00191                 if (maxHeight < contentSize.height)
00192                     maxHeight = contentSize.height;
00193             }
00194 
00195             for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter)
00196             {
00197                 IntSize contentSize = iter->item->_getContentSize();
00198                 iter->item->setCoord(size.width, 0, contentSize.width, maxHeight);
00199                 size.width += contentSize.width + mDistanceButton;
00200             }
00201 
00202             if (!mItemsInfo.empty())
00203                 size.width -= mDistanceButton;
00204         }
00205 
00206         if (mResizeToContent)
00207             setSize(size + mCoord.size() - _getClientWidget()->getSize());
00208     }
00209 
00210     void MenuControl::setItemDataAt(size_t _index, Any _data)
00211     {
00212         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemDataAt");
00213         mItemsInfo[_index].data = _data;
00214     }
00215 
00216     MenuControl* MenuControl::getItemChildAt(size_t _index)
00217     {
00218         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemChildAt");
00219         return mItemsInfo[_index].submenu;
00220     }
00221 
00222     void MenuControl::removeItemChildAt(size_t _index)
00223     {
00224         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::removeItemChildAt");
00225 
00226         if (mItemsInfo[_index].submenu != nullptr)
00227         {
00228             WidgetManager::getInstance().destroyWidget(mItemsInfo[_index].submenu);
00229             mItemsInfo[_index].submenu = nullptr;
00230         }
00231 
00232         update();
00233     }
00234 
00235     void MenuControl::setItemNameAt(size_t _index, const UString& _name)
00236     {
00237         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemNameAt");
00238 
00239         mItemsInfo[_index].name = _name;
00240         MenuItem* item = mItemsInfo[_index].item;
00241         item->setCaption(_name);
00242 
00243         update();
00244     }
00245 
00246     void MenuControl::setItemIdAt(size_t _index, const std::string& _id)
00247     {
00248         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemIdAt");
00249         mItemsInfo[_index].id = _id;
00250     }
00251 
00252     const std::string& MenuControl::getItemIdAt(size_t _index)
00253     {
00254         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemIdAt");
00255         return mItemsInfo[_index].id;
00256     }
00257 
00258     void MenuControl::_notifyDeleteItem(MenuItem* _item)
00259     {
00260         // дитю меняем скин
00261         if (mChangeChildSkin)
00262             return;
00263 
00264         // общий шутдаун виджета
00265         if (mShutdown)
00266             return;
00267 
00268         size_t index = getItemIndex(_item);
00269         mItemsInfo.erase(mItemsInfo.begin() + index);
00270         update();
00271     }
00272 
00273     void MenuControl::_notifyDeletePopup(MenuItem* _item)
00274     {
00275         size_t index = getItemIndex(_item);
00276         mItemsInfo[index].submenu = nullptr;
00277     }
00278 
00279     void MenuControl::_notifyUpdateName(MenuItem* _item)
00280     {
00281         size_t index = getItemIndex(_item);
00282         mItemsInfo[index].name = _item->getCaption();
00283 
00284         ISubWidgetText* text = _item->getSubWidgetText();
00285         mItemsInfo[index].width = text ? (text->getTextSize().width + _item->getSize().width - text->getWidth()) : 0;
00286         update();
00287     }
00288 
00289     MenuItemType MenuControl::getItemTypeAt(size_t _index)
00290     {
00291         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemTypeAt");
00292         return mItemsInfo[_index].type;
00293     }
00294 
00295     void MenuControl::setItemTypeAt(size_t _index, MenuItemType _type)
00296     {
00297         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemTypeAt");
00298         ItemInfo& info = mItemsInfo[_index];
00299         if (info.type == _type)
00300             return;
00301 
00302         // сохраняем данные
00303         info.type = _type;
00304 
00305         // при смене скина дите отпишется
00306         mChangeChildSkin = true;
00307         info.item->changeWidgetSkin(getSkinByType(_type));
00308         mChangeChildSkin = false;
00309 
00310         info.item->setImageName(getIconIndexByType(_type ));
00311         info.item->setCaption(info.name);
00312 
00313         update();
00314     }
00315 
00316     void MenuControl::notifyMenuCtrlAccept(MenuItem* _item)
00317     {
00318         if (mHideByAccept)
00319         {
00320             setVisibleSmooth(false);
00321         }
00322         else
00323         {
00324             InputManager::getInstance().setKeyFocusWidget(nullptr);
00325         }
00326 
00327         MenuItem* parent_item = getMenuItemParent();
00328         if (parent_item)
00329         {
00330             MenuControl* parent_ctrl = parent_item->getMenuCtrlParent();
00331             if (parent_ctrl)
00332             {
00333                 parent_ctrl->notifyMenuCtrlAccept(_item);
00334             }
00335         }
00336 
00337         eventMenuCtrlAccept(this, _item);
00338     }
00339 
00340     void MenuControl::setItemChildVisibleAt(size_t _index, bool _visible)
00341     {
00342         _setItemChildVisibleAt(_index, _visible, true);
00343     }
00344 
00345     void MenuControl::_setItemChildVisibleAt(size_t _index, bool _visible, bool _smooth)
00346     {
00347         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemChildVisibleAt");
00348 
00349         if (_visible)
00350         {
00351             if (mItemsInfo[_index].submenu && mItemsInfo[_index].submenu->getItemCount())
00352             {
00353                 int offset = mItemsInfo[0].item->getAbsoluteTop() - getAbsoluteTop();
00354 
00355                 const IntCoord& coord = mItemsInfo[_index].item->getAbsoluteCoord();
00356                 IntPoint point(getAbsoluteRect().right, coord.top - offset);
00357 
00358                 MenuControl* menu = mItemsInfo[_index].submenu;
00359 
00360                 if (mVerticalAlignment)
00361                 {
00362                     // too wide
00363                     if (point.left + menu->getWidth() > menu->getParentSize().width)
00364                     {
00365                         // move to the left side if possible
00366                         if (point.left - menu->getWidth() - getWidth() > 0)
00367                             point.left -= menu->getWidth() + getWidth();
00368                         // or put near right parent border (window) if too wide for left side too
00369                         else
00370                             point.left = menu->getParentSize().width - menu->getWidth();
00371                     }
00372                     // too high (same logic as for too wide)
00373                     if (point.top + menu->getHeight() > menu->getParentSize().height)
00374                     {
00375                         // move to the top side if possible
00376                         if (point.top - menu->getHeight() - getHeight() > 0)
00377                             point.top -= menu->getHeight() + getHeight();
00378                         // or put near bottom parent border (window) if too high for top side too
00379                         else
00380                             point.top = menu->getParentSize().height - menu->getHeight();
00381                     }
00382                 }
00383                 else
00384                 {
00385                     point.set(coord.left, getAbsoluteRect().bottom);
00386                 }
00387 
00388                 menu->setPosition(point);
00389                 if (_smooth)
00390                     menu->setVisibleSmooth(true);
00391                 else
00392                     menu->setVisible(true);
00393 
00394                 MyGUI::LayerManager::getInstance().upLayerItem(menu);
00395             }
00396         }
00397         else
00398         {
00399             if (mItemsInfo[_index].submenu)
00400             {
00401                 if (_smooth)
00402                     mItemsInfo[_index].submenu->setVisibleSmooth(false);
00403                 else
00404                     mItemsInfo[_index].submenu->setVisible(false);
00405             }
00406         }
00407     }
00408 
00409     void MenuControl::notifyRootKeyChangeFocus(Widget* _sender, bool _focus)
00410     {
00411         MenuItem* item = _sender->castType<MenuItem>();
00412         if (item->getItemType() == MenuItemType::Popup)
00413         {
00414             if (_focus)
00415             {
00416                 if (!mMenuDropMode || mIsMenuDrop)
00417                 {
00418                     item->setItemChildVisible(true);
00419                     item->setStateSelected(true);
00420                 }
00421             }
00422             else
00423             {
00424                 item->setItemChildVisible(false);
00425                 item->setStateSelected(false);
00426             }
00427         }
00428     }
00429 
00430     Widget* MenuControl::createItemChildByType(size_t _index, const std::string& _type)
00431     {
00432         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::createItemChildByType");
00433         removeItemChildAt(_index);
00434         Widget* child = mItemsInfo[_index].item->createWidgetT(WidgetStyle::Popup, _type, mSubMenuSkin, IntCoord(), Align::Default, mSubMenuLayer);
00435         MYGUI_ASSERT(child->isType<MenuControl>(), "child must have MenuControl base type");
00436         return child;
00437     }
00438 
00439     void MenuControl::notifyMouseButtonClick(Widget* _sender)
00440     {
00441         MenuItem* item = _sender->castType<MenuItem>();
00442         if (mMenuDropMode)
00443         {
00444             if (mIsMenuDrop)
00445             {
00446                 if (item->getItemType() == MenuItemType::Popup)
00447                 {
00448                     item->setStateSelected(false);
00449                     item->setItemChildVisible(false);
00450                     mIsMenuDrop = false;
00451                 }
00452             }
00453             else
00454             {
00455                 if (item->getItemType() == MenuItemType::Popup)
00456                 {
00457                     mIsMenuDrop = true;
00458                     item->setStateSelected(true);
00459                     item->setItemChildVisible(true);
00460                     InputManager::getInstance().setKeyFocusWidget(item);
00461                 }
00462             }
00463         }
00464         else
00465         {
00466             if ((item->getItemType() == MenuItemType::Popup && mPopupAccept) ||
00467                 item->getItemType() == MenuItemType::Normal)
00468             {
00469                 notifyMenuCtrlAccept(item);
00470             }
00471         }
00472     }
00473 
00474     void MenuControl::onKeyChangeRootFocus(bool _focus)
00475     {
00476         if (mMenuDropMode)
00477         {
00478             mIsMenuDrop = false;
00479         }
00480         if (!_focus && mHideByLostKey)
00481         {
00482             setVisibleSmooth(false);
00483             eventMenuCtrlClose(this);
00484         }
00485         Base::onKeyChangeRootFocus(_focus);
00486     }
00487 
00488     void MenuControl::notifyMouseSetFocus(Widget* _sender, Widget* _new)
00489     {
00490         InputManager::getInstance().setKeyFocusWidget(_sender);
00491     }
00492 
00493     void MenuControl::_wrapItemChild(MenuItem* _item, MenuControl* _widget)
00494     {
00495         // заменяем
00496         size_t index = getItemIndex(_item);
00497         if (mItemsInfo[index].submenu != nullptr)
00498         {
00499             WidgetManager::getInstance().destroyWidget(mItemsInfo[index].submenu);
00500             mItemsInfo[index].submenu = nullptr;
00501         }
00502         mItemsInfo[index].submenu = _widget;
00503         // скрываем менюшку
00504         mItemsInfo[index].submenu->setVisible(false);
00505 
00506         update();
00507     }
00508 
00509     void MenuControl::_wrapItem(MenuItem* _item, size_t _index, const UString& _name, MenuItemType _type, const std::string& _id, Any _data)
00510     {
00511         _item->setAlign(mVerticalAlignment ? Align::Top | Align::HStretch : Align::Default);
00512         _item->eventRootKeyChangeFocus += newDelegate(this, &MenuControl::notifyRootKeyChangeFocus);
00513         _item->eventMouseButtonClick += newDelegate(this, &MenuControl::notifyMouseButtonClick);
00514         _item->eventMouseSetFocus += newDelegate(this, &MenuControl::notifyMouseSetFocus);
00515 
00516         _item->setImageName(getIconIndexByType(_type ));
00517 
00518         MenuControl* submenu = nullptr;
00519 
00520         ItemInfo info = ItemInfo(_item, _name, _type, submenu, _id, _data);
00521 
00522         mItemsInfo.insert(mItemsInfo.begin() + _index, info);
00523 
00524         mChangeChildSkin = true;
00525         _item->changeWidgetSkin(getSkinByType(_type));
00526         mChangeChildSkin = false;
00527 
00528         // его сет капшен, обновит размер
00529         _item->setCaption(_name);
00530 
00531         update();
00532     }
00533 
00534     void MenuControl::setVisible(bool _visible)
00535     {
00536         if (mAnimateSmooth)
00537         {
00538             ControllerManager::getInstance().removeItem(this);
00539             setAlpha(ALPHA_MAX);
00540             setEnabledSilent(true);
00541             mAnimateSmooth = false;
00542         }
00543 
00544         if (_visible)
00545         {
00546             if (mOwner == nullptr && mHideByLostKey)
00547             {
00548                 MyGUI::InputManager::getInstance().setKeyFocusWidget(this);
00549             }
00550         }
00551 
00552         Base::setVisible(_visible);
00553     }
00554 
00555     void MenuControl::setVisibleSmooth(bool _visible)
00556     {
00557         mAnimateSmooth = true;
00558         ControllerManager::getInstance().removeItem(this);
00559 
00560         if (_visible)
00561         {
00562             setEnabledSilent(true);
00563             if (!getVisible())
00564             {
00565                 setAlpha(ALPHA_MIN);
00566                 Base::setVisible(true);
00567             }
00568 
00569             ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MAX, POPUP_MENU_SPEED_COEF, true);
00570             controller->eventPostAction += newDelegate(action::actionWidgetShow);
00571             ControllerManager::getInstance().addItem(this, controller);
00572         }
00573         else
00574         {
00575             setEnabledSilent(false);
00576 
00577             ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MIN, POPUP_MENU_SPEED_COEF, false);
00578             controller->eventPostAction += newDelegate(action::actionWidgetHide);
00579             ControllerManager::getInstance().addItem(this, controller);
00580         }
00581     }
00582 
00583     ControllerFadeAlpha* MenuControl::createControllerFadeAlpha(float _alpha, float _coef, bool _enable)
00584     {
00585         ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName());
00586         ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>();
00587 
00588         controller->setAlpha(_alpha);
00589         controller->setCoef(_coef);
00590         controller->setEnabled(_enable);
00591 
00592         return controller;
00593     }
00594 
00595     MenuItem* MenuControl::insertItem(MenuItem* _to, const UString& _name, MenuItemType _type, const std::string& _id, Any _data)
00596     {
00597         return insertItemAt(getItemIndex(_to), _name, _type, _id, _data);
00598     }
00599 
00600     MenuItem* MenuControl::addItem(const UString& _name, MenuItemType _type, const std::string& _id, Any _data)
00601     {
00602         return insertItemAt(ITEM_NONE, _name, _type, _id, _data);
00603     }
00604 
00605     void MenuControl::removeItem(MenuItem* _item)
00606     {
00607         removeItemAt(getItemIndex(_item));
00608     }
00609 
00610     MenuItem* MenuControl::getItemAt(size_t _index)
00611     {
00612         MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemAt");
00613         return mItemsInfo[_index].item;
00614     }
00615 
00616     size_t MenuControl::getItemIndex(MenuItem* _item)
00617     {
00618         for (size_t pos = 0; pos < mItemsInfo.size(); pos++)
00619         {
00620             if (mItemsInfo[pos].item == _item)
00621                 return pos;
00622         }
00623         MYGUI_EXCEPT("item (" << _item << ") not found, source 'MenuControl::getItemIndex'");
00624     }
00625 
00626     MenuItem* MenuControl::findItemWith(const UString& _name)
00627     {
00628         for (size_t pos = 0; pos < mItemsInfo.size(); pos++)
00629         {
00630             if (mItemsInfo[pos].name == _name)
00631                 return mItemsInfo[pos].item;
00632         }
00633         return nullptr;
00634     }
00635 
00636     MenuItem* MenuControl::getItemById(const std::string& _id)
00637     {
00638         for (size_t index = 0; index < mItemsInfo.size(); index++)
00639         {
00640             if (mItemsInfo[index].id == _id)
00641                 return mItemsInfo[index].item;
00642         }
00643         MYGUI_EXCEPT("item id (" << _id << ") not found, source 'MenuControl::getItemById'");
00644     }
00645 
00646     size_t MenuControl::getItemIndexById(const std::string& _id)
00647     {
00648         for (size_t index = 0; index < mItemsInfo.size(); index++)
00649         {
00650             if (mItemsInfo[index].id == _id)
00651                 return index;
00652         }
00653         MYGUI_EXCEPT("item id (" << _id << ") not found, source 'MenuControl::getItemById'");
00654     }
00655 
00656     MenuItem* MenuControl::findItemById(const std::string& _id, bool _recursive)
00657     {
00658         for (size_t index = 0; index < mItemsInfo.size(); index++)
00659         {
00660             if (mItemsInfo[index].id == _id)
00661                 return mItemsInfo[index].item;
00662 
00663             if (_recursive && mItemsInfo[index].submenu != nullptr)
00664             {
00665                 MenuItem* find = mItemsInfo[index].submenu->findItemById(_id, _recursive);
00666                 if (find != nullptr)
00667                     return find;
00668             }
00669         }
00670         return nullptr;
00671     }
00672 
00673     size_t MenuControl::findItemIndexWith(const UString& _name)
00674     {
00675         for (size_t index = 0; index < mItemsInfo.size(); index++)
00676         {
00677             if (mItemsInfo[index].name == _name)
00678                 return index;
00679         }
00680         return ITEM_NONE;
00681     }
00682 
00683     size_t MenuControl::findItemIndex(MenuItem* _item)
00684     {
00685         for (size_t index = 0; index < mItemsInfo.size(); index++)
00686         {
00687             if (mItemsInfo[index].item == _item)
00688                 return index;
00689         }
00690         return ITEM_NONE;
00691     }
00692 
00693     Widget* MenuControl::_getClientWidget()
00694     {
00695         return mClient == nullptr ? this : mClient;
00696     }
00697 
00698     size_t MenuControl::getItemCount() const
00699     {
00700         return mItemsInfo.size();
00701     }
00702 
00703     void MenuControl::setItemData(MenuItem* _item, Any _data)
00704     {
00705         setItemDataAt(getItemIndex(_item), _data);
00706     }
00707 
00708     void MenuControl::clearItemDataAt(size_t _index)
00709     {
00710         setItemDataAt(_index, Any::Null);
00711     }
00712 
00713     void MenuControl::clearItemData(MenuItem* _item)
00714     {
00715         clearItemDataAt(getItemIndex(_item));
00716     }
00717 
00718     void MenuControl::setItemId(MenuItem* _item, const std::string& _id)
00719     {
00720         setItemIdAt(getItemIndex(_item), _id);
00721     }
00722 
00723     const std::string& MenuControl::getItemId(MenuItem* _item)
00724     {
00725         return getItemIdAt(getItemIndex(_item));
00726     }
00727 
00728     void MenuControl::setItemName(MenuItem* _item, const UString& _name)
00729     {
00730         setItemNameAt(getItemIndex(_item), _name);
00731     }
00732 
00733     const UString& MenuControl::getItemName(MenuItem* _item)
00734     {
00735         return getItemNameAt(getItemIndex(_item));
00736     }
00737 
00738     void MenuControl::setItemChildVisible(MenuItem* _item, bool _visible)
00739     {
00740         setItemChildVisibleAt(getItemIndex(_item), _visible);
00741     }
00742 
00743     MenuControl* MenuControl::getItemChild(MenuItem* _item)
00744     {
00745         return getItemChildAt(getItemIndex(_item));
00746     }
00747 
00748     MenuControl* MenuControl::createItemChildAt(size_t _index)
00749     {
00750         return createItemChildTAt<MenuControl>(_index);
00751     }
00752 
00753     MenuControl* MenuControl::createItemChild(MenuItem* _item)
00754     {
00755         return createItemChildAt(getItemIndex(_item));
00756     }
00757 
00758     void MenuControl::removeItemChild(MenuItem* _item)
00759     {
00760         removeItemChildAt(getItemIndex(_item));
00761     }
00762 
00763     MenuItemType MenuControl::getItemType(MenuItem* _item)
00764     {
00765         return getItemTypeAt(getItemIndex(_item));
00766     }
00767 
00768     void MenuControl::setItemType(MenuItem* _item, MenuItemType _type)
00769     {
00770         setItemTypeAt(getItemIndex(_item), _type);
00771     }
00772 
00773     void MenuControl::setPopupAccept(bool _value)
00774     {
00775         mPopupAccept = _value;
00776     }
00777 
00778     bool MenuControl::getPopupAccept() const
00779     {
00780         return mPopupAccept;
00781     }
00782 
00783     MenuItem* MenuControl::getMenuItemParent()
00784     {
00785         return mOwner;
00786     }
00787 
00788     const std::string& MenuControl::getSkinByType(MenuItemType _type) const
00789     {
00790         if (_type == MenuItemType::Popup)
00791             return mItemPopupSkin;
00792         else if (_type == MenuItemType::Separator)
00793             return mItemSeparatorSkin;
00794         return mItemNormalSkin;
00795     }
00796 
00797     std::string MenuControl::getIconIndexByType(MenuItemType _type) const
00798     {
00799         if (_type == MenuItemType::Popup)
00800             return "Popup";
00801         return "None";
00802     }
00803 
00804     MenuItemType MenuControl::getItemType(bool _submenu, bool _separator) const
00805     {
00806         if (_submenu)
00807             return MenuItemType::Popup;
00808         else if (_separator)
00809             return MenuItemType::Separator;
00810         return MenuItemType::Normal;
00811     }
00812 
00813     size_t MenuControl::_getItemCount()
00814     {
00815         return getItemCount();
00816     }
00817 
00818     void MenuControl::_addItem(const MyGUI::UString& _name)
00819     {
00820         addItem(_name, MenuItemType::Normal);
00821     }
00822 
00823     void MenuControl::_removeItemAt(size_t _index)
00824     {
00825         removeItemAt(_index);
00826 
00827         _updateSizeForEmpty();
00828     }
00829 
00830     Widget* MenuControl::_getItemAt(size_t _index)
00831     {
00832         return getItemAt(_index);
00833     }
00834 
00835     void MenuControl::_setItemNameAt(size_t _index, const UString& _name)
00836     {
00837         setItemNameAt(_index, _name);
00838     }
00839 
00840     const UString& MenuControl::_getItemNameAt(size_t _index)
00841     {
00842         return getItemNameAt(_index);
00843     }
00844 
00845     void MenuControl::_setItemSelected(IItem* _item)
00846     {
00847         MenuItem* item = static_cast<MenuItem*>(_item);
00848         for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter)
00849         {
00850             if ((*iter).type == MenuItemType::Popup)
00851             {
00852                 (*iter).item->setStateSelected(false);
00853 
00854                 if ((*iter).submenu != nullptr)
00855                     (*iter).submenu->setVisible(false);
00856             }
00857         }
00858 
00859         if (item->getItemType() == MenuItemType::Popup)
00860         {
00861             item->setStateSelected(true);
00862             size_t index = getItemIndex(item);
00863 
00864             _setItemChildVisibleAt(index, true, false);
00865 
00866             _updateItems(index);
00867         }
00868     }
00869 
00870     void MenuControl::_updateItems(size_t _index)
00871     {
00872         if (mItemsInfo[_index].submenu != nullptr)
00873             mItemsInfo[_index].submenu->_updateSizeForEmpty();
00874     }
00875 
00876     void MenuControl::_updateSizeForEmpty()
00877     {
00878         if (mItemsInfo.empty())
00879             setSize(100, 100);
00880     }
00881 
00882     void MenuControl::setVerticalAlignment(bool _value)
00883     {
00884         mVerticalAlignment = _value;
00885 
00886         update();
00887     }
00888 
00889     bool MenuControl::getVerticalAlignment() const
00890     {
00891         return mVerticalAlignment;
00892     }
00893 
00894     void MenuControl::setPropertyOverride(const std::string& _key, const std::string& _value)
00895     {
00897         if (_key == "VerticalAlignment")
00898             setVerticalAlignment(utility::parseValue<bool>(_value));
00899 
00900         else
00901         {
00902             Base::setPropertyOverride(_key, _value);
00903             return;
00904         }
00905 
00906         eventChangeProperty(this, _key, _value);
00907     }
00908 
00909 } // namespace MyGUI