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