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_TabControl.h" 9 #include "MyGUI_ControllerManager.h" 10 #include "MyGUI_WidgetManager.h" 11 #include "MyGUI_Button.h" 12 #include "MyGUI_TabItem.h" 13 #include "MyGUI_ResourceSkin.h" 14 15 namespace MyGUI 16 { 17 18 const float TAB_SPEED_FADE_COEF = 5.0f; 19 TabControl()20 TabControl::TabControl() : 21 mOffsetTab(0), 22 mButtonShow(true), 23 mWidthBar(0), 24 mWidgetBar(nullptr), 25 mButtonLeft(nullptr), 26 mButtonRight(nullptr), 27 mButtonDecor(nullptr), 28 mEmptyBarWidget(nullptr), 29 mItemTemplate(nullptr), 30 mStartIndex(0), 31 mIndexSelect(ITEM_NONE), 32 mButtonDefaultWidth(1), 33 mSmoothShow(true), 34 mButtonAutoWidth(true), 35 mShutdown(false), 36 mHeaderPlace(nullptr), 37 mControls(nullptr), 38 mEmpty(nullptr) 39 { 40 } 41 initialiseOverride()42 void TabControl::initialiseOverride() 43 { 44 Base::initialiseOverride(); 45 46 if (isUserString("ButtonSkin")) 47 mButtonSkinName = getUserString("ButtonSkin"); 48 49 // OBSOLETE 50 if (isUserString("OffsetBar")) 51 mOffsetTab = utility::parseValue<int>(getUserString("OffsetBar")); 52 53 // OBSOLETE 54 if (isUserString("EmptyBarSkin")) 55 mEmptySkinName = getUserString("EmptyBarSkin"); 56 57 // OBSOLETE 58 assignWidget(mWidgetBar, "Bar"); 59 if (mWidgetBar != nullptr) 60 { 61 mWidgetBar->setSize(mWidgetBar->getWidth() - mOffsetTab, mWidgetBar->getHeight()); 62 } 63 64 ///@wskin_child{TabControl, Button, Left} Кнопка прокрутки заголовков влево. 65 assignWidget(mButtonLeft, "Left"); 66 if (mButtonLeft != nullptr) 67 { 68 mButtonLeft->eventMouseButtonClick += newDelegate(this, &TabControl::notifyPressedButtonEvent); 69 } 70 71 ///@wskin_child{TabControl, Button, Right} Кнопка прокрутки заголовков вправо. 72 assignWidget(mButtonRight, "Right"); 73 if (mButtonRight != nullptr) 74 { 75 mButtonRight->eventMouseButtonClick += newDelegate(this, &TabControl::notifyPressedButtonEvent); 76 } 77 78 // OBSOLETE 79 assignWidget(mButtonDecor, "ButtonDecor"); 80 if (mButtonDecor != nullptr) 81 { 82 mButtonDecor->setVisible(false); 83 } 84 85 ///@wskin_child{TabControl, Widget, TabItem} Шаблон для страницы, по которому будут создаваться клиентские зоны страниц. 86 assignWidget(mItemTemplate, "TabItem"); 87 if (mItemTemplate != nullptr) 88 { 89 mItemTemplate->setVisible(false); 90 } 91 92 #ifndef MYGUI_DONT_USE_OBSOLETE 93 if (mItemTemplate == nullptr) 94 { 95 assignWidget(mItemTemplate, "Sheet"); 96 if (mItemTemplate != nullptr) 97 { 98 mItemTemplate->setVisible(false); 99 } 100 } 101 #endif // MYGUI_DONT_USE_OBSOLETE 102 103 // OBSOLETE 104 Widget* showPatch = nullptr; 105 assignWidget(showPatch, "ShowPatch"); 106 if (showPatch != nullptr) 107 { 108 mWidgetsPatch.push_back(showPatch); 109 showPatch->setVisible(false); 110 } 111 112 ///@wskin_child{TabControl, Widget, HeaderPlace} Место для заголовоков. 113 assignWidget(mHeaderPlace, "HeaderPlace"); 114 115 ///@wskin_child{TabControl, Widget, Controls} Виджет на котором должны быть расположены кнопки влево и вправо для заголовоков. 116 assignWidget(mControls, "Controls"); 117 118 ///@wskin_child{TabControl, Widget, Empty} Виджет который будет показываться в месте где нет заголовков (справа от заголовков). 119 assignWidget(mEmpty, "Empty"); 120 121 if (mEmpty == nullptr) 122 { 123 // создаем виджет, носитель скина пустоты бара 124 // OBSOLETE 125 mEmptyBarWidget = _getWidgetBar()->createWidget<Widget>(mEmptySkinName, IntCoord(), Align::Left | Align::Top); 126 } 127 128 updateBar(); 129 130 // FIXME добавленно, так как шетдаун вызывается и при смене скина 131 mShutdown = false; 132 } 133 shutdownOverride()134 void TabControl::shutdownOverride() 135 { 136 mWidgetsPatch.clear(); 137 mWidgetBar = nullptr; 138 mButtonLeft = nullptr; 139 mButtonRight = nullptr; 140 mButtonDecor = nullptr; 141 mItemTemplate = nullptr; 142 mEmptyBarWidget = nullptr; 143 144 mHeaderPlace = nullptr; 145 mControls = nullptr; 146 mEmpty = nullptr; 147 148 // FIXME перенесенно из деструктора, может косячить при смене скина 149 mShutdown = true; 150 151 Base::shutdownOverride(); 152 } 153 onWidgetCreated(Widget * _widget)154 void TabControl::onWidgetCreated(Widget* _widget) 155 { 156 Base::onWidgetCreated(_widget); 157 158 TabItem* child = _widget->castType<TabItem>(false); 159 if (child != nullptr) 160 { 161 child->setCoord(_getWidgetTemplate()->getAbsoluteLeft() - getAbsoluteLeft(), _getWidgetTemplate()->getAbsoluteTop() - getAbsoluteTop(), _getWidgetTemplate()->getWidth(), _getWidgetTemplate()->getHeight()); 162 child->setAlign(_getWidgetTemplate()->getAlign()); 163 164 _insertItem(ITEM_NONE, "", child, Any::Null); 165 } 166 } 167 insertItemAt(size_t _index,const UString & _name,Any _data)168 TabItem* TabControl::insertItemAt(size_t _index, const UString& _name, Any _data) 169 { 170 MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "TabControl::insertItem"); 171 172 Widget* widget = Base::baseCreateWidget(WidgetStyle::Child, TabItem::getClassTypeName(), "Default", _getWidgetTemplate()->getCoord(), _getWidgetTemplate()->getAlign(), "", "", false); 173 174 size_t lastIndex = mItemsInfo.size() - 1; 175 setItemNameAt(lastIndex, _name); 176 setItemDataAt(lastIndex, _data); 177 178 swapItems(_index == ITEM_NONE ? lastIndex : _index, lastIndex); 179 180 return widget->castType<TabItem>(); 181 } 182 swapItems(size_t _index1,size_t _index2)183 void TabControl::swapItems(size_t _index1, size_t _index2) 184 { 185 MYGUI_ASSERT_RANGE(_index1, mItemsInfo.size(), "TabControl::swapItems"); 186 MYGUI_ASSERT_RANGE(_index2, mItemsInfo.size(), "TabControl::swapItems"); 187 188 if (_index1 != _index2) 189 { 190 std::swap(mItemsInfo[_index1], mItemsInfo[_index2]); 191 updateBar(); 192 } 193 } 194 setPosition(const IntPoint & _point)195 void TabControl::setPosition(const IntPoint& _point) 196 { 197 Base::setPosition(_point); 198 199 updateBar(); 200 } 201 setSize(const IntSize & _size)202 void TabControl::setSize(const IntSize& _size) 203 { 204 Base::setSize(_size); 205 206 updateBar(); 207 } 208 setCoord(const IntCoord & _coord)209 void TabControl::setCoord(const IntCoord& _coord) 210 { 211 Base::setCoord(_coord); 212 213 updateBar(); 214 } 215 notifyPressedButtonEvent(MyGUI::Widget * _sender)216 void TabControl::notifyPressedButtonEvent(MyGUI::Widget* _sender) 217 { 218 if (_sender == mButtonLeft) 219 { 220 if (mStartIndex > 0) 221 { 222 mStartIndex --; 223 updateBar(); 224 } 225 } 226 else if (_sender == mButtonRight) 227 { 228 if ((mStartIndex + 1) < mItemsInfo.size()) 229 { 230 mStartIndex ++; 231 // в updateBar() будет подкорректированно если что 232 updateBar(); 233 } 234 } 235 } 236 notifyPressedBarButtonEvent(MyGUI::Widget * _sender)237 void TabControl::notifyPressedBarButtonEvent(MyGUI::Widget* _sender) 238 { 239 size_t select = *_sender->_getInternalData<size_t>() + mStartIndex; 240 // щелкнули по той же кнопке 241 if (select == mIndexSelect) 242 { 243 // стараемся показать выделенную кнопку 244 beginToItemSelected(); 245 return; 246 } 247 size_t old = mIndexSelect; 248 mIndexSelect = select; 249 250 size_t count = 0; 251 for (size_t pos = 0; pos < mItemButton.size(); pos++) 252 { 253 Button* button = mItemButton[count]->castType<Button>(); 254 if (button->getVisible()) 255 { 256 // корректируем нажатость кнопки 257 button->setStateSelected((pos + mStartIndex) == mIndexSelect); 258 } 259 count ++; 260 } 261 262 // стараемся показать выделенную кнопку 263 beginToItemSelected(); 264 265 // поднимаем страницу для пикинга 266 _forcePick(mItemsInfo[mIndexSelect].item); 267 268 _showItem(mItemsInfo[mIndexSelect].item, true, mSmoothShow); 269 _showItem(mItemsInfo[old].item, false, mSmoothShow); 270 271 eventTabChangeSelect(this, mIndexSelect); 272 } 273 beginToItemAt(size_t _index)274 void TabControl::beginToItemAt(size_t _index) 275 { 276 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::beginToItemAt"); 277 278 // подстраховка 279 if (_getWidgetBar()->getWidth() < 1) 280 return; 281 282 if (_index == mStartIndex) 283 return; 284 else if (_index < mStartIndex) 285 { 286 mStartIndex = _index; 287 updateBar(); 288 } 289 else 290 { 291 // длинна бара от старт индекса до нужной включительно 292 int width = 0; 293 for (size_t pos = mStartIndex; pos <= _index; pos++) 294 { 295 width += mItemsInfo[pos].width; 296 } 297 298 // уменьшем старт индекс пока не появиться нужная 299 bool change = false; 300 while ((mStartIndex < _index) && (width > _getWidgetBar()->getWidth())) 301 { 302 width -= mItemsInfo[mStartIndex].width; 303 mStartIndex ++; 304 change = true; 305 } 306 if (change) 307 updateBar(); 308 } 309 } 310 setButtonDefaultWidth(int _width)311 void TabControl::setButtonDefaultWidth(int _width) 312 { 313 mButtonDefaultWidth = _width; 314 if (mButtonDefaultWidth < 1) 315 mButtonDefaultWidth = 1; 316 setButtonAutoWidth(false); 317 } 318 setButtonAutoWidth(bool _auto)319 void TabControl::setButtonAutoWidth(bool _auto) 320 { 321 mButtonAutoWidth = _auto; 322 323 for (size_t pos = 0; pos < mItemsInfo.size(); pos++) 324 { 325 int width; 326 if (mButtonAutoWidth) 327 width = _getTextWidth(mItemsInfo[pos].name); 328 else 329 width = mButtonDefaultWidth; 330 331 mWidthBar += width - mItemsInfo[pos].width; 332 mItemsInfo[pos].width = width; 333 } 334 335 updateBar(); 336 } 337 setButtonWidthAt(size_t _index,int _width)338 void TabControl::setButtonWidthAt(size_t _index, int _width) 339 { 340 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::setButtonWidthAt"); 341 342 if (_width <= 0) 343 { 344 if (mButtonAutoWidth) 345 _width = _getTextWidth(mItemsInfo[_index].name); 346 else 347 _width = mButtonDefaultWidth; 348 } 349 350 mWidthBar += _width - mItemsInfo[_index].width; 351 mItemsInfo[_index].width = _width; 352 353 updateBar(); 354 } 355 setItemNameAt(size_t _index,const UString & _name)356 void TabControl::setItemNameAt(size_t _index, const UString& _name) 357 { 358 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::setItemNameAt"); 359 mItemsInfo[_index].name = _name; 360 361 int width; 362 if (mButtonAutoWidth) 363 width = _getTextWidth(_name); 364 else 365 width = mButtonDefaultWidth; 366 367 mWidthBar += width - mItemsInfo[_index].width; 368 mItemsInfo[_index].width = width; 369 370 updateBar(); 371 } 372 setIndexSelected(size_t _index)373 void TabControl::setIndexSelected(size_t _index) 374 { 375 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::setIndexSelected"); 376 if (mIndexSelect == _index) 377 return; 378 size_t old = mIndexSelect; 379 mIndexSelect = _index; 380 updateBar(); 381 382 // поднимаем страницу для пикинга 383 if (mSmoothShow) 384 _forcePick(mItemsInfo[mIndexSelect].item); 385 386 _showItem(mItemsInfo[mIndexSelect].item, true, mSmoothShow); 387 _showItem(mItemsInfo[old].item, false, mSmoothShow); 388 389 beginToItemSelected(); 390 } 391 actionWidgetHide(Widget * _widget,ControllerItem * _controller)392 void TabControl::actionWidgetHide(Widget* _widget, ControllerItem* _controller) 393 { 394 _widget->setVisible(false); 395 _widget->setEnabled(true); 396 } 397 _showItem(TabItem * _item,bool _show,bool _smooth)398 void TabControl::_showItem(TabItem* _item, bool _show, bool _smooth) 399 { 400 if (!_smooth) 401 { 402 ControllerManager::getInstance().removeItem(_item); 403 _item->setAlpha(ALPHA_MAX); 404 405 _item->setVisible(_show); 406 407 return; 408 } 409 410 if (_show) 411 { 412 ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MAX, TAB_SPEED_FADE_COEF, true); 413 ControllerManager::getInstance().addItem(_item, controller); 414 } 415 else 416 { 417 ControllerFadeAlpha* controller = createControllerFadeAlpha(ALPHA_MIN, TAB_SPEED_FADE_COEF, false); 418 controller->eventPostAction += newDelegate(this, &TabControl::actionWidgetHide); 419 ControllerManager::getInstance().addItem(_item, controller); 420 } 421 } 422 createButton()423 Button* TabControl::createButton() 424 { 425 Widget* parent = this; 426 if (mWidgetBar != nullptr) 427 parent = mWidgetBar; 428 else if (mHeaderPlace != nullptr) 429 parent = mHeaderPlace; 430 431 return parent->createWidget<Button>(mButtonSkinName, IntCoord(), Align::Left | Align::Top); 432 } 433 _createItemButton()434 void TabControl::_createItemButton() 435 { 436 Button* button = createButton(); 437 button->eventMouseButtonClick += newDelegate(this, &TabControl::notifyPressedBarButtonEvent); 438 button->_setInternalData(mItemButton.size()); // порядковый номер 439 mItemButton.push_back(button); 440 } 441 _getTextWidth(const UString & _text)442 int TabControl::_getTextWidth(const UString& _text) 443 { 444 if (mItemButton.empty()) 445 _createItemButton(); 446 447 UString save = mItemButton[0]->getCaption(); 448 mItemButton[0]->setCaption(_text); 449 450 ISubWidgetText* text = mItemButton[0]->getSubWidgetText(); 451 const IntSize& size = text ? text->getTextSize() : IntSize(); 452 const IntCoord& coord = text ? text->getCoord() : IntCoord(); 453 454 mItemButton[0]->setCaption(save); 455 456 return size.width + mItemButton[0]->getWidth() - coord.width; 457 } 458 _notifyDeleteItem(TabItem * _sheet)459 void TabControl::_notifyDeleteItem(TabItem* _sheet) 460 { 461 // общий шутдаун виджета 462 if (mShutdown) 463 return; 464 465 size_t index = getItemIndex(_sheet); 466 467 mWidthBar -= mItemsInfo[index].width; 468 mItemsInfo.erase(mItemsInfo.begin() + index); 469 470 if (mItemsInfo.empty()) 471 mIndexSelect = ITEM_NONE; 472 else 473 { 474 if (index < mIndexSelect) 475 mIndexSelect --; 476 else if (index == mIndexSelect) 477 { 478 if (mIndexSelect == mItemsInfo.size()) 479 mIndexSelect --; 480 mItemsInfo[mIndexSelect].item->setVisible(true); 481 mItemsInfo[mIndexSelect].item->setAlpha(ALPHA_MAX); 482 } 483 } 484 485 updateBar(); 486 } 487 _insertItem(size_t _index,const UString & _name,TabItem * _sheet,Any _data)488 void TabControl::_insertItem(size_t _index, const UString& _name, TabItem* _sheet, Any _data) 489 { 490 if (_index == ITEM_NONE) 491 _index = mItemsInfo.size(); 492 493 // добавляем инфу о вкладке 494 int width = (mButtonAutoWidth ? _getTextWidth(_name) : mButtonDefaultWidth); 495 mWidthBar += width; 496 497 mItemsInfo.insert(mItemsInfo.begin() + _index, TabItemInfo(width, _name, _sheet, _data)); 498 499 // первая вкладка 500 if (1 == mItemsInfo.size()) 501 mIndexSelect = 0; 502 else 503 { 504 _sheet->setVisible(false); 505 if (_index <= mIndexSelect) 506 mIndexSelect ++; 507 } 508 509 updateBar(); 510 } 511 setItemDataAt(size_t _index,Any _data)512 void TabControl::setItemDataAt(size_t _index, Any _data) 513 { 514 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::setItemDataAt"); 515 mItemsInfo[_index].data = _data; 516 } 517 getButtonWidthAt(size_t _index)518 int TabControl::getButtonWidthAt(size_t _index) 519 { 520 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::getButtonWidthAt"); 521 return mItemsInfo[_index].width; 522 } 523 getItemNameAt(size_t _index)524 const UString& TabControl::getItemNameAt(size_t _index) 525 { 526 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::getItemNameAt"); 527 return mItemsInfo[_index].name; 528 } 529 getItemAt(size_t _index)530 TabItem* TabControl::getItemAt(size_t _index) 531 { 532 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::getItemAt"); 533 return mItemsInfo[_index].item; 534 } 535 removeItemAt(size_t _index)536 void TabControl::removeItemAt(size_t _index) 537 { 538 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "TabControl::removeItemAt"); 539 this->_destroyChildWidget(mItemsInfo[_index].item); 540 } 541 removeAllItems()542 void TabControl::removeAllItems() 543 { 544 while (!mItemsInfo.empty()) 545 { 546 _destroyChildWidget(mItemsInfo.back().item); 547 } 548 } 549 createControllerFadeAlpha(float _alpha,float _coef,bool _enable)550 ControllerFadeAlpha* TabControl::createControllerFadeAlpha(float _alpha, float _coef, bool _enable) 551 { 552 ControllerItem* item = ControllerManager::getInstance().createItem(ControllerFadeAlpha::getClassTypeName()); 553 ControllerFadeAlpha* controller = item->castType<ControllerFadeAlpha>(); 554 555 controller->setAlpha(_alpha); 556 controller->setCoef(_coef); 557 controller->setEnabled(_enable); 558 559 return controller; 560 } 561 getItemIndex(TabItem * _item)562 size_t TabControl::getItemIndex(TabItem* _item) 563 { 564 for (size_t pos = 0; pos < mItemsInfo.size(); pos++) 565 { 566 if (mItemsInfo[pos].item == _item) 567 return pos; 568 } 569 MYGUI_EXCEPT("item (" << _item << ") not found, source 'TabControl::getItemIndex'"); 570 } 571 findItemIndex(TabItem * _item)572 size_t TabControl::findItemIndex(TabItem* _item) 573 { 574 for (size_t pos = 0; pos < mItemsInfo.size(); pos++) 575 { 576 if (mItemsInfo[pos].item == _item) 577 return pos; 578 } 579 return ITEM_NONE; 580 } 581 findItemIndexWith(const UString & _name)582 size_t TabControl::findItemIndexWith(const UString& _name) 583 { 584 for (size_t pos = 0; pos < mItemsInfo.size(); pos++) 585 { 586 if (mItemsInfo[pos].name == _name) 587 return pos; 588 } 589 return ITEM_NONE; 590 } 591 findItemWith(const UString & _name)592 TabItem* TabControl::findItemWith(const UString& _name) 593 { 594 for (size_t pos = 0; pos < mItemsInfo.size(); pos++) 595 { 596 if (mItemsInfo[pos].name == _name) 597 return mItemsInfo[pos].item; 598 } 599 return nullptr; 600 } 601 getItemSelected()602 TabItem* TabControl::getItemSelected() 603 { 604 return getIndexSelected() != ITEM_NONE ? getItemAt(getIndexSelected()) : nullptr; 605 } 606 _getWidgetTemplate()607 Widget* TabControl::_getWidgetTemplate() 608 { 609 return mItemTemplate == nullptr ? this : mItemTemplate; 610 } 611 _getWidgetBar()612 Widget* TabControl::_getWidgetBar() 613 { 614 return mWidgetBar == nullptr ? this : mWidgetBar; 615 } 616 setPropertyOverride(const std::string & _key,const std::string & _value)617 void TabControl::setPropertyOverride(const std::string& _key, const std::string& _value) 618 { 619 /// @wproperty{TabControl, ButtonWidth, int} Ширина кнопок в заголовках в пикселях. 620 if (_key == "ButtonWidth") 621 setButtonDefaultWidth(utility::parseValue<int>(_value)); 622 623 /// @wproperty{TabControl, ButtonAutoWidth, bool} Режим автоматического вычисления ширины кнопок в заголовках. 624 else if (_key == "ButtonAutoWidth") 625 setButtonAutoWidth(utility::parseValue<bool>(_value)); 626 627 /// @wproperty{TabControl, SmoothShow, bool} Плавное переключение между закладками. 628 else if (_key == "SmoothShow") 629 setSmoothShow(utility::parseValue<bool>(_value)); 630 631 // не коментировать 632 else if (_key == "SelectItem") 633 setIndexSelected(utility::parseValue<size_t>(_value)); 634 635 else 636 { 637 Base::setPropertyOverride(_key, _value); 638 return; 639 } 640 641 eventChangeProperty(this, _key, _value); 642 } 643 getItemCount() const644 size_t TabControl::getItemCount() const 645 { 646 return mItemsInfo.size(); 647 } 648 insertItem(TabItem * _to,const UString & _name,Any _data)649 TabItem* TabControl::insertItem(TabItem* _to, const UString& _name, Any _data) 650 { 651 return insertItemAt(getItemIndex(_to), _name, _data); 652 } 653 addItem(const UString & _name,Any _data)654 TabItem* TabControl::addItem(const UString& _name, Any _data) 655 { 656 return insertItemAt(ITEM_NONE, _name, _data); 657 } 658 removeItem(TabItem * _item)659 void TabControl::removeItem(TabItem* _item) 660 { 661 removeItemAt(getItemIndex(_item)); 662 } 663 getIndexSelected() const664 size_t TabControl::getIndexSelected() const 665 { 666 return mIndexSelect; 667 } 668 setItemSelected(TabItem * _item)669 void TabControl::setItemSelected(TabItem* _item) 670 { 671 setIndexSelected(getItemIndex(_item)); 672 } 673 setItemData(TabItem * _item,Any _data)674 void TabControl::setItemData(TabItem* _item, Any _data) 675 { 676 setItemDataAt(getItemIndex(_item), _data); 677 } 678 clearItemDataAt(size_t _index)679 void TabControl::clearItemDataAt(size_t _index) 680 { 681 setItemDataAt(_index, Any::Null); 682 } 683 clearItemData(TabItem * _item)684 void TabControl::clearItemData(TabItem* _item) 685 { 686 clearItemDataAt(getItemIndex(_item)); 687 } 688 setItemName(TabItem * _item,const UString & _name)689 void TabControl::setItemName(TabItem* _item, const UString& _name) 690 { 691 setItemNameAt(getItemIndex(_item), _name); 692 } 693 getItemName(TabItem * _item)694 const UString& TabControl::getItemName(TabItem* _item) 695 { 696 return getItemNameAt(getItemIndex(_item)); 697 } 698 beginToItem(TabItem * _item)699 void TabControl::beginToItem(TabItem* _item) 700 { 701 beginToItemAt(getItemIndex(_item)); 702 } 703 beginToItemFirst()704 void TabControl::beginToItemFirst() 705 { 706 if (getItemCount()) 707 beginToItemAt(0); 708 } 709 beginToItemLast()710 void TabControl::beginToItemLast() 711 { 712 if (getItemCount()) 713 beginToItemAt(getItemCount() - 1); 714 } 715 beginToItemSelected()716 void TabControl::beginToItemSelected() 717 { 718 if (getIndexSelected() != ITEM_NONE) 719 beginToItemAt(getIndexSelected()); 720 } 721 setButtonWidth(TabItem * _item,int _width)722 void TabControl::setButtonWidth(TabItem* _item, int _width) 723 { 724 setButtonWidthAt(getItemIndex(_item), _width); 725 } 726 getButtonWidth(TabItem * _item)727 int TabControl::getButtonWidth(TabItem* _item) 728 { 729 return getButtonWidthAt(getItemIndex(_item)); 730 } 731 getButtonDefaultWidth() const732 int TabControl::getButtonDefaultWidth() const 733 { 734 return mButtonDefaultWidth; 735 } 736 getButtonAutoWidth() const737 bool TabControl::getButtonAutoWidth() const 738 { 739 return mButtonAutoWidth; 740 } 741 setSmoothShow(bool _value)742 void TabControl::setSmoothShow(bool _value) 743 { 744 mSmoothShow = _value; 745 } 746 getSmoothShow() const747 bool TabControl::getSmoothShow() const 748 { 749 return mSmoothShow; 750 } 751 _getItemCount()752 size_t TabControl::_getItemCount() 753 { 754 return getItemCount(); 755 } 756 _addItem(const MyGUI::UString & _name)757 void TabControl::_addItem(const MyGUI::UString& _name) 758 { 759 addItem(_name); 760 } 761 _removeItemAt(size_t _index)762 void TabControl::_removeItemAt(size_t _index) 763 { 764 removeItemAt(_index); 765 } 766 _getItemAt(size_t _index)767 Widget* TabControl::_getItemAt(size_t _index) 768 { 769 return getItemAt(_index); 770 } 771 _setItemNameAt(size_t _index,const UString & _name)772 void TabControl::_setItemNameAt(size_t _index, const UString& _name) 773 { 774 setItemNameAt(_index, _name); 775 } 776 _getItemNameAt(size_t _index)777 const UString& TabControl::_getItemNameAt(size_t _index) 778 { 779 return getItemNameAt(_index); 780 } 781 updateBar()782 void TabControl::updateBar() 783 { 784 if (mHeaderPlace != nullptr) 785 updateBarNew(); 786 else 787 updateBarOld(); 788 } 789 updateBarOld()790 void TabControl::updateBarOld() 791 { 792 // подстраховка 793 if (_getWidgetBar()->getWidth() < 1) 794 return; 795 796 if ((_getWidgetBar()->getWidth() < mWidthBar) && (1 < mItemsInfo.size())) 797 { 798 if (!mButtonShow) 799 { 800 mButtonShow = true; 801 802 if (nullptr != mButtonLeft) 803 mButtonLeft->setVisible(true); 804 if (nullptr != mButtonRight) 805 mButtonRight->setVisible(true); 806 if (nullptr != mButtonDecor) 807 mButtonDecor->setVisible(true); 808 for (VectorWidgetPtr::iterator iter = mWidgetsPatch.begin(); iter != mWidgetsPatch.end(); ++iter) 809 (*iter)->setVisible(true); 810 if (mWidgetBar != nullptr) 811 mWidgetBar->setSize(mWidgetBar->getWidth() - mOffsetTab, mWidgetBar->getHeight()); 812 } 813 } 814 else 815 { 816 if (mButtonShow) 817 { 818 mButtonShow = false; 819 if (nullptr != mButtonLeft) 820 mButtonLeft->setVisible(false); 821 if (nullptr != mButtonRight) 822 mButtonRight->setVisible(false); 823 if (nullptr != mButtonDecor) 824 mButtonDecor->setVisible(false); 825 for (VectorWidgetPtr::iterator iter = mWidgetsPatch.begin(); iter != mWidgetsPatch.end(); ++iter) 826 (*iter)->setVisible(false); 827 if (mWidgetBar != nullptr) 828 mWidgetBar->setSize(mWidgetBar->getWidth() + mOffsetTab, mWidgetBar->getHeight()); 829 } 830 } 831 832 // проверяем правильность стартового индекса 833 if (mStartIndex > 0) 834 { 835 // считаем длинну видимых кнопок 836 int width = 0; 837 for (size_t pos = mStartIndex; pos < mItemsInfo.size(); pos++) 838 width += mItemsInfo[pos].width; 839 840 // уменьшаем индекс до тех пор пока кнопка до индекста полностью не влезет в бар 841 while ((mStartIndex > 0) && ((width + mItemsInfo[mStartIndex - 1].width) <= _getWidgetBar()->getWidth())) 842 { 843 mStartIndex--; 844 width += mItemsInfo[mStartIndex].width; 845 } 846 } 847 848 // проверяем и обновляем бар 849 int width = 0; 850 size_t count = 0; 851 size_t pos = mStartIndex; 852 for (; pos < mItemsInfo.size(); pos++) 853 { 854 // текущая кнопка не влазиет 855 if (width > _getWidgetBar()->getWidth()) 856 break; 857 858 // следующая не влазиет 859 TabItemInfo& info = mItemsInfo[pos]; 860 if ((width + info.width) > _getWidgetBar()->getWidth()) 861 { 862 break; 863 } 864 865 // проверяем физическое наличие кнопки 866 if (count >= mItemButton.size()) 867 _createItemButton(); 868 869 // если кнопка не соответствует, то изменяем ее 870 Button* button = mItemButton[count]->castType<Button>(); 871 button->setVisible(true); 872 873 // корректируем нажатость кнопки 874 button->setStateSelected(pos == mIndexSelect); 875 876 if (button->getCaption() != info.name) 877 button->setCaption(info.name); 878 // положение кнопки 879 IntCoord coord(width, 0, info.width, _getWidgetBar()->getHeight()); 880 if (coord != button->getCoord()) 881 button->setCoord(coord); 882 883 width += info.width; 884 count ++; 885 } 886 887 // скрываем кнопки что были созданны, но не видны 888 while (count < mItemButton.size()) 889 { 890 mItemButton[count]->setVisible(false); 891 count ++; 892 } 893 894 bool right = true; 895 if (pos == mItemsInfo.size()) 896 right = false; 897 898 // в редакторе падает почему то, хотя этот скин создается всегда 899 if (mEmptyBarWidget != nullptr) 900 { 901 // корректируем виджет для пустоты 902 if (width < _getWidgetBar()->getWidth()) 903 { 904 mEmptyBarWidget->setVisible(true); 905 mEmptyBarWidget->setCoord(width, 0, _getWidgetBar()->getWidth() - width, _getWidgetBar()->getHeight()); 906 } 907 else 908 { 909 mEmptyBarWidget->setVisible(false); 910 } 911 } 912 913 // корректируем доступность стрелок 914 if (mStartIndex == 0) 915 { 916 if (nullptr != mButtonLeft) 917 mButtonLeft->setEnabled(false); 918 } 919 else 920 { 921 if (nullptr != mButtonLeft) 922 mButtonLeft->setEnabled(true); 923 } 924 925 if (right) 926 { 927 if (nullptr != mButtonRight) 928 mButtonRight->setEnabled(true); 929 } 930 else 931 { 932 if (nullptr != mButtonRight) 933 mButtonRight->setEnabled(false); 934 } 935 } 936 updateBarNew()937 void TabControl::updateBarNew() 938 { 939 if (mHeaderPlace == nullptr) 940 return; 941 942 // подстраховка 943 if (mHeaderPlace->getWidth() < 1) 944 return; 945 946 int widthControls = 0; 947 if (mControls != nullptr) 948 widthControls = mControls->getWidth(); 949 950 if ((mHeaderPlace->getWidth() < mWidthBar) && (1 < mItemsInfo.size()) && (mHeaderPlace->getWidth() >= widthControls)) 951 { 952 if (!mButtonShow) 953 { 954 mButtonShow = true; 955 956 if (nullptr != mControls) 957 mControls->setVisible(true); 958 } 959 960 if (mControls != nullptr) 961 mControls->setCoord(mHeaderPlace->getWidth() - mControls->getWidth(), 0, mControls->getWidth(), mHeaderPlace->getHeight()); 962 } 963 else 964 { 965 if (mButtonShow) 966 { 967 mButtonShow = false; 968 969 if (nullptr != mControls) 970 mControls->setVisible(false); 971 } 972 973 widthControls = 0; 974 } 975 976 // проверяем правильность стартового индекса 977 if (mStartIndex > 0) 978 { 979 // считаем длинну видимых кнопок 980 int width = 0; 981 for (size_t pos = mStartIndex; pos < mItemsInfo.size(); pos++) 982 width += mItemsInfo[pos].width; 983 984 // уменьшаем индекс до тех пор пока кнопка до индекста полностью не влезет в бар 985 while ((mStartIndex > 0) && ((width + mItemsInfo[mStartIndex - 1].width) <= (mHeaderPlace->getWidth() - widthControls))) 986 { 987 mStartIndex--; 988 width += mItemsInfo[mStartIndex].width; 989 } 990 } 991 992 // проверяем и обновляем бар 993 int width = 0; 994 size_t count = 0; 995 size_t pos = mStartIndex; 996 for (; pos < mItemsInfo.size(); pos++) 997 { 998 // текущая кнопка не влазиет 999 if (width > (mHeaderPlace->getWidth() - widthControls)) 1000 break; 1001 1002 // следующая не влазиет 1003 TabItemInfo& info = mItemsInfo[pos]; 1004 if ((width + info.width) > (mHeaderPlace->getWidth() - widthControls)) 1005 { 1006 break; 1007 } 1008 1009 // проверяем физическое наличие кнопки 1010 if (count >= mItemButton.size()) 1011 _createItemButton(); 1012 1013 // если кнопка не соответствует, то изменяем ее 1014 Button* button = mItemButton[count]; 1015 button->setVisible(true); 1016 1017 // корректируем нажатость кнопки 1018 button->setStateSelected(pos == mIndexSelect); 1019 1020 if (button->getCaption() != info.name) 1021 button->setCaption(info.name); 1022 // положение кнопки 1023 IntCoord coord(width, 0, info.width, mHeaderPlace->getHeight()); 1024 if (coord != button->getCoord()) 1025 button->setCoord(coord); 1026 1027 width += info.width; 1028 count ++; 1029 } 1030 1031 // скрываем кнопки что были созданны, но не видны 1032 while (count < mItemButton.size()) 1033 { 1034 mItemButton[count]->setVisible(false); 1035 count ++; 1036 } 1037 1038 bool right = true; 1039 if (pos == mItemsInfo.size()) 1040 right = false; 1041 1042 if (mEmpty != nullptr) 1043 { 1044 // корректируем виджет для пустоты 1045 mEmpty->setCoord(width, 0, mHeaderPlace->getWidth() - width - widthControls, mHeaderPlace->getHeight()); 1046 } 1047 1048 // корректируем доступность стрелок 1049 if (mStartIndex == 0) 1050 { 1051 if (nullptr != mButtonLeft) 1052 mButtonLeft->setEnabled(false); 1053 } 1054 else 1055 { 1056 if (nullptr != mButtonLeft) 1057 mButtonLeft->setEnabled(true); 1058 } 1059 1060 if (right) 1061 { 1062 if (nullptr != mButtonRight) 1063 mButtonRight->setEnabled(true); 1064 } 1065 else 1066 { 1067 if (nullptr != mButtonRight) 1068 mButtonRight->setEnabled(false); 1069 } 1070 } 1071 1072 } // namespace MyGUI 1073