MyGUI: MyGUI_MultiListBox.cpp Source File

MyGUI 3.2.2

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