1 /* 2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/ 3 * Distributed under the MIT License 4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) 5 */ 6 7 #include "MyGUI_Precompiled.h" 8 #include "MyGUI_MenuControl.h" 9 #include "MyGUI_ResourceSkin.h" 10 #include "MyGUI_MenuItem.h" 11 #include "MyGUI_ImageBox.h" 12 #include "MyGUI_MenuBar.h" 13 #include "MyGUI_WidgetManager.h" 14 #include "MyGUI_LayerManager.h" 15 #include "MyGUI_ControllerManager.h" 16 #include "MyGUI_InputManager.h" 17 #include "MyGUI_Gui.h" 18 #include "MyGUI_RenderManager.h" 19 20 namespace MyGUI 21 { 22 23 const float POPUP_MENU_SPEED_COEF = 3.0f; 24 MenuControl()25 MenuControl::MenuControl() : 26 mHideByAccept(true), 27 mMenuDropMode(false), 28 mIsMenuDrop(true), 29 mHideByLostKey(false), 30 mResizeToContent(true), 31 mShutdown(false), 32 mVerticalAlignment(true), 33 mDistanceButton(0), 34 mPopupAccept(false), 35 mOwner(nullptr), 36 mAnimateSmooth(false), 37 mChangeChildSkin(false), 38 mInternalCreateChild(false) 39 { 40 } 41 initialiseOverride()42 void MenuControl::initialiseOverride() 43 { 44 Base::initialiseOverride(); 45 46 // инициализируем овнера 47 Widget* parent = getParent(); 48 if (parent) 49 { 50 mOwner = parent->castType<MenuItem>(false); 51 if (!mOwner) 52 { 53 Widget* client = parent; 54 parent = client->getParent(); 55 if (parent && parent->getClientWidget()) 56 { 57 mOwner = parent->castType<MenuItem>(false); 58 } 59 } 60 } 61 62 // FIXME нам нужен фокус клавы 63 setNeedKeyFocus(true); 64 65 //OBSOLETE 66 if (isUserString("SkinLine")) 67 { 68 mItemNormalSkin = getUserString("SkinLine"); 69 mItemPopupSkin = mItemNormalSkin; 70 } 71 72 if (isUserString("SeparatorSkin")) 73 mItemSeparatorSkin = getUserString("SeparatorSkin"); 74 75 if (isUserString("NormalSkin")) 76 mItemNormalSkin = getUserString("NormalSkin"); 77 78 if (isUserString("PopupSkin")) 79 mItemPopupSkin = getUserString("PopupSkin"); 80 81 if (isUserString("DistanceButton")) 82 mDistanceButton = utility::parseValue<int>(getUserString("DistanceButton")); 83 84 if (isUserString("SubMenuSkin")) 85 mSubMenuSkin = getUserString("SubMenuSkin"); 86 87 if (isUserString("SubMenuLayer")) 88 mSubMenuLayer = getUserString("SubMenuLayer"); 89 90 // FIXME добавленно, так как шетдаун вызывается и при смене скина 91 mShutdown = false; 92 } 93 shutdownOverride()94 void MenuControl::shutdownOverride() 95 { 96 mShutdown = true; 97 98 if (mOwner != nullptr) 99 mOwner->getMenuCtrlParent()->_notifyDeletePopup(mOwner); 100 101 Base::shutdownOverride(); 102 } 103 onWidgetCreated(Widget * _widget)104 void MenuControl::onWidgetCreated(Widget* _widget) 105 { 106 Base::onWidgetCreated(_widget); 107 108 MenuItem* child = _widget->castType<MenuItem>(false); 109 if (child != nullptr && !mInternalCreateChild) 110 { 111 _wrapItem(child, mItemsInfo.size(), "", MenuItemType::Normal, "", Any::Null); 112 } 113 } 114 insertItemAt(size_t _index,const UString & _name,MenuItemType _type,const std::string & _id,Any _data)115 MenuItem* MenuControl::insertItemAt(size_t _index, const UString& _name, MenuItemType _type, const std::string& _id, Any _data) 116 { 117 MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "MenuControl::insertItemAt"); 118 if (_index == ITEM_NONE) _index = mItemsInfo.size(); 119 120 mInternalCreateChild = true; 121 MenuItem* item = _getClientWidget()->createWidget<MenuItem>(getSkinByType(_type), IntCoord(), Align::Default); 122 mInternalCreateChild = false; 123 _wrapItem(item, _index, _name, _type, _id, _data); 124 125 return item; 126 } 127 removeItemAt(size_t _index)128 void MenuControl::removeItemAt(size_t _index) 129 { 130 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::removeItemAt"); 131 132 if (mItemsInfo[_index].submenu) 133 { 134 WidgetManager::getInstance().destroyWidget(mItemsInfo[_index].submenu); 135 mItemsInfo[_index].submenu = nullptr; 136 } 137 WidgetManager::getInstance().destroyWidget(mItemsInfo[_index].item); 138 } 139 removeAllItems()140 void MenuControl::removeAllItems() 141 { 142 while (!mItemsInfo.empty()) 143 { 144 if (mItemsInfo.back().submenu) 145 { 146 WidgetManager::getInstance().destroyWidget(mItemsInfo.back().submenu); 147 mItemsInfo.back().submenu = nullptr; 148 } 149 WidgetManager::getInstance().destroyWidget(mItemsInfo.back().item); 150 } 151 } 152 getItemNameAt(size_t _index)153 const UString& MenuControl::getItemNameAt(size_t _index) 154 { 155 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemNameAt"); 156 return mItemsInfo[_index].name; 157 } 158 update()159 void MenuControl::update() 160 { 161 IntSize size; 162 163 if (mVerticalAlignment) 164 { 165 for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter) 166 { 167 IntSize contentSize = iter->item->_getContentSize(); 168 iter->item->setCoord(0, size.height, _getClientWidget()->getWidth(), contentSize.height); 169 size.height += contentSize.height + mDistanceButton; 170 171 if (contentSize.width > size.width) 172 size.width = contentSize.width; 173 } 174 if (!mItemsInfo.empty()) 175 size.height -= mDistanceButton; 176 } 177 else 178 { 179 int maxHeight = 0; 180 for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter) 181 { 182 IntSize contentSize = iter->item->_getContentSize(); 183 if (maxHeight < contentSize.height) 184 maxHeight = contentSize.height; 185 } 186 187 for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter) 188 { 189 IntSize contentSize = iter->item->_getContentSize(); 190 iter->item->setCoord(size.width, 0, contentSize.width, maxHeight); 191 size.width += contentSize.width + mDistanceButton; 192 } 193 194 if (!mItemsInfo.empty()) 195 size.width -= mDistanceButton; 196 } 197 198 if (mResizeToContent) 199 setSize(size + mCoord.size() - _getClientWidget()->getSize()); 200 } 201 setItemDataAt(size_t _index,Any _data)202 void MenuControl::setItemDataAt(size_t _index, Any _data) 203 { 204 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemDataAt"); 205 mItemsInfo[_index].data = _data; 206 } 207 getItemChildAt(size_t _index)208 MenuControl* MenuControl::getItemChildAt(size_t _index) 209 { 210 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemChildAt"); 211 return mItemsInfo[_index].submenu; 212 } 213 removeItemChildAt(size_t _index)214 void MenuControl::removeItemChildAt(size_t _index) 215 { 216 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::removeItemChildAt"); 217 218 if (mItemsInfo[_index].submenu != nullptr) 219 { 220 WidgetManager::getInstance().destroyWidget(mItemsInfo[_index].submenu); 221 mItemsInfo[_index].submenu = nullptr; 222 } 223 224 update(); 225 } 226 setItemNameAt(size_t _index,const UString & _name)227 void MenuControl::setItemNameAt(size_t _index, const UString& _name) 228 { 229 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemNameAt"); 230 231 mItemsInfo[_index].name = _name; 232 MenuItem* item = mItemsInfo[_index].item; 233 item->setCaption(_name); 234 235 update(); 236 } 237 setItemIdAt(size_t _index,const std::string & _id)238 void MenuControl::setItemIdAt(size_t _index, const std::string& _id) 239 { 240 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemIdAt"); 241 mItemsInfo[_index].id = _id; 242 } 243 getItemIdAt(size_t _index)244 const std::string& MenuControl::getItemIdAt(size_t _index) 245 { 246 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemIdAt"); 247 return mItemsInfo[_index].id; 248 } 249 _notifyDeleteItem(MenuItem * _item)250 void MenuControl::_notifyDeleteItem(MenuItem* _item) 251 { 252 // дитю меняем скин 253 if (mChangeChildSkin) 254 return; 255 256 // общий шутдаун виджета 257 if (mShutdown) 258 return; 259 260 size_t index = getItemIndex(_item); 261 mItemsInfo.erase(mItemsInfo.begin() + index); 262 update(); 263 } 264 _notifyDeletePopup(MenuItem * _item)265 void MenuControl::_notifyDeletePopup(MenuItem* _item) 266 { 267 size_t index = getItemIndex(_item); 268 mItemsInfo[index].submenu = nullptr; 269 } 270 _notifyUpdateName(MenuItem * _item)271 void MenuControl::_notifyUpdateName(MenuItem* _item) 272 { 273 size_t index = getItemIndex(_item); 274 mItemsInfo[index].name = _item->getCaption(); 275 276 ISubWidgetText* text = _item->getSubWidgetText(); 277 mItemsInfo[index].width = text ? (text->getTextSize().width + _item->getSize().width - text->getWidth()) : 0; 278 update(); 279 } 280 getItemTypeAt(size_t _index)281 MenuItemType MenuControl::getItemTypeAt(size_t _index) 282 { 283 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemTypeAt"); 284 return mItemsInfo[_index].type; 285 } 286 setItemTypeAt(size_t _index,MenuItemType _type)287 void MenuControl::setItemTypeAt(size_t _index, MenuItemType _type) 288 { 289 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemTypeAt"); 290 ItemInfo& info = mItemsInfo[_index]; 291 if (info.type == _type) 292 return; 293 294 // сохраняем данные 295 info.type = _type; 296 297 // при смене скина дите отпишется 298 mChangeChildSkin = true; 299 info.item->changeWidgetSkin(getSkinByType(_type)); 300 mChangeChildSkin = false; 301 302 info.item->setImageName(getIconIndexByType(_type )); 303 info.item->setCaption(info.name); 304 305 update(); 306 } 307 notifyMenuCtrlAccept(MenuItem * _item)308 void MenuControl::notifyMenuCtrlAccept(MenuItem* _item) 309 { 310 if (mHideByAccept) 311 { 312 setVisibleSmooth(false); 313 } 314 else 315 { 316 InputManager::getInstance().setKeyFocusWidget(nullptr); 317 } 318 319 MenuItem* parent_item = getMenuItemParent(); 320 if (parent_item) 321 { 322 MenuControl* parent_ctrl = parent_item->getMenuCtrlParent(); 323 if (parent_ctrl) 324 { 325 parent_ctrl->notifyMenuCtrlAccept(_item); 326 } 327 } 328 329 eventMenuCtrlAccept(this, _item); 330 } 331 setItemChildVisibleAt(size_t _index,bool _visible)332 void MenuControl::setItemChildVisibleAt(size_t _index, bool _visible) 333 { 334 _setItemChildVisibleAt(_index, _visible, true); 335 } 336 _setItemChildVisibleAt(size_t _index,bool _visible,bool _smooth)337 void MenuControl::_setItemChildVisibleAt(size_t _index, bool _visible, bool _smooth) 338 { 339 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::setItemChildVisibleAt"); 340 341 if (_visible) 342 { 343 if (mItemsInfo[_index].submenu && mItemsInfo[_index].submenu->getItemCount()) 344 { 345 int offset = mItemsInfo[0].item->getAbsoluteTop() - getAbsoluteTop(); 346 347 const IntCoord& coord = mItemsInfo[_index].item->getAbsoluteCoord(); 348 IntPoint point(getAbsoluteRect().right, coord.top - offset); 349 350 MenuControl* menu = mItemsInfo[_index].submenu; 351 352 if (mVerticalAlignment) 353 { 354 // too wide 355 if (point.left + menu->getWidth() > menu->getParentSize().width) 356 { 357 // move to the left side if possible 358 if (point.left - menu->getWidth() - getWidth() > 0) 359 point.left -= menu->getWidth() + getWidth(); 360 // or put near right parent border (window) if too wide for left side too 361 else 362 point.left = menu->getParentSize().width - menu->getWidth(); 363 } 364 // too high (same logic as for too wide) 365 if (point.top + menu->getHeight() > menu->getParentSize().height) 366 { 367 // move to the top side if possible 368 if (point.top - menu->getHeight() - getHeight() > 0) 369 point.top -= menu->getHeight() + getHeight(); 370 // or put near bottom parent border (window) if too high for top side too 371 else 372 point.top = menu->getParentSize().height - menu->getHeight(); 373 } 374 } 375 else 376 { 377 point.set(coord.left, getAbsoluteRect().bottom); 378 } 379 380 menu->setPosition(point); 381 if (_smooth) 382 menu->setVisibleSmooth(true); 383 else 384 menu->setVisible(true); 385 386 MyGUI::LayerManager::getInstance().upLayerItem(menu); 387 } 388 } 389 else 390 { 391 if (mItemsInfo[_index].submenu) 392 { 393 if (_smooth) 394 mItemsInfo[_index].submenu->setVisibleSmooth(false); 395 else 396 mItemsInfo[_index].submenu->setVisible(false); 397 } 398 } 399 } 400 notifyRootKeyChangeFocus(Widget * _sender,bool _focus)401 void MenuControl::notifyRootKeyChangeFocus(Widget* _sender, bool _focus) 402 { 403 MenuItem* item = _sender->castType<MenuItem>(); 404 if (item->getItemType() == MenuItemType::Popup) 405 { 406 if (_focus) 407 { 408 if (!mMenuDropMode || mIsMenuDrop) 409 { 410 item->setItemChildVisible(true); 411 item->setStateSelected(true); 412 } 413 } 414 else 415 { 416 item->setItemChildVisible(false); 417 item->setStateSelected(false); 418 } 419 } 420 } 421 createItemChildByType(size_t _index,const std::string & _type)422 Widget* MenuControl::createItemChildByType(size_t _index, const std::string& _type) 423 { 424 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::createItemChildByType"); 425 removeItemChildAt(_index); 426 Widget* child = mItemsInfo[_index].item->createWidgetT(WidgetStyle::Popup, _type, mSubMenuSkin, IntCoord(), Align::Default, mSubMenuLayer); 427 MYGUI_ASSERT(child->isType<MenuControl>(), "child must have MenuControl base type"); 428 return child; 429 } 430 notifyMouseButtonClick(Widget * _sender)431 void MenuControl::notifyMouseButtonClick(Widget* _sender) 432 { 433 MenuItem* item = _sender->castType<MenuItem>(); 434 if (mMenuDropMode) 435 { 436 if (mIsMenuDrop) 437 { 438 if (item->getItemType() == MenuItemType::Popup) 439 { 440 item->setStateSelected(false); 441 item->setItemChildVisible(false); 442 mIsMenuDrop = false; 443 } 444 } 445 else 446 { 447 if (item->getItemType() == MenuItemType::Popup) 448 { 449 mIsMenuDrop = true; 450 item->setStateSelected(true); 451 item->setItemChildVisible(true); 452 InputManager::getInstance().setKeyFocusWidget(item); 453 } 454 } 455 } 456 else 457 { 458 if ((item->getItemType() == MenuItemType::Popup && mPopupAccept) || 459 item->getItemType() == MenuItemType::Normal) 460 { 461 notifyMenuCtrlAccept(item); 462 } 463 } 464 } 465 onKeyChangeRootFocus(bool _focus)466 void MenuControl::onKeyChangeRootFocus(bool _focus) 467 { 468 if (mMenuDropMode) 469 { 470 mIsMenuDrop = false; 471 } 472 if (!_focus && mHideByLostKey) 473 { 474 setVisibleSmooth(false); 475 eventMenuCtrlClose(this); 476 } 477 Base::onKeyChangeRootFocus(_focus); 478 } 479 notifyMouseSetFocus(Widget * _sender,Widget * _new)480 void MenuControl::notifyMouseSetFocus(Widget* _sender, Widget* _new) 481 { 482 InputManager::getInstance().setKeyFocusWidget(_sender); 483 } 484 _wrapItemChild(MenuItem * _item,MenuControl * _widget)485 void MenuControl::_wrapItemChild(MenuItem* _item, MenuControl* _widget) 486 { 487 // заменяем 488 size_t index = getItemIndex(_item); 489 if (mItemsInfo[index].submenu != nullptr) 490 { 491 WidgetManager::getInstance().destroyWidget(mItemsInfo[index].submenu); 492 mItemsInfo[index].submenu = nullptr; 493 } 494 mItemsInfo[index].submenu = _widget; 495 // скрываем менюшку 496 mItemsInfo[index].submenu->setVisible(false); 497 498 update(); 499 } 500 _wrapItem(MenuItem * _item,size_t _index,const UString & _name,MenuItemType _type,const std::string & _id,Any _data)501 void MenuControl::_wrapItem(MenuItem* _item, size_t _index, const UString& _name, MenuItemType _type, const std::string& _id, Any _data) 502 { 503 _item->setAlign(mVerticalAlignment ? Align::Top | Align::HStretch : Align::Default); 504 _item->eventRootKeyChangeFocus += newDelegate(this, &MenuControl::notifyRootKeyChangeFocus); 505 _item->eventMouseButtonClick += newDelegate(this, &MenuControl::notifyMouseButtonClick); 506 _item->eventMouseSetFocus += newDelegate(this, &MenuControl::notifyMouseSetFocus); 507 508 _item->setImageName(getIconIndexByType(_type )); 509 510 MenuControl* submenu = nullptr; 511 512 ItemInfo info = ItemInfo(_item, _name, _type, submenu, _id, _data); 513 514 mItemsInfo.insert(mItemsInfo.begin() + _index, info); 515 516 mChangeChildSkin = true; 517 _item->changeWidgetSkin(getSkinByType(_type)); 518 mChangeChildSkin = false; 519 520 // его сет капшен, обновит размер 521 _item->setCaption(_name); 522 523 update(); 524 } 525 setVisible(bool _visible)526 void MenuControl::setVisible(bool _visible) 527 { 528 if (mAnimateSmooth) 529 { 530 ControllerManager::getInstance().removeItem(this); 531 setAlpha(ALPHA_MAX); 532 setEnabledSilent(true); 533 mAnimateSmooth = false; 534 } 535 536 if (_visible) 537 { 538 if (mOwner == nullptr && mHideByLostKey) 539 { 540 MyGUI::InputManager::getInstance().setKeyFocusWidget(this); 541 } 542 } 543 544 Base::setVisible(_visible); 545 } 546 setVisibleSmooth(bool _visible)547 void MenuControl::setVisibleSmooth(bool _visible) 548 { 549 mAnimateSmooth = true; 550 ControllerManager::getInstance().removeItem(this); 551 552 if (_visible) 553 { 554 setEnabledSilent(true); 555 if (!getVisible()) 556 { 557 setAlpha(ALPHA_MIN); 558 Base::setVisible(true); 559 } 560 561 ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MAX, POPUP_MENU_SPEED_COEF, true); 562 controller->eventPostAction += newDelegate(action::actionWidgetShow); 563 ControllerManager::getInstance().addItem(this, controller); 564 } 565 else 566 { 567 setEnabledSilent(false); 568 569 ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MIN, POPUP_MENU_SPEED_COEF, false); 570 controller->eventPostAction += newDelegate(action::actionWidgetHide); 571 ControllerManager::getInstance().addItem(this, controller); 572 } 573 } 574 createControllerFadeAlpha(float _alpha,float _coef,bool _enable)575 ControllerFadeAlpha* MenuControl::createControllerFadeAlpha(float _alpha, float _coef, bool _enable) 576 { 577 ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName()); 578 ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>(); 579 580 controller->setAlpha(_alpha); 581 controller->setCoef(_coef); 582 controller->setEnabled(_enable); 583 584 return controller; 585 } 586 insertItem(MenuItem * _to,const UString & _name,MenuItemType _type,const std::string & _id,Any _data)587 MenuItem* MenuControl::insertItem(MenuItem* _to, const UString& _name, MenuItemType _type, const std::string& _id, Any _data) 588 { 589 return insertItemAt(getItemIndex(_to), _name, _type, _id, _data); 590 } 591 addItem(const UString & _name,MenuItemType _type,const std::string & _id,Any _data)592 MenuItem* MenuControl::addItem(const UString& _name, MenuItemType _type, const std::string& _id, Any _data) 593 { 594 return insertItemAt(ITEM_NONE, _name, _type, _id, _data); 595 } 596 removeItem(MenuItem * _item)597 void MenuControl::removeItem(MenuItem* _item) 598 { 599 removeItemAt(getItemIndex(_item)); 600 } 601 getItemAt(size_t _index)602 MenuItem* MenuControl::getItemAt(size_t _index) 603 { 604 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "MenuControl::getItemAt"); 605 return mItemsInfo[_index].item; 606 } 607 getItemIndex(MenuItem * _item)608 size_t MenuControl::getItemIndex(MenuItem* _item) 609 { 610 for (size_t pos = 0; pos < mItemsInfo.size(); pos++) 611 { 612 if (mItemsInfo[pos].item == _item) 613 return pos; 614 } 615 MYGUI_EXCEPT("item (" << _item << ") not found, source 'MenuControl::getItemIndex'"); 616 } 617 findItemWith(const UString & _name)618 MenuItem* MenuControl::findItemWith(const UString& _name) 619 { 620 for (size_t pos = 0; pos < mItemsInfo.size(); pos++) 621 { 622 if (mItemsInfo[pos].name == _name) 623 return mItemsInfo[pos].item; 624 } 625 return nullptr; 626 } 627 getItemById(const std::string & _id)628 MenuItem* MenuControl::getItemById(const std::string& _id) 629 { 630 for (size_t index = 0; index < mItemsInfo.size(); index++) 631 { 632 if (mItemsInfo[index].id == _id) 633 return mItemsInfo[index].item; 634 } 635 MYGUI_EXCEPT("item id (" << _id << ") not found, source 'MenuControl::getItemById'"); 636 } 637 getItemIndexById(const std::string & _id)638 size_t MenuControl::getItemIndexById(const std::string& _id) 639 { 640 for (size_t index = 0; index < mItemsInfo.size(); index++) 641 { 642 if (mItemsInfo[index].id == _id) 643 return index; 644 } 645 MYGUI_EXCEPT("item id (" << _id << ") not found, source 'MenuControl::getItemById'"); 646 } 647 findItemById(const std::string & _id,bool _recursive)648 MenuItem* MenuControl::findItemById(const std::string& _id, bool _recursive) 649 { 650 for (size_t index = 0; index < mItemsInfo.size(); index++) 651 { 652 if (mItemsInfo[index].id == _id) 653 return mItemsInfo[index].item; 654 655 if (_recursive && mItemsInfo[index].submenu != nullptr) 656 { 657 MenuItem* find = mItemsInfo[index].submenu->findItemById(_id, _recursive); 658 if (find != nullptr) 659 return find; 660 } 661 } 662 return nullptr; 663 } 664 findItemIndexWith(const UString & _name)665 size_t MenuControl::findItemIndexWith(const UString& _name) 666 { 667 for (size_t index = 0; index < mItemsInfo.size(); index++) 668 { 669 if (mItemsInfo[index].name == _name) 670 return index; 671 } 672 return ITEM_NONE; 673 } 674 findItemIndex(MenuItem * _item)675 size_t MenuControl::findItemIndex(MenuItem* _item) 676 { 677 for (size_t index = 0; index < mItemsInfo.size(); index++) 678 { 679 if (mItemsInfo[index].item == _item) 680 return index; 681 } 682 return ITEM_NONE; 683 } 684 getItemCount() const685 size_t MenuControl::getItemCount() const 686 { 687 return mItemsInfo.size(); 688 } 689 setItemData(MenuItem * _item,Any _data)690 void MenuControl::setItemData(MenuItem* _item, Any _data) 691 { 692 setItemDataAt(getItemIndex(_item), _data); 693 } 694 clearItemDataAt(size_t _index)695 void MenuControl::clearItemDataAt(size_t _index) 696 { 697 setItemDataAt(_index, Any::Null); 698 } 699 clearItemData(MenuItem * _item)700 void MenuControl::clearItemData(MenuItem* _item) 701 { 702 clearItemDataAt(getItemIndex(_item)); 703 } 704 setItemId(MenuItem * _item,const std::string & _id)705 void MenuControl::setItemId(MenuItem* _item, const std::string& _id) 706 { 707 setItemIdAt(getItemIndex(_item), _id); 708 } 709 getItemId(MenuItem * _item)710 const std::string& MenuControl::getItemId(MenuItem* _item) 711 { 712 return getItemIdAt(getItemIndex(_item)); 713 } 714 setItemName(MenuItem * _item,const UString & _name)715 void MenuControl::setItemName(MenuItem* _item, const UString& _name) 716 { 717 setItemNameAt(getItemIndex(_item), _name); 718 } 719 getItemName(MenuItem * _item)720 const UString& MenuControl::getItemName(MenuItem* _item) 721 { 722 return getItemNameAt(getItemIndex(_item)); 723 } 724 setItemChildVisible(MenuItem * _item,bool _visible)725 void MenuControl::setItemChildVisible(MenuItem* _item, bool _visible) 726 { 727 setItemChildVisibleAt(getItemIndex(_item), _visible); 728 } 729 getItemChild(MenuItem * _item)730 MenuControl* MenuControl::getItemChild(MenuItem* _item) 731 { 732 return getItemChildAt(getItemIndex(_item)); 733 } 734 createItemChildAt(size_t _index)735 MenuControl* MenuControl::createItemChildAt(size_t _index) 736 { 737 return createItemChildTAt<MenuControl>(_index); 738 } 739 createItemChild(MenuItem * _item)740 MenuControl* MenuControl::createItemChild(MenuItem* _item) 741 { 742 return createItemChildAt(getItemIndex(_item)); 743 } 744 removeItemChild(MenuItem * _item)745 void MenuControl::removeItemChild(MenuItem* _item) 746 { 747 removeItemChildAt(getItemIndex(_item)); 748 } 749 getItemType(MenuItem * _item)750 MenuItemType MenuControl::getItemType(MenuItem* _item) 751 { 752 return getItemTypeAt(getItemIndex(_item)); 753 } 754 setItemType(MenuItem * _item,MenuItemType _type)755 void MenuControl::setItemType(MenuItem* _item, MenuItemType _type) 756 { 757 setItemTypeAt(getItemIndex(_item), _type); 758 } 759 setPopupAccept(bool _value)760 void MenuControl::setPopupAccept(bool _value) 761 { 762 mPopupAccept = _value; 763 } 764 getPopupAccept() const765 bool MenuControl::getPopupAccept() const 766 { 767 return mPopupAccept; 768 } 769 getMenuItemParent()770 MenuItem* MenuControl::getMenuItemParent() 771 { 772 return mOwner; 773 } 774 getSkinByType(MenuItemType _type) const775 const std::string& MenuControl::getSkinByType(MenuItemType _type) const 776 { 777 if (_type == MenuItemType::Popup) 778 return mItemPopupSkin; 779 else if (_type == MenuItemType::Separator) 780 return mItemSeparatorSkin; 781 return mItemNormalSkin; 782 } 783 getIconIndexByType(MenuItemType _type) const784 std::string MenuControl::getIconIndexByType(MenuItemType _type) const 785 { 786 if (_type == MenuItemType::Popup) 787 return "Popup"; 788 return "None"; 789 } 790 getItemType(bool _submenu,bool _separator) const791 MenuItemType MenuControl::getItemType(bool _submenu, bool _separator) const 792 { 793 if (_submenu) 794 return MenuItemType::Popup; 795 else if (_separator) 796 return MenuItemType::Separator; 797 return MenuItemType::Normal; 798 } 799 _getItemCount()800 size_t MenuControl::_getItemCount() 801 { 802 return getItemCount(); 803 } 804 _addItem(const MyGUI::UString & _name)805 void MenuControl::_addItem(const MyGUI::UString& _name) 806 { 807 addItem(_name, MenuItemType::Normal); 808 } 809 _removeItemAt(size_t _index)810 void MenuControl::_removeItemAt(size_t _index) 811 { 812 removeItemAt(_index); 813 814 _updateSizeForEmpty(); 815 } 816 _getItemAt(size_t _index)817 Widget* MenuControl::_getItemAt(size_t _index) 818 { 819 return getItemAt(_index); 820 } 821 _setItemNameAt(size_t _index,const UString & _name)822 void MenuControl::_setItemNameAt(size_t _index, const UString& _name) 823 { 824 setItemNameAt(_index, _name); 825 } 826 _getItemNameAt(size_t _index)827 const UString& MenuControl::_getItemNameAt(size_t _index) 828 { 829 return getItemNameAt(_index); 830 } 831 _setItemSelected(IItem * _item)832 void MenuControl::_setItemSelected(IItem* _item) 833 { 834 MenuItem* item = static_cast<MenuItem*>(_item); 835 for (VectorMenuItemInfo::iterator iter = mItemsInfo.begin(); iter != mItemsInfo.end(); ++iter) 836 { 837 if ((*iter).type == MenuItemType::Popup) 838 { 839 (*iter).item->setStateSelected(false); 840 841 if ((*iter).submenu != nullptr) 842 (*iter).submenu->setVisible(false); 843 } 844 } 845 846 if (item->getItemType() == MenuItemType::Popup) 847 { 848 item->setStateSelected(true); 849 size_t index = getItemIndex(item); 850 851 _setItemChildVisibleAt(index, true, false); 852 853 _updateItems(index); 854 } 855 } 856 _updateItems(size_t _index)857 void MenuControl::_updateItems(size_t _index) 858 { 859 if (mItemsInfo[_index].submenu != nullptr) 860 mItemsInfo[_index].submenu->_updateSizeForEmpty(); 861 } 862 _updateSizeForEmpty()863 void MenuControl::_updateSizeForEmpty() 864 { 865 if (mItemsInfo.empty()) 866 setSize(100, 100); 867 } 868 setVerticalAlignment(bool _value)869 void MenuControl::setVerticalAlignment(bool _value) 870 { 871 mVerticalAlignment = _value; 872 873 update(); 874 } 875 getVerticalAlignment() const876 bool MenuControl::getVerticalAlignment() const 877 { 878 return mVerticalAlignment; 879 } 880 setPropertyOverride(const std::string & _key,const std::string & _value)881 void MenuControl::setPropertyOverride(const std::string& _key, const std::string& _value) 882 { 883 /// @wproperty{MenuControl, VerticalAlignment, bool} Вертикальное выравнивание. 884 if (_key == "VerticalAlignment") 885 setVerticalAlignment(utility::parseValue<bool>(_value)); 886 887 else 888 { 889 Base::setPropertyOverride(_key, _value); 890 return; 891 } 892 893 eventChangeProperty(this, _key, _value); 894 } 895 896 } // namespace MyGUI 897