MyGUI  3.4.0
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 
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)
99  {
100  MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getColumnNameAt");
101  return mVectorColumnInfo[_column].name;
102  }
103 
104  int MultiListBox::getColumnWidthAt(size_t _column)
105  {
106  MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getColumnWidthAt");
107  return mVectorColumnInfo[_column].width;
108  }
109 
111  {
112  while (!mVectorColumnInfo.empty())
113  removeColumnAt(0);
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 
173  void MultiListBox::setIndexSelected(size_t _index)
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)
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::getSeparator(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)
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 
560  void MultiListBox::clearItemDataAt(size_t _index)
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)
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)
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.sizeType = ResizingPolicy::Auto;
701 
702  column.item = _item;
703  column.list = _item->createWidget<ListBox>(mSkinList, IntCoord(0, 0, _item->getWidth(), _item->getHeight()), Align::Stretch);
704  column.list->eventListChangePosition += newDelegate(this, &MultiListBox::notifyListChangePosition);
705  column.list->eventListMouseItemFocus += newDelegate(this, &MultiListBox::notifyListChangeFocus);
706  column.list->eventListChangeScroll += newDelegate(this, &MultiListBox::notifyListChangeScrollPosition);
707  column.list->eventListSelectAccept += newDelegate(this, &MultiListBox::notifyListSelectAccept);
708  column.list->eventNotifyItem += newDelegate(this, &MultiListBox::notifyListNotifyItem);
709 
710  if (mHeaderPlace != nullptr)
711  column.button = mHeaderPlace->createWidget<Button>(mSkinButton, IntCoord(), Align::Default);
712  else
713  column.button = _getClientWidget()->createWidget<Button>(mSkinButton, IntCoord(), Align::Default);
714 
715  column.button->eventMouseButtonClick += newDelegate(this, &MultiListBox::notifyButtonClick);
716 
717  // если уже были столбики, то делаем то же колличество полей
718  if (!mVectorColumnInfo.empty())
719  {
720  size_t count = mVectorColumnInfo.front().list->getItemCount();
721  for (size_t pos = 0; pos < count; ++pos)
722  column.list->addItem("");
723  }
724 
725  mVectorColumnInfo.push_back(column);
726 
727  updateColumns();
728 
729  // показываем скролл нового крайнего
730  mVectorColumnInfo.back().list->setScrollVisible(true);
731  }
732 
733  void MultiListBox::_unwrapItem(MultiListItem* _item)
734  {
735  for (VectorColumnInfo::iterator item = mVectorColumnInfo.begin(); item != mVectorColumnInfo.end(); ++item)
736  {
737  if ((*item).item == _item)
738  {
739  if ((*item).button != nullptr)
740  WidgetManager::getInstance().destroyWidget((*item).button);
741 
742  mVectorColumnInfo.erase(item);
743  break;
744  }
745  }
746 
747  if (mVectorColumnInfo.empty())
748  {
749  mSortColumnIndex = ITEM_NONE;
750  mItemSelected = ITEM_NONE;
751  }
752  else
753  {
754  mSortColumnIndex = ITEM_NONE;
755  mSortUp = true;
756  sortList();
757  }
758 
759  updateColumns();
760 
761  if (!mVectorColumnInfo.empty())
762  mVectorColumnInfo.back().list->setScrollVisible(true);
763  }
764 
766  {
767  MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::_getItemAt");
768  return mVectorColumnInfo[_index].item;
769  }
770 
772  {
773  setColumnNameAt(getColumnIndex(_item), _name);
774  }
775 
777  {
778  return getColumnNameAt(getColumnIndex(_item));
779  }
780 
782  {
783  for (size_t index = 0; index < mVectorColumnInfo.size(); ++ index)
784  {
785  if (mVectorColumnInfo[index].item == _item)
786  return index;
787  }
788 
789  return ITEM_NONE;
790  }
791 
793  {
795  }
796 
798  {
799  MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::setColumnWidthAt");
800  mVectorColumnInfo[_index].sizeType = _value;
801  updateColumns();
802  }
803 
805  {
806  setColumnWidthAt(getColumnIndex(_item), _width);
807  }
808 
810  {
811  Base::setPosition(_point);
812  }
813 
814  void MultiListBox::setSize(const IntSize& _size)
815  {
816  Base::setSize(_size);
817 
818  if (getUpdateByResize())
819  updateColumns();
820  }
821 
822  void MultiListBox::setCoord(const IntCoord& _coord)
823  {
824  Base::setCoord(_coord);
825 
826  if (getUpdateByResize())
827  updateColumns();
828  }
829 
830  bool MultiListBox::getUpdateByResize()
831  {
832  if (mWidgetEmpty != nullptr)
833  return true;
834 
835  for (VectorColumnInfo::iterator item = mVectorColumnInfo.begin(); item != mVectorColumnInfo.end(); ++item)
836  {
837  if ((*item).sizeType == ResizingPolicy::Fill)
838  return true;
839  }
840  return false;
841  }
842 
843  int MultiListBox::getColumnWidth(size_t _index, int _freeSpace, size_t _countStars, size_t _lastIndexStar, int _starWidth) const
844  {
845  const ColumnInfo& info = mVectorColumnInfo[_index];
846 
847  if (info.sizeType == ResizingPolicy::Auto)
848  {
849  return info.realWidth;
850  }
851  else if (info.sizeType == ResizingPolicy::Fixed)
852  {
853  return info.realWidth;
854  }
855  else if (info.sizeType == ResizingPolicy::Fill)
856  {
857  if (_lastIndexStar == _index)
858  {
859  return _starWidth + _freeSpace - (_starWidth * _countStars);
860  }
861  else
862  {
863  return _starWidth;
864  }
865  }
866  return 0;
867  }
868 
869  int MultiListBox::updateWidthColumns(size_t& _countStars, size_t& _lastIndexStar)
870  {
871  _countStars = 0;
872  _lastIndexStar = ITEM_NONE;
873 
874  int width = 0;
875 
876  for (size_t index = 0; index < mVectorColumnInfo.size(); ++ index)
877  {
878  ColumnInfo& info = mVectorColumnInfo[index];
879 
880  if (info.sizeType == ResizingPolicy::Auto)
881  {
882  info.realWidth = info.button->getWidth() - info.button->getTextRegion().width + info.button->getTextSize().width;
883  }
884  else if (info.sizeType == ResizingPolicy::Fixed)
885  {
886  info.realWidth = info.width < 0 ? 0 : info.width;
887  }
888  else if (info.sizeType == ResizingPolicy::Fill)
889  {
890  info.realWidth = 0;
891  _countStars ++;
892  _lastIndexStar = index;
893  }
894  else
895  {
896  info.realWidth = 0;
897  }
898 
899  width += info.realWidth;
900  }
901 
902  return width;
903  }
904 
905  void MultiListBox::updateColumns()
906  {
907  size_t countStars = 0;
908  size_t lastIndexStar = ITEM_NONE;
909 
910  int allColumnsWidth = updateWidthColumns(countStars, lastIndexStar);
911  int clientWidth = _getClientWidget()->getWidth();
912  int separatorsWidth = mVectorColumnInfo.empty() ? 0 : (mVectorColumnInfo.size() - 1) * mWidthSeparator;
913  int freeSpace = clientWidth - separatorsWidth - allColumnsWidth;
914  int starWidth = (countStars != 0 && freeSpace > 0) ? (freeSpace / countStars) : 0;
915 
916  mWidthBar = 0;
917  for (size_t index = 0; index < mVectorColumnInfo.size(); ++ index)
918  {
919  ColumnInfo& info = mVectorColumnInfo[index];
920 
921  int columnWidth = getColumnWidth(index, freeSpace, countStars, lastIndexStar, starWidth);
922 
923  if (mHeaderPlace != nullptr)
924  {
925  info.item->setCoord(mWidthBar, 0, columnWidth, _getClientWidget()->getHeight());
926  }
927  else
928  {
929  info.item->setCoord(mWidthBar, mHeightButton, columnWidth, _getClientWidget()->getHeight() - mHeightButton);
930  }
931 
932  info.button->setCoord(mWidthBar, 0, columnWidth, getButtonHeight());
933  info.button->_setInternalData(index);
934 
935  mWidthBar += columnWidth;
936 
937  // промежуток между листами
938  Widget* separator = getSeparator(index);
939  if (separator)
940  {
941  separator->setCoord(mWidthBar, 0, mWidthSeparator, _getClientWidget()->getHeight());
942  }
943 
944  mWidthBar += mWidthSeparator;
945  }
946 
947  redrawButtons();
948  updateOnlyEmpty();
949  }
950 
951 } // namespace MyGUI
MyGUI::Singleton< Gui >::getInstance
static Gui & getInstance()
Definition: MyGUI_Singleton.h:44
MyGUI::MultiListBox::shutdownOverride
void shutdownOverride() override
Definition: MyGUI_MultiListBox.cpp:77
MyGUI::MultiListBox::requestOperatorLess
EventPair< EventHandle_MultiListPtrSizeTCUTFStringRefCUTFStringRefBoolRef, EventHandle_MultiListPtrSizeTSizeTSizeTBoolRef > requestOperatorLess
Definition: MyGUI_MultiListBox.h:287
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:23
MyGUI::Widget::createWidget
T * createWidget(const std::string &_skin, const IntCoord &_coord, Align _align, const std::string &_name="")
Definition: MyGUI_Widget.h:67
MyGUI::MultiListBox::_setItemNameAt
void _setItemNameAt(size_t _index, const UString &_name) override
Definition: MyGUI_MultiListBox.cpp:592
MyGUI::ListBox
ListBox properties. Skin childs. ListBox widget description should be here.
Definition: MyGUI_ListBox.h:31
MyGUI::MultiListBox::eventListChangePosition
EventPair< EventHandle_WidgetSizeT, EventHandle_MultiListPtrSizeT > eventListChangePosition
Definition: MyGUI_MultiListBox.h:277
MyGUI::MultiListBox::_removeItemAt
void _removeItemAt(size_t _index) override
Definition: MyGUI_MultiListBox.cpp:587
MyGUI_Gui.h
MyGUI::MultiListBox::insertItemAt
void insertItemAt(size_t _index, const UString &_name, Any _data=Any::Null)
Definition: MyGUI_MultiListBox.cpp:437
MyGUI::MultiListBox::setColumnWidth
void setColumnWidth(MultiListItem *_item, int _width)
Definition: MyGUI_MultiListBox.cpp:804
MyGUI::MultiListBox::setColumnNameAt
void setColumnNameAt(size_t _column, const UString &_name)
Definition: MyGUI_MultiListBox.cpp:82
MyGUI::MultiListBox::getIndexSelected
size_t getIndexSelected() const
Definition: MyGUI_MultiListBox.cpp:545
MyGUI::MultiListBox::clearSubItemDataAt
void clearSubItemDataAt(size_t _column, size_t _index)
Clear an item data at a specified position.
Definition: MyGUI_MultiListBox.cpp:565
MyGUI::MultiListBox::setColumnDataAt
void setColumnDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
Definition: MyGUI_MultiListBox.cpp:501
MyGUI_MultiListBox.h
MyGUI::MultiListBox::setSubItemNameAt
void setSubItemNameAt(size_t _column, size_t _index, const UString &_name)
Definition: MyGUI_MultiListBox.cpp:185
MyGUI::MultiListBox::setColumnWidthAt
void setColumnWidthAt(size_t _column, int _width)
Definition: MyGUI_MultiListBox.cpp:91
MyGUI::MultiListBox::addItem
void addItem(const UString &_name, Any _data=Any::Null)
Definition: MyGUI_MultiListBox.cpp:530
MyGUI::Widget::Widget
Widget()
Definition: MyGUI_Widget.cpp:31
MyGUI_ListBox.h
MyGUI::MultiListBox::removeAllColumns
void removeAllColumns()
Definition: MyGUI_MultiListBox.cpp:110
MYGUI_ASSERT_RANGE
#define MYGUI_ASSERT_RANGE(index, size, owner)
Definition: MyGUI_Diagnostic.h:45
MyGUI::MultiListBox::clearItemDataAt
void clearItemDataAt(size_t _index)
Clear an item data at a specified position.
Definition: MyGUI_MultiListBox.cpp:560
MyGUI::BiIndexBase::swapItemsFaceAt
void swapItemsFaceAt(size_t _index1, size_t _index2)
Definition: MyGUI_BiIndexBase.cpp:119
MyGUI::MultiListBox::clearIndexSelected
void clearIndexSelected()
Definition: MyGUI_MultiListBox.cpp:550
MyGUI::Align::Stretch
@ Stretch
Definition: MyGUI_Align.h:35
MYGUI_ASSERT_RANGE_AND_NONE
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
Definition: MyGUI_Diagnostic.h:46
MyGUI::ResizingPolicy::Fixed
@ Fixed
Definition: MyGUI_ResizingPolicy.h:20
MyGUI::IntCoord
types::TCoord< int > IntCoord
Definition: MyGUI_Types.h:35
MyGUI::IBNotifyItemData::index
size_t index
Definition: MyGUI_IBItemInfo.h:105
MyGUI::Widget
Widget properties. Skin childs. Widget widget description should be here.
Definition: MyGUI_Widget.h:37
MyGUI::MultiListBox::_getItemNameAt
const UString & _getItemNameAt(size_t _index) override
Definition: MyGUI_MultiListBox.cpp:597
MyGUI::MultiListBox::removeColumnAt
void removeColumnAt(size_t _column)
Definition: MyGUI_MultiListBox.cpp:628
MyGUI::BiIndexBase::convertToBack
size_t convertToBack(size_t _index) const
Definition: MyGUI_BiIndexBase.cpp:101
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:64
MyGUI::Button
Button properties. Skin childs. Button widget description should be here.
Definition: MyGUI_Button.h:22
MyGUI_MultiListItem.h
MyGUI::BiIndexBase::swapItemsBackAt
void swapItemsBackAt(size_t _index1, size_t _index2)
Definition: MyGUI_BiIndexBase.cpp:131
MyGUI::ListBox::setItemDataAt
void setItemDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
Definition: MyGUI_ListBox.cpp:752
MyGUI::MultiListBox::getColumnNameAt
const UString & getColumnNameAt(size_t _column)
Definition: MyGUI_MultiListBox.cpp:98
MyGUI::MultiListBox::removeAllItems
void removeAllItems()
Definition: MyGUI_MultiListBox.cpp:144
MyGUI::UserData::getUserString
const std::string & getUserString(const std::string &_key) const
Definition: MyGUI_WidgetUserData.cpp:20
MyGUI::MultiListBox::setCoord
void setCoord(const IntCoord &_value) override
Definition: MyGUI_MultiListBox.cpp:822
MyGUI::ResizingPolicy::Auto
@ Auto
Definition: MyGUI_ResizingPolicy.h:19
MyGUI::MultiListBox::_addItem
void _addItem(const MyGUI::UString &_name) override
Definition: MyGUI_MultiListBox.cpp:581
MyGUI::BiIndexBase::removeAllItems
void removeAllItems()
Definition: MyGUI_BiIndexBase.cpp:94
MyGUI::UString
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
Definition: MyGUI_UString.h:168
MyGUI::newDelegate
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
Definition: MyGUI_Delegate.h:99
MyGUI_Precompiled.h
MyGUI::BiIndexBase::insertItemAt
size_t insertItemAt(size_t _index)
Definition: MyGUI_BiIndexBase.cpp:18
MyGUI::Align::Default
@ Default
Definition: MyGUI_Align.h:36
MyGUI::ResizingPolicy::Fill
@ Fill
Definition: MyGUI_ResizingPolicy.h:21
MyGUI::MultiListBox::insertColumnAt
void insertColumnAt(size_t _column, const UString &_name, int _width=0, Any _data=Any::Null)
Definition: MyGUI_MultiListBox.cpp:602
MyGUI::MultiListBox::getItemCount
size_t getItemCount() const
Definition: MyGUI_MultiListBox.cpp:137
MyGUI::MultiListBox::getColumnCount
size_t getColumnCount() const
Get number of columns.
Definition: MyGUI_MultiListBox.cpp:515
MyGUI_ImageBox.h
MyGUI::ResizingPolicy
Definition: MyGUI_ResizingPolicy.h:16
MyGUI::Widget::setVisible
virtual void setVisible(bool _value)
Definition: MyGUI_Widget.cpp:957
MyGUI::MultiListBox::onWidgetDestroy
void onWidgetDestroy(Widget *_widget) override
Definition: MyGUI_MultiListBox.cpp:671
MyGUI::MultiListBox::swapColumnsAt
void swapColumnsAt(size_t _index1, size_t _index2)
Swap columns at a specified positions.
Definition: MyGUI_MultiListBox.cpp:637
MyGUI::MultiListBox::_getItemCount
size_t _getItemCount() override
Definition: MyGUI_MultiListBox.cpp:576
MyGUI_Button.h
MyGUI::MultiListBox::onWidgetCreated
void onWidgetCreated(Widget *_widget) override
Definition: MyGUI_MultiListBox.cpp:660
MYGUI_ASSERT
#define MYGUI_ASSERT(exp, dest)
Definition: MyGUI_Diagnostic.h:34
MyGUI::IObject::castType
Type * castType(bool _throw=true)
Definition: MyGUI_IObject.h:18
MyGUI_WidgetManager.h
MyGUI::MultiListBox::setPosition
void setPosition(const IntPoint &_value) override
Definition: MyGUI_MultiListBox.cpp:809
MyGUI::MultiListBox::getSubItemNameAt
const UString & getSubItemNameAt(size_t _column, size_t _index)
Definition: MyGUI_MultiListBox.cpp:197
MyGUI::MultiListBox::getColumnName
const UString & getColumnName(MultiListItem *_item)
Definition: MyGUI_MultiListBox.cpp:776
MyGUI::MultiListBox::eventListSelectAccept
EventPair< EventHandle_WidgetSizeT, EventHandle_MultiListPtrSizeT > eventListSelectAccept
Definition: MyGUI_MultiListBox.h:270
MyGUI::UserData::isUserString
bool isUserString(const std::string &_key) const
Definition: MyGUI_WidgetUserData.cpp:44
MyGUI::MultiListBox::removeItemAt
void removeItemAt(size_t _index)
Remove item at a specified position.
Definition: MyGUI_MultiListBox.cpp:462
MyGUI::MultiListBox::getColumnWidthAt
int getColumnWidthAt(size_t _column)
Definition: MyGUI_MultiListBox.cpp:104
MyGUI::Widget::_getClientWidget
Widget * _getClientWidget()
If there is client widget return it, otherwise return this.
Definition: MyGUI_Widget.cpp:1133
MyGUI::types::TSize< int >
MyGUI::Widget::setCoord
void setCoord(const IntCoord &_value) override
Definition: MyGUI_Widget.cpp:684
MyGUI::MultiListBox::_getItemAt
Widget * _getItemAt(size_t _index) override
Definition: MyGUI_MultiListBox.cpp:765
MyGUI::ListBox::eventListChangePosition
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListChangePosition
Definition: MyGUI_ListBox.h:203
MyGUI::MultiListBox::addColumn
void addColumn(const UString &_name, int _width=0, Any _data=Any::Null)
Definition: MyGUI_MultiListBox.cpp:520
MyGUI::MultiListBox::clearColumnDataAt
void clearColumnDataAt(size_t _index)
Clear an item data at a specified position.
Definition: MyGUI_MultiListBox.cpp:525
MyGUI::Widget::assignWidget
void assignWidget(T *&_widget, const std::string &_name)
Definition: MyGUI_Widget.h:329
MyGUI::MultiListBox::setColumnResizingPolicy
void setColumnResizingPolicy(MultiListItem *_item, ResizingPolicy _value)
Definition: MyGUI_MultiListBox.cpp:792
MyGUI::BiIndexBase::removeItemAt
size_t removeItemAt(size_t _index)
Definition: MyGUI_BiIndexBase.cpp:66
MyGUI::MultiListBox::setIndexSelected
void setIndexSelected(size_t _index)
Definition: MyGUI_MultiListBox.cpp:173
MyGUI::MultiListBox::getColumnIndex
size_t getColumnIndex(MultiListItem *_item)
Get column index.
Definition: MyGUI_MultiListBox.cpp:781
MyGUI::MultiListBox::findSubItemWith
size_t findSubItemWith(size_t _column, const UString &_name)
Definition: MyGUI_MultiListBox.cpp:205
MyGUI::MultiListBox::swapItemsAt
void swapItemsAt(size_t _index1, size_t _index2)
Swap items at a specified positions.
Definition: MyGUI_MultiListBox.cpp:488
MyGUI::MultiListBox::sortByColumn
void sortByColumn(size_t _column, bool _backward=false)
Definition: MyGUI_MultiListBox.cpp:116
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::eventNotifyItem
EventHandle_MultiListPtrCIBNotifyCellDataRef eventNotifyItem
Definition: MyGUI_MultiListBox.h:294
MyGUI::MultiListBox::setColumnName
void setColumnName(MultiListItem *_item, const UString &_name)
Definition: MyGUI_MultiListBox.cpp:771
MyGUI::ListBox::getItemNameAt
const UString & getItemNameAt(size_t _index)
Get item name from specified position.
Definition: MyGUI_ListBox.cpp:759
MyGUI::IBNotifyItemData
Definition: MyGUI_IBItemInfo.h:62
MYGUI_ASSERT_RANGE_INSERT
#define MYGUI_ASSERT_RANGE_INSERT(index, size, owner)
Definition: MyGUI_Diagnostic.h:47
MyGUI::MultiListBox::setColumnResizingPolicyAt
void setColumnResizingPolicyAt(size_t _index, ResizingPolicy _value)
Definition: MyGUI_MultiListBox.cpp:797
MyGUI::types::TCoord< int >
MyGUI::MultiListBox::initialiseOverride
void initialiseOverride() override
Definition: MyGUI_MultiListBox.cpp:34
MyGUI::MultiListBox::setSize
void setSize(const IntSize &_value) override
Definition: MyGUI_MultiListBox.cpp:814
MyGUI::UserData::_getInternalData
ValueType * _getInternalData(bool _throw=true) const
Definition: MyGUI_WidgetUserData.h:54
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:540
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:507
MyGUI::ListBox::setItemNameAt
void setItemNameAt(size_t _index, const UString &_name)
Replace an item name at a specified position.
Definition: MyGUI_ListBox.cpp:745
MyGUI::Any::Null
static AnyEmpty Null
Definition: MyGUI_Any.h:67
MyGUI
Definition: MyGUI_ActionController.h:15
MyGUI::BiIndexBase::convertToFace
size_t convertToFace(size_t _index) const
Definition: MyGUI_BiIndexBase.cpp:110
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:897
MyGUI::MultiListBox::setItemDataAt
void setItemDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
Definition: MyGUI_MultiListBox.cpp:555
MyGUI_ResourceSkin.h
MyGUI::MultiListBox::setItemNameAt
void setItemNameAt(size_t _index, const UString &_name)
Replace an item name.
Definition: MyGUI_MultiListBox.cpp:535
MyGUI::WidgetInput::eventMouseButtonClick
EventHandle_WidgetVoid eventMouseButtonClick
Definition: MyGUI_WidgetInput.h:169