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