MyGUI: MyGUI_MultiListBox.cpp Source File

MyGUI 3.4.3

MyGUI_MultiListBox.cpp
Go to the documentation of this file.
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_MultiListBox.h"
9#include "MyGUI_MultiListItem.h"
10#include "MyGUI_ResourceSkin.h"
11#include "MyGUI_Button.h"
12#include "MyGUI_ImageBox.h"
13#include "MyGUI_ListBox.h"
14#include "MyGUI_Gui.h"
15#include "MyGUI_WidgetManager.h"
16
17namespace MyGUI
18{
19
20 void MultiListBox::initialiseOverride()
21 {
22 Base::initialiseOverride();
23
24 if (isUserString("SkinButton"))
25 mSkinButton = getUserString("SkinButton");
26
27 if (isUserString("SkinList"))
28 mSkinList = getUserString("SkinList");
29
30 if (isUserString("SkinSeparator"))
31 mSkinSeparator = getUserString("SkinSeparator");
32
33 if (isUserString("WidthSeparator"))
34 mWidthSeparator = utility::parseValue<int>(getUserString("WidthSeparator"));
35
36 // OBSOLETE
37 if (isUserString("HeightButton"))
38 mHeightButton = utility::parseValue<int>(getUserString("HeightButton"));
39 if (mHeightButton < 0)
40 mHeightButton = 0;
41
43 assignWidget(mHeaderPlace, "HeaderPlace");
44
46 assignWidget(mWidgetEmpty, "Empty");
47
48 if (mWidgetEmpty == nullptr)
49 {
50 std::string_view skinButtonEmpty;
51 if (isUserString("SkinButtonEmpty"))
52 skinButtonEmpty = getUserString("SkinButtonEmpty");
53
54 if (!skinButtonEmpty.empty())
55 mWidgetEmpty = _getClientWidget()->createWidget<Widget>(
56 skinButtonEmpty,
57 IntCoord(0, 0, _getClientWidget()->getWidth(), getButtonHeight()),
58 Align::Default);
59 }
60
61 if (getUpdateByResize())
62 updateColumns();
63 }
64
65 void MultiListBox::shutdownOverride()
66 {
67 Base::shutdownOverride();
68 }
69
70 void MultiListBox::setColumnNameAt(size_t _column, const UString& _name)
71 {
72 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::setColumnNameAt");
73 mVectorColumnInfo[_column].name = _name;
74 // обновляем кэпшен сначала
75 redrawButtons();
76 updateColumns();
77 }
78
79 void MultiListBox::setColumnWidthAt(size_t _column, int _width)
80 {
81 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::setColumnWidthAt");
82 mVectorColumnInfo[_column].width = _width;
83 updateColumns();
84 }
85
86 const UString& MultiListBox::getColumnNameAt(size_t _column) const
87 {
88 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getColumnNameAt");
89 return mVectorColumnInfo[_column].name;
90 }
91
92 int MultiListBox::getColumnWidthAt(size_t _column) const
93 {
94 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getColumnWidthAt");
95 return mVectorColumnInfo[_column].width;
96 }
97
98 void MultiListBox::removeAllColumns()
99 {
100 while (!mVectorColumnInfo.empty())
101 removeColumnAt(0);
102 }
103
104 void MultiListBox::sortByColumn(size_t _column, bool _backward)
105 {
106 mSortColumnIndex = _column;
107 if (_backward)
108 {
109 mSortUp = !mSortUp;
110 redrawButtons();
111 // если было недосортированно то сортируем
112 if (mFrameAdvise)
113 sortList();
114
115 flipList();
116 }
117 else
118 {
119 mSortUp = true;
120 redrawButtons();
121 sortList();
122 }
123 }
124
125 size_t MultiListBox::getItemCount() const
126 {
127 if (mVectorColumnInfo.empty())
128 return 0;
129 return mVectorColumnInfo.front().list->getItemCount();
130 }
131
132 void MultiListBox::removeAllItems()
133 {
134 BiIndexBase::removeAllItems();
135 for (auto& iter : mVectorColumnInfo)
136 {
137 iter.list->removeAllItems();
138 }
139
140 mItemSelected = ITEM_NONE;
141 }
142
143 void MultiListBox::updateBackSelected(size_t _index)
144 {
145 if (_index == ITEM_NONE)
146 {
147 for (auto& iter : mVectorColumnInfo)
148 {
149 iter.list->clearIndexSelected();
150 }
151 }
152 else
153 {
154 for (auto& iter : mVectorColumnInfo)
155 {
156 iter.list->setIndexSelected(_index);
157 }
158 }
159 }
160
161 void MultiListBox::setIndexSelected(size_t _index)
162 {
163 if (_index == mItemSelected)
164 return;
165
166 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::setIndexSelected");
167 MYGUI_ASSERT_RANGE_AND_NONE(
168 _index,
169 mVectorColumnInfo.begin()->list->getItemCount(),
170 "MultiListBox::setIndexSelected");
171
172 mItemSelected = _index;
173 updateBackSelected(BiIndexBase::convertToBack(mItemSelected));
174 }
175
176 void MultiListBox::setSubItemNameAt(size_t _column, size_t _index, const UString& _name)
177 {
178 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::setSubItemAt");
179
180 size_t index = BiIndexBase::convertToBack(_index);
181 getSubItemAt(_column)->setItemNameAt(index, _name);
182
183 // если мы попортили список с активным сортом, надо пересчитывать
184 if (_column == mSortColumnIndex)
185 frameAdvise(true);
186 }
187
188 const UString& MultiListBox::getSubItemNameAt(size_t _column, size_t _index) const
189 {
190 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::getSubItemNameAt");
191
192 size_t index = BiIndexBase::convertToBack(_index);
193 return getSubItemAt(_column)->getItemNameAt(index);
194 }
195
196 size_t MultiListBox::findSubItemWith(size_t _column, const UString& _name)
197 {
198 size_t index = getSubItemAt(_column)->findItemIndexWith(_name);
199 return BiIndexBase::convertToFace(index);
200 }
201
202 int MultiListBox::getButtonHeight() const
203 {
204 if (mHeaderPlace != nullptr)
205 return mHeaderPlace->getHeight();
206 return mHeightButton;
207 }
208
209 void MultiListBox::updateOnlyEmpty()
210 {
211 if (nullptr == mWidgetEmpty)
212 return;
213
214 // кнопка, для заполнения пустоты
215 if (mWidthBar >= _getClientWidget()->getWidth())
216 mWidgetEmpty->setVisible(false);
217 else
218 {
219 mWidgetEmpty->setCoord(mWidthBar, 0, _getClientWidget()->getWidth() - mWidthBar, getButtonHeight());
220 mWidgetEmpty->setVisible(true);
221 }
222 }
223
224 void MultiListBox::notifyListChangePosition(ListBox* _sender, size_t _position)
225 {
226 for (auto& iter : mVectorColumnInfo)
227 {
228 if (_sender != iter.list)
229 iter.list->setIndexSelected(_position);
230 }
231
232 updateBackSelected(_position);
233
234 mItemSelected = BiIndexBase::convertToFace(_position);
235
236 // наш евент
237 eventListChangePosition(this, mItemSelected);
238 }
239
240 void MultiListBox::notifyListSelectAccept(ListBox* _sender, size_t _position)
241 {
242 // наш евент
243 eventListSelectAccept(this, BiIndexBase::convertToFace(_position));
244 }
245
246 void MultiListBox::notifyListNotifyItem(ListBox* _sender, const MyGUI::IBNotifyItemData& _info)
247 {
248 IBNotifyItemData infoConvertedIndex(_info);
249 infoConvertedIndex.index = BiIndexBase::convertToFace(_info.index);
250 eventNotifyItem(this, infoConvertedIndex);
251 }
252
253 void MultiListBox::notifyListChangeFocus(ListBox* _sender, size_t _position)
254 {
255 for (auto& iter : mVectorColumnInfo)
256 {
257 if (_sender != iter.list)
258 {
259 if (ITEM_NONE != mLastMouseFocusIndex)
260 iter.list->_setItemFocus(mLastMouseFocusIndex, false);
261 if (ITEM_NONE != _position)
262 iter.list->_setItemFocus(_position, true);
263 }
264 }
265 mLastMouseFocusIndex = _position;
266 }
267
268 void MultiListBox::notifyListChangeScrollPosition(ListBox* _sender, size_t _position)
269 {
270 for (auto& iter : mVectorColumnInfo)
271 {
272 if (_sender != iter.list)
273 iter.list->setScrollPosition(_position);
274 }
275 }
276
277 void MultiListBox::notifyButtonClick(MyGUI::Widget* _sender)
278 {
279 size_t index = *_sender->_getInternalData<size_t>();
280 sortByColumn(index, index == mSortColumnIndex);
281 }
282
283 void MultiListBox::redrawButtons()
284 {
285 size_t pos = 0;
286 for (auto& iter : mVectorColumnInfo)
287 {
288 if (pos == mSortColumnIndex)
289 {
290 if (mSortUp)
291 iter.button->setImageName("Up");
292 else
293 iter.button->setImageName("Down");
294 }
295 else
296 iter.button->setImageName("None");
297
298 iter.button->setCaption(iter.name);
299 pos++;
300 }
301 }
302
303 void MultiListBox::frameEntered(float _frame)
304 {
305 sortList();
306 }
307
308 void MultiListBox::frameAdvise(bool _advise)
309 {
310 if (_advise)
311 {
312 if (!mFrameAdvise)
313 {
314 MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate(this, &MultiListBox::frameEntered);
315 mFrameAdvise = true;
316 }
317 }
318 else
319 {
320 if (mFrameAdvise)
321 {
322 MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &MultiListBox::frameEntered);
323 mFrameAdvise = false;
324 }
325 }
326 }
327
328 Widget* MultiListBox::getOrCreateSeparator(size_t _index)
329 {
330 if (!mWidthSeparator || mSkinSeparator.empty())
331 return nullptr;
332 // последний столбик
333 if (_index == mVectorColumnInfo.size() - 1)
334 return nullptr;
335
336 while (_index >= mSeparators.size())
337 {
338 Widget* separator = _getClientWidget()->createWidget<Widget>(mSkinSeparator, IntCoord(), Align::Default);
339 mSeparators.push_back(separator);
340 }
341
342 return mSeparators[_index];
343 }
344
345 void MultiListBox::flipList()
346 {
347 if (ITEM_NONE == mSortColumnIndex)
348 return;
349
350 size_t last = mVectorColumnInfo.front().list->getItemCount();
351 if (0 == last)
352 return;
353 last--;
354 size_t first = 0;
355
356 while (first < last)
357 {
358 BiIndexBase::swapItemsBackAt(first, last);
359 for (auto& iter : mVectorColumnInfo)
360 {
361 iter.list->swapItemsAt(first, last);
362 }
363
364 first++;
365 last--;
366 }
367
368 updateBackSelected(BiIndexBase::convertToBack(mItemSelected));
369 }
370
371 bool MultiListBox::compare(ListBox* _list, size_t _left, size_t _right)
372 {
373 bool result = false;
374 if (mSortUp)
375 std::swap(_left, _right);
376 if (requestOperatorLess.empty())
377 {
378 result = _list->getItemNameAt(_left) < _list->getItemNameAt(_right);
379 }
380 else
381 {
382#ifndef MYGUI_DONT_USE_OBSOLETE
383 requestOperatorLess.m_eventObsolete(
384 this,
385 mSortColumnIndex,
386 _list->getItemNameAt(_left),
387 _list->getItemNameAt(_right),
388 result);
389 requestOperatorLess.m_event(
390 this,
391 mSortColumnIndex,
392 BiIndexBase::convertToFace(_left),
393 BiIndexBase::convertToFace(_right),
394 result);
395#else
396 requestOperatorLess(
397 this,
398 mSortColumnIndex,
399 BiIndexBase::convertToFace(_left),
400 BiIndexBase::convertToFace(_right),
401 result);
402#endif
403 }
404 return result;
405 }
406
407 void MultiListBox::sortList()
408 {
409 if (ITEM_NONE == mSortColumnIndex)
410 return;
411
412 ListBox* list = mVectorColumnInfo[mSortColumnIndex].list;
413
414 size_t count = list->getItemCount();
415 if (0 == count)
416 return;
417
418 // shell sort
419 int first;
420 size_t last;
421 for (size_t step = count >> 1; step > 0; step >>= 1)
422 {
423 for (size_t i = 0; i < (count - step); i++)
424 {
425 first = (int)i;
426 while (first >= 0)
427 {
428 last = first + step;
429 if (compare(list, first, last))
430 {
431 BiIndexBase::swapItemsBackAt(first, last);
432 for (auto& iter : mVectorColumnInfo)
433 {
434 iter.list->swapItemsAt(first, last);
435 }
436 }
437 first--;
438 }
439 }
440 }
441
442 frameAdvise(false);
443
444 updateBackSelected(BiIndexBase::convertToBack(mItemSelected));
445 }
446
447 void MultiListBox::insertItemAt(size_t _index, const UString& _name, Any _data)
448 {
449 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::insertItemAt");
450 MYGUI_ASSERT_RANGE_INSERT(_index, mVectorColumnInfo.front().list->getItemCount(), "MultiListBox::insertItemAt");
451 if (ITEM_NONE == _index)
452 _index = mVectorColumnInfo.front().list->getItemCount();
453
454 // если надо, то меняем выделенный элемент
455 // при сортировке, обновится
456 if ((mItemSelected != ITEM_NONE) && (_index <= mItemSelected))
457 mItemSelected++;
458
459 size_t index = BiIndexBase::insertItemAt(_index);
460
461 // вставляем во все поля пустые, а потом присваиваем первому
462 for (auto& iter : mVectorColumnInfo)
463 {
464 iter.list->insertItemAt(index, UString());
465 }
466 mVectorColumnInfo.front().list->setItemNameAt(index, _name);
467 mVectorColumnInfo.front().list->setItemDataAt(index, _data);
468
469 frameAdvise(true);
470 }
471
472 void MultiListBox::removeItemAt(size_t _index)
473 {
474 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::removeItemAt");
475 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::removeItemAt");
476
477 size_t index = BiIndexBase::removeItemAt(_index);
478
479 for (auto& iter : mVectorColumnInfo)
480 {
481 iter.list->removeItemAt(index);
482 }
483
484 // если надо, то меняем выделенный элемент
485 size_t count = mVectorColumnInfo.begin()->list->getItemCount();
486 if (count == 0)
487 mItemSelected = ITEM_NONE;
488 else if (mItemSelected != ITEM_NONE)
489 {
490 if (_index < mItemSelected)
491 mItemSelected--;
492 else if ((_index == mItemSelected) && (mItemSelected == count))
493 mItemSelected--;
494 }
495 updateBackSelected(BiIndexBase::convertToBack(mItemSelected));
496 }
497
498 void MultiListBox::swapItemsAt(size_t _index1, size_t _index2)
499 {
500 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::removeItemAt");
501 MYGUI_ASSERT_RANGE(_index1, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::swapItemsAt");
502 MYGUI_ASSERT_RANGE(_index2, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::swapItemsAt");
503
504 // при сортированном, меняем только индексы
505 BiIndexBase::swapItemsFaceAt(_index1, _index2);
506
507 // при несортированном, нужно наоборот, поменять только данные
508 // FIXME
509 }
510
511 void MultiListBox::setColumnDataAt(size_t _index, Any _data)
512 {
513 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::setColumnDataAt");
514 mVectorColumnInfo[_index].data = std::move(_data);
515 }
516
517 void MultiListBox::setSubItemDataAt(size_t _column, size_t _index, Any _data)
518 {
519 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::setSubItemDataAt");
520
521 size_t index = BiIndexBase::convertToBack(_index);
522 getSubItemAt(_column)->setItemDataAt(index, _data);
523 }
524
525 size_t MultiListBox::getColumnCount() const
526 {
527 return mVectorColumnInfo.size();
528 }
529
530 void MultiListBox::addColumn(const UString& _name, int _width, Any _data)
531 {
532 insertColumnAt(ITEM_NONE, _name, _width, _data);
533 }
534
535 void MultiListBox::clearColumnDataAt(size_t _index)
536 {
537 setColumnDataAt(_index, Any::Null);
538 }
539
540 void MultiListBox::addItem(const UString& _name, Any _data)
541 {
542 insertItemAt(ITEM_NONE, _name, _data);
543 }
544
545 void MultiListBox::setItemNameAt(size_t _index, const UString& _name)
546 {
547 setSubItemNameAt(0, _index, _name);
548 }
549
550 const UString& MultiListBox::getItemNameAt(size_t _index) const
551 {
552 return getSubItemNameAt(0, _index);
553 }
554
555 size_t MultiListBox::getIndexSelected() const
556 {
557 return mItemSelected;
558 }
559
560 void MultiListBox::clearIndexSelected()
561 {
562 setIndexSelected(ITEM_NONE);
563 }
564
565 void MultiListBox::setItemDataAt(size_t _index, Any _data)
566 {
567 setSubItemDataAt(0, _index, _data);
568 }
569
570 void MultiListBox::clearItemDataAt(size_t _index)
571 {
572 setItemDataAt(_index, Any::Null);
573 }
574
575 void MultiListBox::clearSubItemDataAt(size_t _column, size_t _index)
576 {
577 setSubItemDataAt(_column, _index, Any::Null);
578 }
579
580 ListBox* MultiListBox::getSubItemAt(size_t _column) const
581 {
582 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getSubItemAt");
583 return mVectorColumnInfo[_column].list;
584 }
585
586 size_t MultiListBox::_getItemCount() const
587 {
588 return getColumnCount();
589 }
590
591 void MultiListBox::_addItem(const MyGUI::UString& _name)
592 {
593 addColumn(_name);
594 setColumnResizingPolicyAt(getColumnCount() - 1, ResizingPolicy::Auto);
595 }
596
597 void MultiListBox::_removeItemAt(size_t _index)
598 {
599 removeColumnAt(_index);
600 }
601
602 void MultiListBox::_setItemNameAt(size_t _index, const UString& _name)
603 {
604 setColumnNameAt(_index, _name);
605 }
606
607 const UString& MultiListBox::_getItemNameAt(size_t _index) const
608 {
609 return getColumnNameAt(_index);
610 }
611
612 void MultiListBox::insertColumnAt(size_t _column, const UString& _name, int _width, Any _data)
613 {
614 MYGUI_ASSERT_RANGE_INSERT(_column, mVectorColumnInfo.size(), "MultiListBox::insertColumnAt");
615 if (_column == ITEM_NONE)
616 _column = mVectorColumnInfo.size();
617
618 createWidget<MultiListItem>(std::string_view{}, IntCoord(), Align::Default);
619
620 mVectorColumnInfo.back().width = _width;
621 mVectorColumnInfo.back().sizeType = ResizingPolicy::Fixed;
622 mVectorColumnInfo.back().name = _name;
623 mVectorColumnInfo.back().data = std::move(_data);
624 mVectorColumnInfo.back().button->setCaption(_name);
625
626 if (_column == (mVectorColumnInfo.size() - 1))
627 {
628 updateColumns();
629
630 mVectorColumnInfo.back().list->setScrollVisible(true);
631 }
632 else
633 {
634 _swapColumnsAt(_column, mVectorColumnInfo.size() - 1);
635 }
636 }
637
638 void MultiListBox::removeColumnAt(size_t _column)
639 {
640 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::removeColumnAt");
641
642 ColumnInfo& info = mVectorColumnInfo[_column];
643
644 WidgetManager::getInstance().destroyWidget(info.item);
645 }
646
647 void MultiListBox::swapColumnsAt(size_t _index1, size_t _index2)
648 {
649 MYGUI_ASSERT_RANGE(_index1, mVectorColumnInfo.size(), "MultiListBox::swapColumnsAt");
650 MYGUI_ASSERT_RANGE(_index2, mVectorColumnInfo.size(), "MultiListBox::swapColumnsAt");
651
652 _swapColumnsAt(_index1, _index2);
653 }
654
655 void MultiListBox::_swapColumnsAt(size_t _index1, size_t _index2)
656 {
657 if (_index1 == _index2)
658 return;
659
660 mVectorColumnInfo[_index1].list->setScrollVisible(false);
661 mVectorColumnInfo[_index2].list->setScrollVisible(false);
662
663 std::swap(mVectorColumnInfo[_index1], mVectorColumnInfo[_index2]);
664
665 updateColumns();
666
667 mVectorColumnInfo.back().list->setScrollVisible(true);
668 }
669
670 void MultiListBox::onWidgetCreated(Widget* _widget)
671 {
672 Base::onWidgetCreated(_widget);
673
674 MultiListItem* child = _widget->castType<MultiListItem>(false);
675 if (child != nullptr)
676 {
677 _wrapItem(child);
678 }
679 }
680
681 void MultiListBox::onWidgetDestroy(Widget* _widget)
682 {
683 Base::onWidgetDestroy(_widget);
684
685 MultiListItem* child = _widget->castType<MultiListItem>(false);
686 if (child != nullptr)
687 {
688 _unwrapItem(child);
689 }
690 else
691 {
692 for (auto& item : mVectorColumnInfo)
693 {
694 if (item.button == _widget)
695 item.button = nullptr;
696 }
697 }
698 }
699
700 void MultiListBox::_wrapItem(MultiListItem* _item)
701 {
702 // скрываем у крайнего скролл
703 if (!mVectorColumnInfo.empty())
704 mVectorColumnInfo.back().list->setScrollVisible(false);
705 else
706 mSortColumnIndex = ITEM_NONE;
707
708 ColumnInfo column;
709 column.width = 0;
710 column.realWidth = 0;
711 column.sizeType = ResizingPolicy::Auto;
712
713 column.item = _item;
714 column.list = _item->createWidget<ListBox>(
715 mSkinList,
716 IntCoord(0, 0, _item->getWidth(), _item->getHeight()),
717 Align::Stretch);
718 column.list->eventListChangePosition += newDelegate(this, &MultiListBox::notifyListChangePosition);
719 column.list->eventListMouseItemFocus += newDelegate(this, &MultiListBox::notifyListChangeFocus);
720 column.list->eventListChangeScroll += newDelegate(this, &MultiListBox::notifyListChangeScrollPosition);
721 column.list->eventListSelectAccept += newDelegate(this, &MultiListBox::notifyListSelectAccept);
722 column.list->eventNotifyItem += newDelegate(this, &MultiListBox::notifyListNotifyItem);
723
724 if (mHeaderPlace != nullptr)
725 column.button = mHeaderPlace->createWidget<Button>(mSkinButton, IntCoord(), Align::Default);
726 else
727 column.button = _getClientWidget()->createWidget<Button>(mSkinButton, IntCoord(), Align::Default);
728
729 column.button->eventMouseButtonClick += newDelegate(this, &MultiListBox::notifyButtonClick);
730
731 // если уже были столбики, то делаем то же колличество полей
732 if (!mVectorColumnInfo.empty())
733 {
734 size_t count = mVectorColumnInfo.front().list->getItemCount();
735 for (size_t pos = 0; pos < count; ++pos)
736 column.list->addItem(UString());
737 }
738
739 mVectorColumnInfo.push_back(column);
740
741 updateColumns();
742
743 // показываем скролл нового крайнего
744 mVectorColumnInfo.back().list->setScrollVisible(true);
745 }
746
747 void MultiListBox::_unwrapItem(MultiListItem* _item)
748 {
749 for (VectorColumnInfo::iterator item = mVectorColumnInfo.begin(); item != mVectorColumnInfo.end(); ++item)
750 {
751 if ((*item).item == _item)
752 {
753 if ((*item).button != nullptr)
754 WidgetManager::getInstance().destroyWidget((*item).button);
755
756 mVectorColumnInfo.erase(item);
757 break;
758 }
759 }
760
761 if (mVectorColumnInfo.empty())
762 {
763 mSortColumnIndex = ITEM_NONE;
764 mItemSelected = ITEM_NONE;
765 }
766 else
767 {
768 mSortColumnIndex = ITEM_NONE;
769 mSortUp = true;
770 sortList();
771 }
772
773 updateColumns();
774
775 if (!mVectorColumnInfo.empty())
776 mVectorColumnInfo.back().list->setScrollVisible(true);
777 }
778
779 Widget* MultiListBox::_getItemAt(size_t _index) const
780 {
781 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::_getItemAt");
782 return mVectorColumnInfo[_index].item;
783 }
784
785 void MultiListBox::setColumnName(MultiListItem* _item, const UString& _name)
786 {
787 setColumnNameAt(getColumnIndex(_item), _name);
788 }
789
790 const UString& MultiListBox::getColumnName(const MultiListItem* _item) const
791 {
792 return getColumnNameAt(getColumnIndex(_item));
793 }
794
795 size_t MultiListBox::getColumnIndex(const MultiListItem* _item) const
796 {
797 for (size_t index = 0; index < mVectorColumnInfo.size(); ++index)
798 {
799 if (mVectorColumnInfo[index].item == _item)
800 return index;
801 }
802
803 return ITEM_NONE;
804 }
805
806 void MultiListBox::setColumnResizingPolicy(MultiListItem* _item, ResizingPolicy _value)
807 {
808 setColumnResizingPolicyAt(getColumnIndex(_item), _value);
809 }
810
811 void MultiListBox::setColumnResizingPolicyAt(size_t _index, ResizingPolicy _value)
812 {
813 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::setColumnWidthAt");
814 mVectorColumnInfo[_index].sizeType = _value;
815 updateColumns();
816 }
817
818 void MultiListBox::setColumnWidth(MultiListItem* _item, int _width)
819 {
820 setColumnWidthAt(getColumnIndex(_item), _width);
821 }
822
823 void MultiListBox::setPosition(const IntPoint& _point)
824 {
825 Base::setPosition(_point);
826 }
827
828 void MultiListBox::setSize(const IntSize& _size)
829 {
830 Base::setSize(_size);
831
832 if (getUpdateByResize())
833 updateColumns();
834 }
835
836 void MultiListBox::setCoord(const IntCoord& _coord)
837 {
838 Base::setCoord(_coord);
839
840 if (getUpdateByResize())
841 updateColumns();
842 }
843
844 bool MultiListBox::getUpdateByResize() const
845 {
846 if (mWidgetEmpty != nullptr)
847 return true;
848
849 for (const auto& info : mVectorColumnInfo)
850 {
851 if (info.sizeType == ResizingPolicy::Fill)
852 return true;
853 }
854 return false;
855 }
856
857 int MultiListBox::getColumnWidth(
858 size_t _index,
859 int _freeSpace,
860 size_t _countStars,
861 size_t _lastIndexStar,
862 int _starWidth) const
863 {
864 const ColumnInfo& info = mVectorColumnInfo[_index];
865
866 if (info.sizeType == ResizingPolicy::Auto)
867 {
868 return info.realWidth;
869 }
870 if (info.sizeType == ResizingPolicy::Fixed)
871 {
872 return info.realWidth;
873 }
874 if (info.sizeType == ResizingPolicy::Fill)
875 {
876 if (_lastIndexStar == _index)
877 {
878 return _starWidth + _freeSpace - (_starWidth * _countStars);
879 }
880 return _starWidth;
881 }
882 return 0;
883 }
884
885 int MultiListBox::updateWidthColumns(size_t& _countStars, size_t& _lastIndexStar)
886 {
887 _countStars = 0;
888 _lastIndexStar = ITEM_NONE;
889
890 int width = 0;
891
892 for (size_t index = 0; index < mVectorColumnInfo.size(); ++index)
893 {
894 ColumnInfo& info = mVectorColumnInfo[index];
895
896 if (info.sizeType == ResizingPolicy::Auto)
897 {
898 info.realWidth =
899 info.button->getWidth() - info.button->getTextRegion().width + info.button->getTextSize().width;
900 }
901 else if (info.sizeType == ResizingPolicy::Fixed)
902 {
903 info.realWidth = info.width < 0 ? 0 : info.width;
904 }
905 else if (info.sizeType == ResizingPolicy::Fill)
906 {
907 info.realWidth = 0;
908 _countStars++;
909 _lastIndexStar = index;
910 }
911 else
912 {
913 info.realWidth = 0;
914 }
915
916 width += info.realWidth;
917 }
918
919 return width;
920 }
921
922 void MultiListBox::updateColumns()
923 {
924 size_t countStars = 0;
925 size_t lastIndexStar = ITEM_NONE;
926
927 int allColumnsWidth = updateWidthColumns(countStars, lastIndexStar);
928 int clientWidth = _getClientWidget()->getWidth();
929 int separatorsWidth = mVectorColumnInfo.empty() ? 0 : (mVectorColumnInfo.size() - 1) * mWidthSeparator;
930 int freeSpace = clientWidth - separatorsWidth - allColumnsWidth;
931 int starWidth = (countStars != 0 && freeSpace > 0) ? (freeSpace / countStars) : 0;
932
933 mWidthBar = 0;
934 for (size_t index = 0; index < mVectorColumnInfo.size(); ++index)
935 {
936 ColumnInfo& info = mVectorColumnInfo[index];
937
938 int columnWidth = getColumnWidth(index, freeSpace, countStars, lastIndexStar, starWidth);
939
940 if (mHeaderPlace != nullptr)
941 {
942 info.item->setCoord(mWidthBar, 0, columnWidth, _getClientWidget()->getHeight());
943 }
944 else
945 {
946 info.item
947 ->setCoord(mWidthBar, mHeightButton, columnWidth, _getClientWidget()->getHeight() - mHeightButton);
948 }
949
950 info.button->setCoord(mWidthBar, 0, columnWidth, getButtonHeight());
951 info.button->_setInternalData(index);
952
953 mWidthBar += columnWidth;
954
955 // промежуток между листами
956 Widget* separator = getOrCreateSeparator(index);
957 if (separator)
958 {
959 separator->setCoord(mWidthBar, 0, mWidthSeparator, _getClientWidget()->getHeight());
960 }
961
962 mWidthBar += mWidthSeparator;
963 }
964
965 redrawButtons();
966 updateOnlyEmpty();
967 }
968
969} // namespace MyGUI
MyGUI_Button.h
MYGUI_ASSERT
#define MYGUI_ASSERT(exp, dest)
Definition MyGUI_Diagnostic.h:31
MYGUI_ASSERT_RANGE_INSERT
#define MYGUI_ASSERT_RANGE_INSERT(index, size, owner)
Definition MyGUI_Diagnostic.h:50
MYGUI_ASSERT_RANGE
#define MYGUI_ASSERT_RANGE(index, size, owner)
Definition MyGUI_Diagnostic.h:44
MYGUI_ASSERT_RANGE_AND_NONE
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
Definition MyGUI_Diagnostic.h:46
MyGUI_Gui.h
MyGUI_ImageBox.h
MyGUI_ListBox.h
MyGUI_MultiListBox.h
MyGUI_MultiListItem.h
MyGUI_Precompiled.h
MyGUI_ResourceSkin.h
MyGUI_WidgetManager.h
MyGUI::Any
Definition MyGUI_Any.h:56
MyGUI::Any::Null
static const Any Null
Definition MyGUI_Any.h:58
MyGUI::BiIndexBase::removeAllItems
void removeAllItems()
Definition MyGUI_BiIndexBase.cpp:94
MyGUI::BiIndexBase::swapItemsBackAt
void swapItemsBackAt(size_t _index1, size_t _index2)
Definition MyGUI_BiIndexBase.cpp:131
MyGUI::BiIndexBase::removeItemAt
size_t removeItemAt(size_t _index)
Definition MyGUI_BiIndexBase.cpp:66
MyGUI::BiIndexBase::insertItemAt
size_t insertItemAt(size_t _index)
Definition MyGUI_BiIndexBase.cpp:18
MyGUI::BiIndexBase::convertToBack
size_t convertToBack(size_t _index) const
Definition MyGUI_BiIndexBase.cpp:101
MyGUI::BiIndexBase::convertToFace
size_t convertToFace(size_t _index) const
Definition MyGUI_BiIndexBase.cpp:110
MyGUI::BiIndexBase::swapItemsFaceAt
void swapItemsFaceAt(size_t _index1, size_t _index2)
Definition MyGUI_BiIndexBase.cpp:119
MyGUI::Button
widget description should be here.
Definition MyGUI_Button.h:20
MyGUI::Gui::getInstance
static Gui & getInstance()
Definition MyGUI_Gui.cpp:34
MyGUI::Gui::eventFrameStart
EventHandle_FrameEventDelegate eventFrameStart
Definition MyGUI_Gui.h:215
MyGUI::ICroppedRectangle::getWidth
int getWidth() const
Definition MyGUI_ICroppedRectangle.h:113
MyGUI::ICroppedRectangle::getHeight
int getHeight() const
Definition MyGUI_ICroppedRectangle.h:118
MyGUI::IObject::castType
Type * castType(bool _throw=true)
Definition MyGUI_IObject.h:18
MyGUI::ListBox
widget description should be here.
Definition MyGUI_ListBox.h:28
MyGUI::ListBox::eventListChangePosition
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListChangePosition
Definition MyGUI_ListBox.h:198
MyGUI::MultiListBox::_getItemCount
size_t _getItemCount() const override
Definition MyGUI_MultiListBox.cpp:586
MyGUI::MultiListBox::removeAllItems
void removeAllItems()
Definition MyGUI_MultiListBox.cpp:132
MyGUI::MultiListBox::setColumnWidthAt
void setColumnWidthAt(size_t _column, int _width)
Definition MyGUI_MultiListBox.cpp:79
MyGUI::MultiListBox::addItem
void addItem(const UString &_name, Any _data=Any::Null)
Definition MyGUI_MultiListBox.cpp:540
MyGUI::MultiListBox::onWidgetDestroy
void onWidgetDestroy(Widget *_widget) override
Definition MyGUI_MultiListBox.cpp:681
MyGUI::MultiListBox::_removeItemAt
void _removeItemAt(size_t _index) override
Definition MyGUI_MultiListBox.cpp:597
MyGUI::MultiListBox::insertItemAt
void insertItemAt(size_t _index, const UString &_name, Any _data=Any::Null)
Definition MyGUI_MultiListBox.cpp:447
MyGUI::MultiListBox::setColumnResizingPolicyAt
void setColumnResizingPolicyAt(size_t _index, ResizingPolicy _value)
Definition MyGUI_MultiListBox.cpp:811
MyGUI::MultiListBox::setColumnWidth
void setColumnWidth(MultiListItem *_item, int _width)
Definition MyGUI_MultiListBox.cpp:818
MyGUI::MultiListBox::_setItemNameAt
void _setItemNameAt(size_t _index, const UString &_name) override
Definition MyGUI_MultiListBox.cpp:602
MyGUI::MultiListBox::removeItemAt
void removeItemAt(size_t _index)
Remove item at a specified position.
Definition MyGUI_MultiListBox.cpp:472
MyGUI::MultiListBox::setCoord
void setCoord(const IntCoord &_coord) override
Definition MyGUI_MultiListBox.cpp:836
MyGUI::MultiListBox::requestOperatorLess
EventPair< EventHandle_MultiListPtrSizeTCUTFStringRefCUTFStringRefBoolRef, EventHandle_MultiListPtrSizeTSizeTSizeTBoolRef > requestOperatorLess
Definition MyGUI_MultiListBox.h:295
MyGUI::MultiListBox::getItemNameAt
const UString & getItemNameAt(size_t _index) const
Get item name from specified position.
Definition MyGUI_MultiListBox.cpp:550
MyGUI::MultiListBox::setColumnDataAt
void setColumnDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
Definition MyGUI_MultiListBox.cpp:511
MyGUI::MultiListBox::eventListChangePosition
EventPair< EventHandle_WidgetSizeT, EventHandle_MultiListPtrSizeT > eventListChangePosition
Definition MyGUI_MultiListBox.h:282
MyGUI::MultiListBox::sortByColumn
void sortByColumn(size_t _column, bool _backward=false)
Definition MyGUI_MultiListBox.cpp:104
MyGUI::MultiListBox::_getItemNameAt
const UString & _getItemNameAt(size_t _index) const override
Definition MyGUI_MultiListBox.cpp:607
MyGUI::MultiListBox::insertColumnAt
void insertColumnAt(size_t _column, const UString &_name, int _width=0, Any _data=Any::Null)
Definition MyGUI_MultiListBox.cpp:612
MyGUI::MultiListBox::setItemNameAt
void setItemNameAt(size_t _index, const UString &_name)
Replace an item name.
Definition MyGUI_MultiListBox.cpp:545
MyGUI::MultiListBox::getColumnWidthAt
int getColumnWidthAt(size_t _column) const
Definition MyGUI_MultiListBox.cpp:92
MyGUI::MultiListBox::setSize
void setSize(const IntSize &_size) override
Definition MyGUI_MultiListBox.cpp:828
MyGUI::MultiListBox::eventListSelectAccept
EventPair< EventHandle_WidgetSizeT, EventHandle_MultiListPtrSizeT > eventListSelectAccept
Definition MyGUI_MultiListBox.h:275
MyGUI::MultiListBox::getColumnCount
size_t getColumnCount() const
Get number of columns.
Definition MyGUI_MultiListBox.cpp:525
MyGUI::MultiListBox::setSubItemDataAt
void setSubItemDataAt(size_t _column, size_t _index, Any _data)
Replace an item data at a specified position.
Definition MyGUI_MultiListBox.cpp:517
MyGUI::MultiListBox::swapItemsAt
void swapItemsAt(size_t _index1, size_t _index2)
Swap items at a specified positions.
Definition MyGUI_MultiListBox.cpp:498
MyGUI::MultiListBox::setSubItemNameAt
void setSubItemNameAt(size_t _column, size_t _index, const UString &_name)
Definition MyGUI_MultiListBox.cpp:176
MyGUI::MultiListBox::onWidgetCreated
void onWidgetCreated(Widget *_widget) override
Definition MyGUI_MultiListBox.cpp:670
MyGUI::MultiListBox::removeColumnAt
void removeColumnAt(size_t _column)
Definition MyGUI_MultiListBox.cpp:638
MyGUI::MultiListBox::_getItemAt
Widget * _getItemAt(size_t _index) const override
Definition MyGUI_MultiListBox.cpp:779
MyGUI::MultiListBox::setPosition
void setPosition(const IntPoint &_point) override
Definition MyGUI_MultiListBox.cpp:823
MyGUI::MultiListBox::clearItemDataAt
void clearItemDataAt(size_t _index)
Clear an item data at a specified position.
Definition MyGUI_MultiListBox.cpp:570
MyGUI::MultiListBox::findSubItemWith
size_t findSubItemWith(size_t _column, const UString &_name)
Definition MyGUI_MultiListBox.cpp:196
MyGUI::MultiListBox::_addItem
void _addItem(const MyGUI::UString &_name) override
Definition MyGUI_MultiListBox.cpp:591
MyGUI::MultiListBox::clearColumnDataAt
void clearColumnDataAt(size_t _index)
Clear an item data at a specified position.
Definition MyGUI_MultiListBox.cpp:535
MyGUI::MultiListBox::setItemDataAt
void setItemDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
Definition MyGUI_MultiListBox.cpp:565
MyGUI::MultiListBox::shutdownOverride
void shutdownOverride() override
Definition MyGUI_MultiListBox.cpp:65
MyGUI::MultiListBox::eventNotifyItem
EventHandle_MultiListPtrCIBNotifyCellDataRef eventNotifyItem
Definition MyGUI_MultiListBox.h:302
MyGUI::MultiListBox::initialiseOverride
void initialiseOverride() override
Definition MyGUI_MultiListBox.cpp:20
MyGUI::MultiListBox::getColumnIndex
size_t getColumnIndex(const MultiListItem *_item) const
Get column index.
Definition MyGUI_MultiListBox.cpp:795
MyGUI::MultiListBox::setColumnNameAt
void setColumnNameAt(size_t _column, const UString &_name)
Definition MyGUI_MultiListBox.cpp:70
MyGUI::MultiListBox::addColumn
void addColumn(const UString &_name, int _width=0, Any _data=Any::Null)
Definition MyGUI_MultiListBox.cpp:530
MyGUI::MultiListBox::getSubItemNameAt
const UString & getSubItemNameAt(size_t _column, size_t _index) const
Definition MyGUI_MultiListBox.cpp:188
MyGUI::MultiListBox::getIndexSelected
size_t getIndexSelected() const
Definition MyGUI_MultiListBox.cpp:555
MyGUI::MultiListBox::setColumnName
void setColumnName(MultiListItem *_item, const UString &_name)
Definition MyGUI_MultiListBox.cpp:785
MyGUI::MultiListBox::setColumnResizingPolicy
void setColumnResizingPolicy(MultiListItem *_item, ResizingPolicy _value)
Definition MyGUI_MultiListBox.cpp:806
MyGUI::MultiListBox::clearSubItemDataAt
void clearSubItemDataAt(size_t _column, size_t _index)
Clear an item data at a specified position.
Definition MyGUI_MultiListBox.cpp:575
MyGUI::MultiListBox::clearIndexSelected
void clearIndexSelected()
Definition MyGUI_MultiListBox.cpp:560
MyGUI::MultiListBox::setIndexSelected
void setIndexSelected(size_t _index)
Definition MyGUI_MultiListBox.cpp:161
MyGUI::MultiListBox::getItemCount
size_t getItemCount() const
Definition MyGUI_MultiListBox.cpp:125
MyGUI::MultiListBox::getColumnNameAt
const UString & getColumnNameAt(size_t _column) const
Definition MyGUI_MultiListBox.cpp:86
MyGUI::MultiListBox::removeAllColumns
void removeAllColumns()
Definition MyGUI_MultiListBox.cpp:98
MyGUI::MultiListBox::swapColumnsAt
void swapColumnsAt(size_t _index1, size_t _index2)
Swap columns at a specified positions.
Definition MyGUI_MultiListBox.cpp:647
MyGUI::MultiListBox::getColumnName
const UString & getColumnName(const MultiListItem *_item) const
Definition MyGUI_MultiListBox.cpp:790
MyGUI::MultiListItem
widget description should be here.
Definition MyGUI_MultiListItem.h:22
MyGUI::UString
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
Definition MyGUI_UString.h:144
MyGUI::UString::data
const code_point * data() const
returns a pointer to the first character in the current string
Definition MyGUI_UString.cpp:609
MyGUI::UserData::isUserString
bool isUserString(std::string_view _key) const
Definition MyGUI_WidgetUserData.cpp:44
MyGUI::UserData::getUserString
std::string_view getUserString(std::string_view _key) const
Definition MyGUI_WidgetUserData.cpp:20
MyGUI::UserData::_getInternalData
ValueType * _getInternalData(bool _throw=true) const
Definition MyGUI_WidgetUserData.h:54
MyGUI::Widget
widget description should be here.
Definition MyGUI_Widget.h:40
MyGUI::Widget::setVisible
virtual void setVisible(bool _value)
Definition MyGUI_Widget.cpp:1022
MyGUI::Widget::assignWidget
void assignWidget(T *&_widget, std::string_view _name)
Definition MyGUI_Widget.h:413
MyGUI::Widget::createWidget
T * createWidget(std::string_view _skin, const IntCoord &_coord, Align _align, std::string_view _name={})
Definition MyGUI_Widget.h:94
MyGUI::Widget::setCoord
void setCoord(const IntCoord &_coord) override
Definition MyGUI_Widget.cpp:730
MyGUI::Widget::_getClientWidget
Widget * _getClientWidget()
If there is client widget return it, otherwise return this.
Definition MyGUI_Widget.cpp:1196
MyGUI::WidgetInput::eventMouseButtonClick
EventHandle_WidgetVoid eventMouseButtonClick
Definition MyGUI_WidgetInput.h:168
MyGUI::WidgetManager::getInstance
static WidgetManager & getInstance()
MyGUI::WidgetManager::destroyWidget
void destroyWidget(Widget *_widget)
Definition MyGUI_WidgetManager.cpp:123
MyGUI::utility::parseValue
T parseValue(std::string_view _value)
Definition MyGUI_StringUtility.h:60
MyGUI
Definition MyGUI_ActionController.h:15
MyGUI::IntPoint
types::TPoint< int > IntPoint
Definition MyGUI_Types.h:27
MyGUI::ITEM_NONE
constexpr size_t ITEM_NONE
Definition MyGUI_Macros.h:19
MyGUI::IntCoord
types::TCoord< int > IntCoord
Definition MyGUI_Types.h:36
MyGUI::IntSize
types::TSize< int > IntSize
Definition MyGUI_Types.h:30
MyGUI::newDelegate
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
Definition MyGUI_Delegate.h:100
MyGUI::Align::Default
@ Default
Definition MyGUI_Align.h:36
MyGUI::Align::Stretch
@ Stretch
Definition MyGUI_Align.h:35
MyGUI::IBNotifyItemData::index
size_t index
Definition MyGUI_IBItemInfo.h:111
MyGUI::ResizingPolicy
Definition MyGUI_ResizingPolicy.h:16
MyGUI::ResizingPolicy::Auto
@ Auto
Definition MyGUI_ResizingPolicy.h:19
MyGUI::ResizingPolicy::Fixed
@ Fixed
Definition MyGUI_ResizingPolicy.h:20
MyGUI::ResizingPolicy::Fill
@ Fill
Definition MyGUI_ResizingPolicy.h:21