MyGUI  3.0.1
MyGUI_ItemBox.cpp
Go to the documentation of this file.
1 
7 /*
8  This file is part of MyGUI.
9 
10  MyGUI is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  MyGUI is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
22 */
23 #include "MyGUI_Precompiled.h"
24 #include "MyGUI_ItemBox.h"
25 #include "MyGUI_Button.h"
26 #include "MyGUI_VScroll.h"
27 #include "MyGUI_HScroll.h"
28 #include "MyGUI_ResourceSkin.h"
29 #include "MyGUI_InputManager.h"
30 #include "MyGUI_Gui.h"
31 #include "MyGUI_WidgetTranslate.h"
32 #include "MyGUI_WidgetManager.h"
33 
34 namespace MyGUI
35 {
36 
38  mCountItemInLine(0),
39  mCountLines(0),
40  mFirstVisibleIndex(0),
41  mFirstOffsetIndex(0),
42  mIndexSelect(ITEM_NONE),
43  mIndexActive(ITEM_NONE),
44  mIndexAccept(ITEM_NONE),
45  mIndexRefuse(ITEM_NONE),
46  mIsFocus(false),
47  mItemDrag(nullptr),
48  mAlignVert(true)
49  {
51  }
52 
53  void ItemBox::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
54  {
55  Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
56 
57  initialiseWidgetSkin(_info);
58  }
59 
61  {
62  shutdownWidgetSkin();
63  }
64 
66  {
67  shutdownWidgetSkin();
69  initialiseWidgetSkin(_info);
70  }
71 
72  void ItemBox::initialiseWidgetSkin(ResourceSkin* _info)
73  {
74  // нам нужен фокус клавы
75  mNeedKeyFocus = true;
76  mDragLayer = "DragAndDrop";
77 
78  const MapString& properties = _info->getProperties();
79  if (!properties.empty())
80  {
81  MapString::const_iterator iter = properties.find("AlignVert");
82  if (iter != properties.end()) mAlignVert = utility::parseBool(iter->second);
83  iter = properties.find("DragLayer");
84  if (iter != properties.end()) mDragLayer = iter->second;
85  }
86 
87  for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
88  {
89  if (*(*iter)->_getInternalData<std::string>() == "VScroll")
90  {
91  MYGUI_DEBUG_ASSERT( ! mVScroll, "widget already assigned");
92  mVScroll = (*iter)->castType<VScroll>();
94  }
95  if (*(*iter)->_getInternalData<std::string>() == "HScroll")
96  {
97  MYGUI_DEBUG_ASSERT( ! mHScroll, "widget already assigned");
98  mHScroll = (*iter)->castType<HScroll>();
100  }
101  else if (*(*iter)->_getInternalData<std::string>() == "Client")
102  {
103  MYGUI_DEBUG_ASSERT( ! mWidgetClient, "widget already assigned");
104  mWidgetClient = (*iter);
108  }
109  }
110  // сли нет скрола, то клиенская зона не обязательно
111  //MYGUI_ASSERT(nullptr != mWidgetClient, "Child Widget Client not found in skin (ItemBox must have Client) skin ='" << _info->getSkinName() << "'");
112 
113  // подписываем клиент для драгэндропа
114  if (mWidgetClient != nullptr)
116 
117  requestItemSize();
118 
121  }
122 
123  void ItemBox::shutdownWidgetSkin()
124  {
125  mVScroll = nullptr;
126  mHScroll = nullptr;
127  mClient = nullptr;
128  mWidgetClient = nullptr;
129  }
130 
131  void ItemBox::setPosition(const IntPoint& _point)
132  {
133  Base::setPosition(_point);
134  }
135 
136  void ItemBox::setSize(const IntSize& _size)
137  {
138  Base::setSize(_size);
140  }
141 
142  void ItemBox::setCoord(const IntCoord& _coord)
143  {
144  Base::setCoord(_coord);
146  }
147 
148  void ItemBox::requestItemSize()
149  {
150  IntCoord coord(0, 0, 1, 1);
151 
152  // спрашиваем размер иконок
153  requestCoordItem(this, coord, false);
154 
155  mSizeItem = coord.size();
156  MYGUI_ASSERT((mSizeItem.width > 0 && mSizeItem.height > 0), "(mSizeItem.width > 0 && mSizeItem.height > 0) at requestCoordWidgetItem");
157  }
158 
160  {
161  requestItemSize();
162 
165 
166  _updateAllVisible(true);
167  _resetContainer(true);
168  }
169 
170  void ItemBox::_updateAllVisible(bool _redraw)
171  {
172  int count_visible = 0;
173  if (mAlignVert)
174  {
175  count_visible = (_getClientWidget()->getHeight() / mSizeItem.height) + 2;
176  }
177  else
178  {
179  count_visible = (_getClientWidget()->getWidth() / mSizeItem.width) + 2;
180  }
181 
182  size_t start = (mFirstVisibleIndex * mCountItemInLine);
183  size_t count = (count_visible * mCountItemInLine) + start;
184 
185  size_t index = 0;
186  for (size_t pos = start; pos<count; ++pos, ++index)
187  {
188  // дальше нет айтемов
189  if (pos >= mItemsInfo.size()) break;
190 
191  Widget* item = getItemWidget(index);
192  if (mAlignVert)
193  {
194  item->setPosition(((int)index % mCountItemInLine) * mSizeItem.width - mContentPosition.left,
195  (((int)index / mCountItemInLine) * mSizeItem.height) - mFirstOffsetIndex);
196  }
197  else
198  {
199  item->setPosition((((int)index / mCountItemInLine) * mSizeItem.width) - mFirstOffsetIndex,
200  ((int)index % mCountItemInLine) * mSizeItem.height - mContentPosition.top);
201  }
202 
203  item->setSize(mSizeItem);
204  item->setVisible(true);
205 
206  if (_redraw)
207  {
208  IBDrawItemInfo data(pos, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
209  requestDrawItem(this, item, data);
210  }
211 
212  }
213 
214  // все виджеты еще есть, то их надо бы скрыть
215  while (index < mVectorItems.size())
216  {
217  mVectorItems[index]->setVisible(false);
218  index ++;
219  }
220 
221  }
222 
224  {
225  // еще нет такого виджета, нуно создать
226  if (_index == mVectorItems.size())
227  {
228 
229  requestItemSize();
230 
231  Widget* item = _getClientWidget()->createWidget<Widget>("Default", IntCoord(0, 0, mSizeItem.width, mSizeItem.height), Align::Default);
232 
233  // вызываем запрос на создание виджета
234  requestCreateWidgetItem(this, item);
235 
245 
246  item->_setInternalData((size_t)mVectorItems.size());
247 
248  mVectorItems.push_back(item);
249  }
250 
251  // запрашивать только последовательно
252  MYGUI_ASSERT_RANGE(_index, mVectorItems.size(), "ItemBox::getItemWidget");
253 
254  return mVectorItems[_index];
255  }
256 
257  void ItemBox::onMouseWheel(int _rel)
258  {
259  notifyMouseWheel(nullptr, _rel);
260 
261  Base::onMouseWheel(_rel);
262  }
263 
265  {
266  mIsFocus = true;
267  setState("pushed");
268 
269  Base::onKeySetFocus(_old);
270  }
271 
273  {
274  mIsFocus = false;
275  setState("normal");
276 
277  Base::onKeyLostFocus(_new);
278  }
279 
281  {
282  // сбрасываем старую подсветку
283  if (mIndexActive != ITEM_NONE)
284  {
285  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
286  size_t index = mIndexActive;
287  mIndexActive = ITEM_NONE;
288 
289  // если видим, то обновляем
290  if ((mIndexActive >= start) && (mIndexActive < (start + mVectorItems.size())))
291  {
292  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
293 
294  requestDrawItem(this, mVectorItems[mIndexActive - start], data);
295  }
296  }
297  }
298 
300  {
301  MYGUI_DEBUG_ASSERT(mIndexActive == ITEM_NONE, "use : resetCurrentActiveItem() before findCurrentActiveItem()");
302 
304 
305  // сначала проверяем клиентскую зону
306  const IntRect& rect = _getClientAbsoluteRect();
307  if ((point.left < rect.left) || (point.left > rect.right) || (point.top < rect.top) || (point.top > rect.bottom))
308  {
309  return;
310  }
311 
312  for (size_t pos=0; pos<mVectorItems.size(); ++pos)
313  {
314  Widget* item = mVectorItems[pos];
315  const IntRect& abs_rect = item->getAbsoluteRect();
316  if ((point.left>= abs_rect.left) && (point.left <= abs_rect.right) && (point.top>= abs_rect.top) && (point.top <= abs_rect.bottom))
317  {
318 
319  size_t index = calcIndexByWidget(item);
320  // при переборе индекс может быть больше, так как может создасться сколько угодно
321  if (index < mItemsInfo.size())
322  {
323 
324  mIndexActive = index;
325  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
326 
327  requestDrawItem(this, item, data);
328  }
329 
330  break;
331  }
332  }
333  }
334 
335  void ItemBox::_requestGetContainer(Widget* _sender, Widget*& _container, size_t& _index)
336  {
337  if (_sender == _getClientWidget())
338  {
339  _container = this;
340  _index = ITEM_NONE;
341  }
342  else
343  {
344  size_t index = calcIndexByWidget(_sender);
345  if (index < mItemsInfo.size())
346  {
347  _container = this;
348  _index = index;
349  }
350  }
351  }
352 
353  void ItemBox::_setContainerItemInfo(size_t _index, bool _set, bool _accept)
354  {
355  if (_index == ITEM_NONE) return;
356  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::_setContainerItemInfo");
357 
358  mIndexAccept = (_set && _accept ) ? _index : ITEM_NONE;
359  mIndexRefuse = (_set && !_accept) ? _index : ITEM_NONE;
360 
361  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
362  if ((_index >= start) && (_index < (start + mVectorItems.size())))
363  {
364  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
365  requestDrawItem(this, mVectorItems[_index - start], data);
366  }
367  }
368 
369  void ItemBox::setItemDataAt(size_t _index, Any _data)
370  {
371  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::setItemData");
372  mItemsInfo[_index].data = _data;
373 
374  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
375  if ((_index >= start) && (_index < (start + mVectorItems.size())))
376  {
377  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
378  requestDrawItem(this, mVectorItems[_index - start], data);
379  }
380 
381  _resetContainer(true);
382  }
383 
384  void ItemBox::insertItemAt(size_t _index, Any _data)
385  {
386  MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "ItemBox::insertItemAt");
387  if (_index == ITEM_NONE) _index = mItemsInfo.size();
388 
389  _resetContainer(false);
390 
392 
393  mItemsInfo.insert(mItemsInfo.begin() + _index, ItemDataInfo(_data));
394 
395  // расчитываем новый индекс выделения
396  if (mIndexSelect != ITEM_NONE)
397  {
398  if (mIndexSelect >= _index)
399  {
400  mIndexSelect ++;
401  }
402  }
403 
406 
408 
409  _updateAllVisible(true);
410  }
411 
412  void ItemBox::removeItemAt(size_t _index)
413  {
414  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::removeItemAt");
415 
416  _resetContainer(false);
418 
419  mItemsInfo.erase(mItemsInfo.begin() + _index);
420 
421  // расчитываем новый индекс выделения
422  if (mIndexSelect != ITEM_NONE)
423  {
424  if (mItemsInfo.empty())
425  {
426  mIndexSelect = ITEM_NONE;
427  }
428  else if ((mIndexSelect > _index) || (mIndexSelect == mItemsInfo.size()))
429  {
430  mIndexSelect --;
431  }
432  }
433 
436 
438 
439  _updateAllVisible(true);
440  }
441 
443  {
444  if (0 == mItemsInfo.size()) return;
445  _resetContainer(false);
446 
447  mItemsInfo.clear();
448 
449  mIndexSelect = ITEM_NONE;
450  mIndexActive = ITEM_NONE;
451 
454 
455  _updateAllVisible(true);
456  }
457 
458  void ItemBox::redrawItemAt(size_t _index)
459  {
460  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::redrawItemAt");
461 
462  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
463  if ((_index >= start) && (_index < (start + mVectorItems.size())))
464  {
465  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
466  requestDrawItem(this, mVectorItems[_index - start], data);
467  }
468  }
469 
470  void ItemBox::setIndexSelected(size_t _index)
471  {
472  MYGUI_ASSERT_RANGE_AND_NONE(_index, mItemsInfo.size(), "ItemBox::setIndexSelected");
473  if (_index == mIndexSelect) return;
474 
475  size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine);
476 
477  // сбрасываем старое выделение
478  if (mIndexSelect != ITEM_NONE)
479  {
480  size_t index = mIndexSelect;
481  mIndexSelect = ITEM_NONE;
482 
483  if ((index >= start) && (index < (start + mVectorItems.size())))
484  {
485  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
486  requestDrawItem(this, mVectorItems[index - start], data);
487  }
488  }
489 
490  mIndexSelect = _index;
491  if (mIndexSelect != ITEM_NONE)
492  {
493  if ((_index >= start) && (_index < (start + mVectorItems.size())))
494  {
495  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
496  requestDrawItem(this, mVectorItems[_index - start], data);
497  }
498  }
499 
500  }
501 
503  {
504  size_t index = getIndexByWidget(_sender);
505 
506  eventSelectItemAccept(this, index);
507  }
508 
510  {
511  if (mAlignVert == _vert) return;
512  mAlignVert = _vert;
513 
514  mCountItemInLine = -1;
516  }
517 
519  {
521  }
522 
524  {
526  }
527 
529  {
530  MYGUI_ASSERT(_widget, "ItemBox::getIndexByWidget : Widget == nullptr");
531  if (_widget == _getClientWidget()) return ITEM_NONE;
532  MYGUI_ASSERT(_widget->getParent() == _getClientWidget(), "ItemBox::getIndexByWidget : Widget is not child");
533 
534  size_t index = calcIndexByWidget(_widget);
535  MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::getIndexByWidget");
536 
537  return index;
538  }
539 
540  size_t ItemBox::_getContainerIndex(const IntPoint& _point)
541  {
542  for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
543  {
544  if ((*iter)->isVisible())
545  {
546  if ((*iter)->getAbsoluteRect().inside(_point))
547  {
548  return getIndexByWidget(*iter);
549  }
550  }
551  }
552  return ITEM_NONE;
553  }
554 
555  void ItemBox::_resetContainer(bool _update)
556  {
557  // обязательно у базового
558  Base::_resetContainer(_update);
559 
560  if ( ! _update)
561  {
563  for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
564  {
565  instance.unlinkFromUnlinkers(*iter);
566  }
567  }
568  }
569 
571  {
572  for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
573  {
574  if ((*iter)->isVisible())
575  {
576  size_t index = getIndexByWidget(*iter);
577 
578  if (index == _index) return (*iter);
579  }
580  }
581  return nullptr;
582  }
583 
584  void ItemBox::onMouseButtonPressed(int _left, int _top, MouseButton _id)
585  {
586  Base::onMouseButtonPressed(_left, _top, _id);
587  }
588 
589  void ItemBox::onMouseButtonReleased(int _left, int _top, MouseButton _id)
590  {
591  Base::onMouseButtonReleased(_left, _top, _id);
592  }
593 
594  void ItemBox::onMouseDrag(int _left, int _top)
595  {
596  Base::onMouseDrag(_left, _top);
597  }
598 
600  {
601  if (mItemDrag) mItemDrag->setVisible(false);
602  }
603 
605  {
606  if (nullptr == mItemDrag)
607  {
608  // спрашиваем размер иконок
609  IntCoord coord;
610 
611  requestCoordItem(this, coord, true);
612 
613  mPointDragOffset = coord.point();
614 
615  // создаем и запрашиваем детей
616  mItemDrag = Gui::getInstance().createWidget<Widget>("Default", IntCoord(0, 0, coord.width, coord.height), Align::Default, mDragLayer);
617  requestCreateWidgetItem(this, mItemDrag);
618  }
619 
621 
622  mItemDrag->setPosition(point.left - mClickInWidget.left + mPointDragOffset.left, point.top - mClickInWidget.top + mPointDragOffset.top);
623  mItemDrag->setVisible(true);
624  }
625 
627  {
628  IBDrawItemInfo data;
629  data.drop_accept = _state.accept;
630  data.drop_refuse = _state.refuse;
631 
632  data.select = false;
633  data.active = false;
634 
635  data.index = mDropSenderIndex;
636  data.update = _state.update;
637  data.drag = true;
638 
639  requestDrawItem(this, mItemDrag, data);
640  }
641 
642  void ItemBox::notifyMouseDrag(Widget* _sender, int _left, int _top)
643  {
644  mouseDrag();
645  }
646 
647  void ItemBox::notifyMouseButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
648  {
649  mouseButtonPressed(_id);
650 
651  if ( MouseButton::Left == _id)
652  {
653  size_t old = mIndexSelect;
654 
655  if (_sender == _getClientWidget())
656  {
657  // сбрасываем выделение
659  }
660  else
661  {
662  // индекс отправителя
664 
665  // выделенный елемент
667  }
668 
669  // смещение внутри виджета, куда кликнули мышкой
671 
672  // отсылаем событие
673  eventMouseItemActivate(this, mIndexSelect);
674  // смену позиции отсылаем только при реальном изменении
675  if (old != mIndexSelect) eventChangeItemPosition(this, mIndexSelect);
676  }
677 
679  }
680 
681  void ItemBox::notifyMouseButtonReleased(Widget* _sender, int _left, int _top, MouseButton _id)
682  {
683  mouseButtonReleased(_id);
684  size_t index = calcIndexByWidget(_sender);
685  // солличество айтемов может измениться
686  if (index >= getItemCount()) return;
687  eventNotifyItem(this, IBNotifyItemData(index, IBNotifyItemData::MouseReleased, _left, _top, _id));
688  }
689 
690  void ItemBox::notifyRootMouseChangeFocus(Widget* _sender, bool _focus)
691  {
692  size_t index = calcIndexByWidget(_sender);
693  if (_focus)
694  {
695  MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::notifyRootMouseChangeFocus");
696 
697  // сбрасываем старый
698  if (mIndexActive != ITEM_NONE)
699  {
700  size_t old_index = mIndexActive;
701  mIndexActive = ITEM_NONE;
702  IBDrawItemInfo data(old_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
703  requestDrawItem(this, mVectorItems[old_index - (mFirstVisibleIndex * mCountItemInLine)], data);
704  }
705 
706  mIndexActive = index;
707  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
708  requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
709  }
710  else
711  {
712  // при сбросе виджет может быть уже скрыт, и соответсвенно отсутсвовать индекс
713  // сбрасываем индекс, только если мы и есть актив
714  if (index < mItemsInfo.size() && mIndexActive == index)
715  {
716  mIndexActive = ITEM_NONE;
717  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
718  requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data);
719  }
720  }
721  }
722 
724  {
725  if (mAlignVert)
726  {
727  // колличество айтемов на одной строке
728  mCountItemInLine = _getClientWidget()->getWidth() / mSizeItem.width;
729  }
730  else
731  {
732  // колличество айтемов на одной строке
733  mCountItemInLine = _getClientWidget()->getHeight() / mSizeItem.height;
734  }
735 
736  if (1 > mCountItemInLine) mCountItemInLine = 1;
737 
738  // колличество строк
739  mCountLines = mItemsInfo.size() / mCountItemInLine;
740  if (0 != (mItemsInfo.size() % mCountItemInLine)) mCountLines ++;
741 
742  if (mAlignVert)
743  {
744  mContentSize.width = (mSizeItem.width * mCountItemInLine);
745  mContentSize.height = (mSizeItem.height * mCountLines);
746  }
747  else
748  {
749  mContentSize.width = (mSizeItem.width * mCountLines);
750  mContentSize.height = (mSizeItem.height * mCountItemInLine);
751  }
752  }
753 
754  void ItemBox::notifyScrollChangePosition(VScroll* _sender, size_t _index)
755  {
756  if (_sender == mVScroll)
757  {
758  mContentPosition.top = (int)_index;
759  }
760  else if (_sender == mHScroll)
761  {
762  mContentPosition.left = (int)_index;
763  }
764 
765  setContentPosition(mContentPosition);
766  }
767 
768  void ItemBox::notifyMouseWheel(Widget* _sender, int _rel)
769  {
770  if (mAlignVert)
771  {
772  if (mContentSize.height <= 0) return;
773 
774  int offset = mContentPosition.top;
775  if (_rel < 0) offset += mSizeItem.height;
776  else offset -= mSizeItem.height;
777 
778  if (offset >= mContentSize.height - _getClientWidget()->getHeight()) offset = mContentSize.height - _getClientWidget()->getHeight();
779  else if (offset < 0) offset = 0;
780 
781  if (mContentPosition.top == offset) return;
782 
783  // сбрасываем старую подсветку
784  // так как при прокрутке, мышь может находиться над окном
786 
787  mContentPosition.top = offset;
788  }
789  else
790  {
791  if (mContentSize.width <= 0) return;
792 
793  int offset = mContentPosition.left;
794  if (_rel < 0) offset += mSizeItem.width;
795  else offset -= mSizeItem.width;
796 
797  if (offset >= mContentSize.width - _getClientWidget()->getWidth()) offset = mContentSize.width - _getClientWidget()->getWidth();
798  else if (offset < 0) offset = 0;
799 
800  if (mContentPosition.left == offset) return;
801 
802  // сбрасываем старую подсветку
803  // так как при прокрутке, мышь может находиться над окном
805 
806  mContentPosition.left = offset;
807  }
808 
809  setContentPosition(mContentPosition);
810 
811  // заново ищем и подсвечиваем айтем
812  if (!mNeedDrop)
814 
815  if (nullptr != mVScroll) mVScroll->setScrollPosition(mContentPosition.top);
816  if (nullptr != mHScroll) mHScroll->setScrollPosition(mContentPosition.left);
817  }
818 
819  void ItemBox::setContentPosition(const IntPoint& _point)
820  {
821  mContentPosition = _point;
822 
823  int old = mFirstVisibleIndex;
824 
825  if (mAlignVert)
826  {
827  mFirstVisibleIndex = mContentPosition.top / mSizeItem.height;
828  mFirstOffsetIndex = mContentPosition.top % mSizeItem.height;
829  }
830  else
831  {
832  mFirstVisibleIndex = mContentPosition.left / mSizeItem.width;
833  mFirstOffsetIndex = mContentPosition.left % mSizeItem.width;
834  }
835 
836  _updateAllVisible(old != mFirstVisibleIndex);
837  _resetContainer(true);
838  }
839 
841  {
842  _updateAllVisible(true);
843  }
844 
846  {
847  endDrop(true);
848  }
849 
850  size_t ItemBox::calcIndexByWidget(Widget* _widget)
851  {
852  return *_widget->_getInternalData<size_t>() + (mFirstVisibleIndex * mCountItemInLine);
853  }
854 
855  IntSize ItemBox::getContentSize()
856  {
857  return mContentSize;
858  }
859 
860  IntPoint ItemBox::getContentPosition()
861  {
862  return mContentPosition;
863  }
864 
865  IntSize ItemBox::getViewSize() const
866  {
867  return _getClientWidget()->getSize();
868  }
869 
870  void ItemBox::eraseContent()
871  {
872  updateMetrics();
873  }
874 
875  size_t ItemBox::getHScrollPage()
876  {
877  return mSizeItem.width;
878  }
879 
880  size_t ItemBox::getVScrollPage()
881  {
882  return mSizeItem.height;
883  }
884 
885  Align ItemBox::getContentAlign()
886  {
887  return Align::Default;
888  }
889 
890  IntRect ItemBox::_getClientAbsoluteRect()
891  {
892  return _getClientWidget()->getAbsoluteRect();
893  }
894 
895  Widget* ItemBox::_getClientWidget()
896  {
897  return mWidgetClient == nullptr ? this : mWidgetClient;
898  }
899 
900  const Widget* ItemBox::_getClientWidget() const
901  {
902  return mWidgetClient == nullptr ? this : mWidgetClient;
903  }
904 
905 } // namespace MyGUI