MyGUI  3.2.1
MyGUI_ItemBox.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_ItemBox.h"
9 #include "MyGUI_Button.h"
10 #include "MyGUI_ScrollBar.h"
11 #include "MyGUI_ResourceSkin.h"
12 #include "MyGUI_InputManager.h"
13 #include "MyGUI_Gui.h"
14 #include "MyGUI_WidgetTranslate.h"
15 #include "MyGUI_WidgetManager.h"
16 
17 namespace MyGUI
18 {
19 
21  mCountItemInLine(0),
22  mCountLines(0),
23  mFirstVisibleIndex(0),
24  mFirstOffsetIndex(0),
25  mIndexSelect(ITEM_NONE),
26  mIndexActive(ITEM_NONE),
27  mIndexAccept(ITEM_NONE),
28  mIndexRefuse(ITEM_NONE),
29  mIsFocus(false),
30  mItemDrag(nullptr),
31  mAlignVert(true)
32  {
34  }
35 
37  {
39 
40  // FIXME нам нужен фокус клавы
41  setNeedKeyFocus(true);
42 
43  mDragLayer = "DragAndDrop";
44 
45  if (isUserString("DragLayer"))
46  mDragLayer = getUserString("DragLayer");
47 
49  assignWidget(mClient, "Client");
50  if (mClient != nullptr)
51  {
56  }
57 
59  assignWidget(mVScroll, "VScroll");
60  if (mVScroll != nullptr)
61  {
63  }
64 
66  assignWidget(mHScroll, "HScroll");
67  if (mHScroll != nullptr)
68  {
70  }
71 
72  // подписываем клиент для драгэндропа
73  if (mClient != nullptr)
74  mClient->_setContainer(this);
75 
76  requestItemSize();
77 
80  }
81 
83  {
84  mVScroll = nullptr;
85  mHScroll = nullptr;
86  mClient = nullptr;
87 
89  }
90 
91  void ItemBox::setPosition(const IntPoint& _point)
92  {
93  Base::setPosition(_point);
94  }
95 
96  void ItemBox::setSize(const IntSize& _size)
97  {
98  Base::setSize(_size);
100  }
101 
102  void ItemBox::setCoord(const IntCoord& _coord)
103  {
104  Base::setCoord(_coord);
106  }
107 
108  void ItemBox::requestItemSize()
109  {
110  IntCoord coord(0, 0, 1, 1);
111 
112  // спрашиваем размер иконок
113  requestCoordItem(this, coord, false);
114 
115  mSizeItem = coord.size();
116  MYGUI_ASSERT((mSizeItem.width > 0 && mSizeItem.height > 0), "(mSizeItem.width > 0 && mSizeItem.height > 0) at requestCoordWidgetItem");
117  }
118 
120  {
121  requestItemSize();
122 
125 
126  _updateAllVisible(true);
127  _resetContainer(true);
128  }
129 
130  void ItemBox::_updateAllVisible(bool _redraw)
131  {
132  int count_visible = 0;
133  if (mAlignVert)
134  {
135  count_visible = (_getClientWidget()->getHeight() / mSizeItem.height) + 2;
136  }
137  else
138  {
139  count_visible = (_getClientWidget()->getWidth() / mSizeItem.width) + 2;
140  }
141 
142  size_t start = (mFirstVisibleIndex * mCountItemInLine);
143  size_t count = (count_visible * mCountItemInLine) + start;
144 
145  size_t index = 0;
146  for (size_t pos = start; pos < count; ++pos, ++index)
147  {
148  // дальше нет айтемов
149  if (pos >= mItemsInfo.size()) break;
150 
151  Widget* item = getItemWidget(index);
152  if (mAlignVert)
153  {
154  item->setPosition(((int)index % mCountItemInLine) * mSizeItem.width - mContentPosition.left,
155  (((int)index / mCountItemInLine) * mSizeItem.height) - mFirstOffsetIndex);
156  }
157  else
158  {
159  item->setPosition((((int)index / mCountItemInLine) * mSizeItem.width) - mFirstOffsetIndex,
160  ((int)index % mCountItemInLine) * mSizeItem.height - mContentPosition.top);
161  }
162 
163  item->setSize(mSizeItem);
164  item->setVisible(true);
165 
166  if (_redraw)
167  {
168  IBDrawItemInfo data(pos, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
169  requestDrawItem(this, item, data);
170  }
171 
172  }
173 
174  // все виджеты еще есть, то их надо бы скрыть
175  while (index < mVectorItems.size())
176  {
177  mVectorItems[index]->setVisible(false);
178  index ++;
179  }
180  }
181 
183  {
184  // еще нет такого виджета, нуно создать
185  if (_index == mVectorItems.size())
186  {
187  requestItemSize();
188 
189  Widget* item = _getClientWidget()->createWidget<Widget>("Default", IntCoord(0, 0, mSizeItem.width, mSizeItem.height), Align::Default);
190 
191  // вызываем запрос на создание виджета
192  requestCreateWidgetItem(this, item);
193 
200  item->_setContainer(this);
203 
204  item->_setInternalData((size_t)mVectorItems.size());
205 
206  mVectorItems.push_back(item);
207  }
208 
209  // запрашивать только последовательно
210  MYGUI_ASSERT_RANGE(_index, mVectorItems.size(), "ItemBox::getItemWidget");
211 
212  return mVectorItems[_index];
213  }
214 
215  void ItemBox::onMouseWheel(int _rel)
216  {
217  notifyMouseWheel(nullptr, _rel);
218 
219  Base::onMouseWheel(_rel);
220  }
221 
223  {
224  mIsFocus = true;
225 
226  Base::onKeySetFocus(_old);
227  }
228 
230  {
231  mIsFocus = false;
232 
233  Base::onKeyLostFocus(_new);
234  }
235 
237  {
238  // сбрасываем старую подсветку
239  if (mIndexActive != ITEM_NONE)
240  {
241  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
242  size_t index = mIndexActive;
243  mIndexActive = ITEM_NONE;
244 
245  // если видим, то обновляем
246  if ((mIndexActive >= start) && (mIndexActive < (start + mVectorItems.size())))
247  {
248  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
249 
250  requestDrawItem(this, mVectorItems[mIndexActive - start], data);
251  }
252  }
253  }
254 
256  {
257  MYGUI_DEBUG_ASSERT(mIndexActive == ITEM_NONE, "use : resetCurrentActiveItem() before findCurrentActiveItem()");
258 
260 
261  // сначала проверяем клиентскую зону
262  const IntRect& rect = _getClientAbsoluteRect();
263  if ((point.left < rect.left) || (point.left > rect.right) || (point.top < rect.top) || (point.top > rect.bottom))
264  {
265  return;
266  }
267 
268  for (size_t pos = 0; pos < mVectorItems.size(); ++pos)
269  {
270  Widget* item = mVectorItems[pos];
271  const IntRect& abs_rect = item->getAbsoluteRect();
272  if ((point.left >= abs_rect.left) && (point.left <= abs_rect.right) && (point.top >= abs_rect.top) && (point.top <= abs_rect.bottom))
273  {
274 
275  size_t index = calcIndexByWidget(item);
276  // при переборе индекс может быть больше, так как может создасться сколько угодно
277  if (index < mItemsInfo.size())
278  {
279 
280  mIndexActive = index;
281  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
282 
283  requestDrawItem(this, item, data);
284  }
285 
286  break;
287  }
288  }
289  }
290 
292  {
293  if (_item == _getClientWidget())
294  return ITEM_NONE;
295  size_t index = calcIndexByWidget(_item);
296  if (index < mItemsInfo.size())
297  return index;
298  return ITEM_NONE;
299  }
300 
301  void ItemBox::_setContainerItemInfo(size_t _index, bool _set, bool _accept)
302  {
303  if (_index == ITEM_NONE) return;
304  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::_setContainerItemInfo");
305 
306  mIndexAccept = (_set && _accept ) ? _index : ITEM_NONE;
307  mIndexRefuse = (_set && !_accept) ? _index : ITEM_NONE;
308 
309  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
310  if ((_index >= start) && (_index < (start + mVectorItems.size())))
311  {
312  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
313  requestDrawItem(this, mVectorItems[_index - start], data);
314  }
315  }
316 
317  void ItemBox::setItemDataAt(size_t _index, Any _data)
318  {
319  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::setItemData");
320  mItemsInfo[_index].data = _data;
321 
322  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
323  if ((_index >= start) && (_index < (start + mVectorItems.size())))
324  {
325  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
326  requestDrawItem(this, mVectorItems[_index - start], data);
327  }
328 
329  _resetContainer(true);
330  }
331 
332  void ItemBox::insertItemAt(size_t _index, Any _data)
333  {
334  MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "ItemBox::insertItemAt");
335  if (_index == ITEM_NONE) _index = mItemsInfo.size();
336 
337  _resetContainer(false);
338 
340 
341  mItemsInfo.insert(mItemsInfo.begin() + _index, ItemDataInfo(_data));
342 
343  // расчитываем новый индекс выделения
344  if (mIndexSelect != ITEM_NONE)
345  {
346  if (mIndexSelect >= _index)
347  {
348  mIndexSelect ++;
349  }
350  }
351 
354 
356 
357  _updateAllVisible(true);
358  }
359 
360  void ItemBox::removeItemAt(size_t _index)
361  {
362  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::removeItemAt");
363 
364  _resetContainer(false);
366 
367  mItemsInfo.erase(mItemsInfo.begin() + _index);
368 
369  // расчитываем новый индекс выделения
370  if (mIndexSelect != ITEM_NONE)
371  {
372  if (mItemsInfo.empty())
373  {
374  mIndexSelect = ITEM_NONE;
375  }
376  else if ((mIndexSelect > _index) || (mIndexSelect == mItemsInfo.size()))
377  {
378  mIndexSelect --;
379  }
380  }
381 
384 
386 
387  _updateAllVisible(true);
388  }
389 
391  {
392  if (mItemsInfo.empty())
393  return;
394  _resetContainer(false);
395 
396  mItemsInfo.clear();
397 
398  mIndexSelect = ITEM_NONE;
399  mIndexActive = ITEM_NONE;
400 
403 
404  _updateAllVisible(true);
405  }
406 
407  void ItemBox::redrawItemAt(size_t _index)
408  {
409  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::redrawItemAt");
410 
411  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
412  if ((_index >= start) && (_index < (start + mVectorItems.size())))
413  {
414  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
415  requestDrawItem(this, mVectorItems[_index - start], data);
416  }
417  }
418 
419  void ItemBox::setIndexSelected(size_t _index)
420  {
421  MYGUI_ASSERT_RANGE_AND_NONE(_index, mItemsInfo.size(), "ItemBox::setIndexSelected");
422  if (_index == mIndexSelect) return;
423 
424  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
425 
426  // сбрасываем старое выделение
427  if (mIndexSelect != ITEM_NONE)
428  {
429  size_t index = mIndexSelect;
430  mIndexSelect = ITEM_NONE;
431 
432  if ((index >= start) && (index < (start + mVectorItems.size())))
433  {
434  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
435  requestDrawItem(this, mVectorItems[index - start], data);
436  }
437  }
438 
439  mIndexSelect = _index;
440  if (mIndexSelect != ITEM_NONE)
441  {
442  if ((_index >= start) && (_index < (start + mVectorItems.size())))
443  {
444  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
445  requestDrawItem(this, mVectorItems[_index - start], data);
446  }
447  }
448 
449  }
450 
452  {
453  size_t index = getIndexByWidget(_sender);
454 
455  eventSelectItemAccept(this, index);
456  }
457 
459  {
460  if (mAlignVert == _vert)
461  return;
462  mAlignVert = _vert;
463 
464  mCountItemInLine = -1;
466  }
467 
469  {
471  }
472 
474  {
476  }
477 
479  {
480  MYGUI_ASSERT(_widget, "ItemBox::getIndexByWidget : Widget == nullptr");
481  if (_widget == _getClientWidget()) return ITEM_NONE;
482  MYGUI_ASSERT(_widget->getParent() == _getClientWidget(), "ItemBox::getIndexByWidget : Widget is not child");
483 
484  size_t index = calcIndexByWidget(_widget);
485  MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::getIndexByWidget");
486 
487  return index;
488  }
489 
490  size_t ItemBox::_getContainerIndex(const IntPoint& _point)
491  {
492  for (VectorWidgetPtr::iterator iter = mVectorItems.begin(); iter != mVectorItems.end(); ++iter)
493  {
494  if ((*iter)->getVisible())
495  {
496  if ((*iter)->getAbsoluteRect().inside(_point))
497  {
498  return getIndexByWidget(*iter);
499  }
500  }
501  }
502  return ITEM_NONE;
503  }
504 
505  void ItemBox::_resetContainer(bool _update)
506  {
507  // обязательно у базового
508  Base::_resetContainer(_update);
509 
510  if ( ! _update)
511  {
513  for (VectorWidgetPtr::iterator iter = mVectorItems.begin(); iter != mVectorItems.end(); ++iter)
514  {
515  instance.unlinkFromUnlinkers(*iter);
516  }
517  }
518  }
519 
521  {
522  for (VectorWidgetPtr::iterator iter = mVectorItems.begin(); iter != mVectorItems.end(); ++iter)
523  {
524  if ((*iter)->getVisible())
525  {
526  size_t index = getIndexByWidget(*iter);
527 
528  if (index == _index) return (*iter);
529  }
530  }
531  return nullptr;
532  }
533 
534  void ItemBox::onMouseButtonPressed(int _left, int _top, MouseButton _id)
535  {
536  Base::onMouseButtonPressed(_left, _top, _id);
537  }
538 
539  void ItemBox::onMouseButtonReleased(int _left, int _top, MouseButton _id)
540  {
541  Base::onMouseButtonReleased(_left, _top, _id);
542  }
543 
544  void ItemBox::onMouseDrag(int _left, int _top, MouseButton _id)
545  {
546  Base::onMouseDrag(_left, _top, _id);
547  }
548 
550  {
551  if (mItemDrag) mItemDrag->setVisible(false);
552  }
553 
555  {
556  if (nullptr == mItemDrag)
557  {
558  // спрашиваем размер иконок
559  IntCoord coord;
560 
561  requestCoordItem(this, coord, true);
562 
563  mPointDragOffset = coord.point();
564 
565  // создаем и запрашиваем детей
566  mItemDrag = Gui::getInstance().createWidget<Widget>("Default", IntCoord(0, 0, coord.width, coord.height), Align::Default, mDragLayer);
567  requestCreateWidgetItem(this, mItemDrag);
568  }
569 
571 
572  mItemDrag->setPosition(point.left - mClickInWidget.left + mPointDragOffset.left, point.top - mClickInWidget.top + mPointDragOffset.top);
573  mItemDrag->setVisible(true);
574  }
575 
577  {
578  IBDrawItemInfo data;
579  data.drop_accept = _state.accept;
580  data.drop_refuse = _state.refuse;
581 
582  data.select = false;
583  data.active = false;
584 
585  data.index = mDropSenderIndex;
586  data.update = _state.update;
587  data.drag = true;
588 
589  requestDrawItem(this, mItemDrag, data);
590  }
591 
592  void ItemBox::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
593  {
594  mouseDrag(_id);
595  }
596 
597  void ItemBox::notifyMouseButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
598  {
599  mouseButtonPressed(_id);
600 
601  if ( MouseButton::Left == _id)
602  {
603  size_t old = mIndexSelect;
604 
605  if (_sender == _getClientWidget())
606  {
607  // сбрасываем выделение
609  }
610  else
611  {
612  // индекс отправителя
614 
615  // выделенный елемент
617  }
618 
619  // смещение внутри виджета, куда кликнули мышкой
621 
622  // отсылаем событие
623  eventMouseItemActivate(this, mIndexSelect);
624  // смену позиции отсылаем только при реальном изменении
625  if (old != mIndexSelect) eventChangeItemPosition(this, mIndexSelect);
626  }
627 
629  }
630 
631  void ItemBox::notifyMouseButtonReleased(Widget* _sender, int _left, int _top, MouseButton _id)
632  {
633  bool needEvent = !mStartDrop;
634  mouseButtonReleased(_id);
635 
636  if (needEvent)
638  }
639 
640  void ItemBox::notifyRootMouseChangeFocus(Widget* _sender, bool _focus)
641  {
642  size_t index = calcIndexByWidget(_sender);
643  if (_focus)
644  {
645  MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::notifyRootMouseChangeFocus");
646 
647  // сбрасываем старый
648  if (mIndexActive != ITEM_NONE)
649  {
650  size_t old_index = mIndexActive;
651  mIndexActive = ITEM_NONE;
652  IBDrawItemInfo data(old_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
653  requestDrawItem(this, mVectorItems[old_index - (mFirstVisibleIndex * mCountItemInLine)], data);
654  }
655 
656  mIndexActive = index;
657  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
658  requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
659  }
660  else
661  {
662  // при сбросе виджет может быть уже скрыт, и соответсвенно отсутсвовать индекс
663  // сбрасываем индекс, только если мы и есть актив
664  if (index < mItemsInfo.size() && mIndexActive == index)
665  {
666  mIndexActive = ITEM_NONE;
667  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
668  requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
669  }
670  }
671  }
672 
674  {
675  if (mAlignVert)
676  {
677  // колличество айтемов на одной строке
678  mCountItemInLine = _getClientWidget()->getWidth() / mSizeItem.width;
679  }
680  else
681  {
682  // колличество айтемов на одной строке
683  mCountItemInLine = _getClientWidget()->getHeight() / mSizeItem.height;
684  }
685 
686  if (1 > mCountItemInLine) mCountItemInLine = 1;
687 
688  // колличество строк
689  mCountLines = mItemsInfo.size() / mCountItemInLine;
690  if (0 != (mItemsInfo.size() % mCountItemInLine)) mCountLines ++;
691 
692  if (mAlignVert)
693  {
694  mContentSize.width = (mSizeItem.width * mCountItemInLine);
695  mContentSize.height = (mSizeItem.height * mCountLines);
696  }
697  else
698  {
699  mContentSize.width = (mSizeItem.width * mCountLines);
700  mContentSize.height = (mSizeItem.height * mCountItemInLine);
701  }
702  }
703 
704  void ItemBox::notifyScrollChangePosition(ScrollBar* _sender, size_t _index)
705  {
706  if (_sender == mVScroll)
707  {
708  mContentPosition.top = (int)_index;
709  }
710  else if (_sender == mHScroll)
711  {
712  mContentPosition.left = (int)_index;
713  }
714 
715  setContentPosition(mContentPosition);
716  }
717 
718  void ItemBox::notifyMouseWheel(Widget* _sender, int _rel)
719  {
720  if (mAlignVert)
721  {
722  if (mContentSize.height <= 0)
723  return;
724 
725  int offset = mContentPosition.top;
726  if (_rel < 0)
727  offset += mSizeItem.height;
728  else
729  offset -= mSizeItem.height;
730 
731  if (mContentSize.height <= _getClientWidget()->getHeight())
732  offset = 0;
733  else if (offset >= mContentSize.height - _getClientWidget()->getHeight())
734  offset = mContentSize.height - _getClientWidget()->getHeight();
735  else if (offset < 0)
736  offset = 0;
737 
738  if (mContentPosition.top == offset)
739  return;
740 
741  // сбрасываем старую подсветку
742  // так как при прокрутке, мышь может находиться над окном
744 
745  mContentPosition.top = offset;
746  }
747  else
748  {
749  if (mContentSize.width <= 0)
750  return;
751 
752  int offset = mContentPosition.left;
753  if (_rel < 0)
754  offset += mSizeItem.width;
755  else
756  offset -= mSizeItem.width;
757 
758  if (mContentSize.width <= _getClientWidget()->getWidth())
759  offset = 0;
760  else if (offset >= mContentSize.width - _getClientWidget()->getWidth())
761  offset = mContentSize.width - _getClientWidget()->getWidth();
762  else if (offset < 0)
763  offset = 0;
764 
765  if (mContentPosition.left == offset)
766  return;
767 
768  // сбрасываем старую подсветку
769  // так как при прокрутке, мышь может находиться над окном
771 
772  mContentPosition.left = offset;
773  }
774 
775  setContentPosition(mContentPosition);
776 
777  // заново ищем и подсвечиваем айтем
778  if (!mNeedDrop)
780 
781  if (nullptr != mVScroll)
782  mVScroll->setScrollPosition(mContentPosition.top);
783  if (nullptr != mHScroll)
784  mHScroll->setScrollPosition(mContentPosition.left);
785  }
786 
787  void ItemBox::setContentPosition(const IntPoint& _point)
788  {
789  mContentPosition = _point;
790 
791  int old = mFirstVisibleIndex;
792 
793  if (mAlignVert)
794  {
795  mFirstVisibleIndex = mContentPosition.top / mSizeItem.height;
796  mFirstOffsetIndex = mContentPosition.top % mSizeItem.height;
797  }
798  else
799  {
800  mFirstVisibleIndex = mContentPosition.left / mSizeItem.width;
801  mFirstOffsetIndex = mContentPosition.left % mSizeItem.width;
802  }
803 
804  _updateAllVisible(old != mFirstVisibleIndex);
805  _resetContainer(true);
806  }
807 
809  {
810  _updateAllVisible(true);
811  }
812 
814  {
815  endDrop(true);
816  }
817 
818  size_t ItemBox::calcIndexByWidget(Widget* _widget)
819  {
820  return *_widget->_getInternalData<size_t>() + (mFirstVisibleIndex * mCountItemInLine);
821  }
822 
823  IntSize ItemBox::getContentSize()
824  {
825  return mContentSize;
826  }
827 
828  IntPoint ItemBox::getContentPosition()
829  {
830  return mContentPosition;
831  }
832 
834  {
835  return _getClientWidget()->getSize();
836  }
837 
838  void ItemBox::eraseContent()
839  {
840  updateMetrics();
841  }
842 
843  size_t ItemBox::getHScrollPage()
844  {
845  return mSizeItem.width;
846  }
847 
848  size_t ItemBox::getVScrollPage()
849  {
850  return mSizeItem.height;
851  }
852 
853  Align ItemBox::getContentAlign()
854  {
855  return Align::Default;
856  }
857 
858  IntRect ItemBox::_getClientAbsoluteRect()
859  {
860  return _getClientWidget()->getAbsoluteRect();
861  }
862 
863  Widget* ItemBox::_getClientWidget()
864  {
865  return mClient == nullptr ? this : mClient;
866  }
867 
868  size_t ItemBox::getItemCount() const
869  {
870  return mItemsInfo.size();
871  }
872 
873  void ItemBox::addItem(Any _data)
874  {
875  insertItemAt(ITEM_NONE, _data);
876  }
877 
879  {
880  return mIndexSelect;
881  }
882 
884  {
886  }
887 
888  void ItemBox::clearItemDataAt(size_t _index)
889  {
890  setItemDataAt(_index, Any::Null);
891  }
892 
894  {
895  return mAlignVert;
896  }
897 
899  {
900  return mItemDrag;
901  }
902 
903  void ItemBox::setPosition(int _left, int _top)
904  {
905  setPosition(IntPoint(_left, _top));
906  }
907 
908  void ItemBox::setSize(int _width, int _height)
909  {
910  setSize(IntSize(_width, _height));
911  }
912 
913  void ItemBox::setCoord(int _left, int _top, int _width, int _height)
914  {
915  setCoord(IntCoord(_left, _top, _width, _height));
916  }
917 
918  void ItemBox::setPropertyOverride(const std::string& _key, const std::string& _value)
919  {
921  if (_key == "VerticalAlignment")
922  setVerticalAlignment(utility::parseValue<bool>(_value));
923 
924  else
925  {
926  Base::setPropertyOverride(_key, _value);
927  return;
928  }
929 
930  eventChangeProperty(this, _key, _value);
931  }
932 
933  void ItemBox::setViewOffset(const IntPoint& _value)
934  {
935  if (mAlignVert)
936  {
937  if (mContentSize.height <= 0)
938  return;
939 
940  int offset = _value.top;
941 
942  if (mContentSize.height <= _getClientWidget()->getHeight())
943  offset = 0;
944  else if (offset >= mContentSize.height - _getClientWidget()->getHeight())
945  offset = mContentSize.height - _getClientWidget()->getHeight();
946  else if (offset < 0)
947  offset = 0;
948 
949  if (mContentPosition.top == offset)
950  return;
951 
952  // сбрасываем старую подсветку
953  // так как при прокрутке, мышь может находиться над окном
955 
956  mContentPosition.top = offset;
957  }
958  else
959  {
960  if (mContentSize.width <= 0)
961  return;
962 
963  int offset = _value.left;
964 
965  if (mContentSize.width <= _getClientWidget()->getWidth())
966  offset = 0;
967  else if (offset >= mContentSize.width - _getClientWidget()->getWidth())
968  offset = mContentSize.width - _getClientWidget()->getWidth();
969  else if (offset < 0)
970  offset = 0;
971 
972  if (mContentPosition.left == offset)
973  return;
974 
975  // сбрасываем старую подсветку
976  // так как при прокрутке, мышь может находиться над окном
978 
979  mContentPosition.left = offset;
980  }
981 
982  setContentPosition(mContentPosition);
983 
984  // заново ищем и подсвечиваем айтем
985  if (!mNeedDrop)
987 
988  if (nullptr != mVScroll)
989  mVScroll->setScrollPosition(mContentPosition.top);
990  if (nullptr != mHScroll)
991  mHScroll->setScrollPosition(mContentPosition.left);
992  }
993 
995  {
996  return getContentPosition();
997  }
998 
1000  {
1001  Base::onKeyButtonPressed(_key, _char);
1002 
1004  }
1005 
1007  {
1009 
1011  }
1012 
1013 } // namespace MyGUI