MyGUI  3.0.1
MyGUI_ListCtrl.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_ListCtrl.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  mIndexSelect(ITEM_NONE),
39  mIndexActive(ITEM_NONE),
40  mIndexAccept(ITEM_NONE),
41  mIndexRefuse(ITEM_NONE),
42  mIsFocus(false),
43  mItemDrag(nullptr),
44  mScrollViewPage(1)
45  {
47  }
48 
49  void ListCtrl::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name)
50  {
51  Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name);
52 
53  initialiseWidgetSkin(_info);
54  }
55 
57  {
58  shutdownWidgetSkin();
59  }
60 
61  size_t ListCtrl::getHScrollPage()
62  {
63  return mScrollViewPage;
64  }
65 
66  size_t ListCtrl::getVScrollPage()
67  {
68  return mScrollViewPage;
69  }
70 
72  {
73  shutdownWidgetSkin();
75  initialiseWidgetSkin(_info);
76  }
77 
78  void ListCtrl::initialiseWidgetSkin(ResourceSkin* _info)
79  {
80  // нам нужен фокус клавы
81  mNeedKeyFocus = true;
82  mDragLayer = "DragAndDrop";
83 
84  const MapString& properties = _info->getProperties();
85  if (!properties.empty())
86  {
87  MapString::const_iterator iter = properties.end();
88  iter = properties.find("DragLayer");
89  if (iter != properties.end()) mDragLayer = iter->second;
90  }
91 
92  for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter)
93  {
94  if (*(*iter)->_getInternalData<std::string>() == "VScroll")
95  {
96  MYGUI_DEBUG_ASSERT( ! mVScroll, "widget already assigned");
97  mVScroll = (*iter)->castType<VScroll>();
99  }
100  if (*(*iter)->_getInternalData<std::string>() == "HScroll")
101  {
102  MYGUI_DEBUG_ASSERT( ! mHScroll, "widget already assigned");
103  mHScroll = (*iter)->castType<HScroll>();
105  }
106  else if (*(*iter)->_getInternalData<std::string>() == "Client")
107  {
108  MYGUI_DEBUG_ASSERT( ! mWidgetClient, "widget already assigned");
109  mWidgetClient = (*iter);
113  }
114  }
115  // сли нет скрола, то клиенская зона не обязательно
116  //MYGUI_ASSERT(nullptr != mWidgetClient, "Child Widget Client not found in skin (ListCtrl must have Client) skin ='" << _info->getSkinName() << "'");
117 
118  // подписываем клиент для драгэндропа
120 
122  }
123 
124  void ListCtrl::shutdownWidgetSkin()
125  {
126  mVScroll = nullptr;
127  mHScroll = nullptr;
128  mClient = nullptr;
129  mWidgetClient = nullptr;
130  }
131 
132  void ListCtrl::setPosition(const IntPoint& _point)
133  {
134  Base::setPosition(_point);
135  }
136 
137  void ListCtrl::setSize(const IntSize& _size)
138  {
139  Base::setSize(_size);
141  }
142 
143  void ListCtrl::setCoord(const IntCoord& _coord)
144  {
145  Base::setCoord(_coord);
147  }
148 
150  {
151  updateMetrics();
152 
155 
156  _updateAllVisible(ITEM_NONE, true, true);
157  _resetContainer(true);
158  }
159 
160  void ListCtrl::_updateAllVisible(size_t _index, bool _needUpdateContetntSize, bool _update)
161  {
162 
163  bool change = false;
164 
165  int top = 0;
166  size_t widget_index = 0;
167 
168  for (size_t index=0; index<mItemsInfo.size(); ++index)
169  {
170  ItemDataInfo& info = mItemsInfo[index];
171 
172  // айтем сверху не виден
173  if ((top + info.size.height) < (mContentPosition.top))
174  {
175  }
176  // айтем снизу и не виден
177  else if (top > ((mContentPosition.top) + _getClientWidget()->getHeight()))
178  {
179  }
180  // айтем встрял в видимость
181  else
182  {
183  Widget* item = getItemWidget(widget_index);
184  widget_index++;
185 
186  if (index == _index || ITEM_NONE == _index)
187  {
188  item->_setInternalData((size_t)index);
189 
190  item->setPosition(-mContentPosition.left, top - (mContentPosition.top));
191  item->setVisible(true);
192 
193  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, _update, false);
194 
195  IntCoord coord(IntPoint(), info.size);
196  requestDrawItem(this, item, data, coord);
197 
198  if (info.size != coord.size())
199  change = true;
200 
201  info.size = coord.size();
202  item->setSize(mClient->getWidth()/*mContentSize.width*/, info.size.height);
203  }
204 
205  }
206 
207  top += info.size.height;
208  }
209 
210  // если виджеты еще есть, то их надо скрыть
211  while (widget_index < mVectorItems.size())
212  {
213  Widget* item = mVectorItems[widget_index];
214  widget_index ++;
215 
216  item->setVisible(false);
217  item->_setInternalData((size_t)ITEM_NONE);
218  }
219 
220  if (change && _needUpdateContetntSize)
221  {
222  updateMetrics();
223 
226  }
227  }
228 
230  {
231  // еще нет такого виджета, нуно создать
232  if (_index == mVectorItems.size())
233  {
234 
235  Widget* item = _getClientWidget()->createWidget<Widget>("Default", IntCoord(), Align::Default);
236 
237  // вызываем запрос на создание виджета
238  requestCreateWidgetItem(this, item);
239 
249 
250  mVectorItems.push_back(item);
251  }
252 
253  // запрашивать только последовательно
254  MYGUI_ASSERT_RANGE(_index, mVectorItems.size(), "ListCtrl::getItemWidget");
255 
256  return mVectorItems[_index];
257  }
258 
259  void ListCtrl::onMouseWheel(int _rel)
260  {
261  notifyMouseWheel(nullptr, _rel);
262 
263  Base::onMouseWheel(_rel);
264  }
265 
267  {
268  mIsFocus = true;
269  setState("pushed");
270 
271  Base::onKeySetFocus(_old);
272  }
273 
275  {
276  mIsFocus = false;
277  setState("normal");
278 
279  Base::onKeyLostFocus(_new);
280  }
281 
283  {
284  // сбрасываем старую подсветку
285  if (mIndexActive != ITEM_NONE)
286  {
287  //size_t start = (size_t)mFirstVisibleIndex;
288  size_t index = mIndexActive;
289  mIndexActive = ITEM_NONE;
290 
291  //FIXME потом только один попробовать обновить
292  _updateAllVisible(index, true, false);
293 
294  // если видим, то обновляем
295  /*if ((mIndexActive >= start) && (mIndexActive < (start + mVectorItems.size())))
296  {
297  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
298 
299  IntCoord coord(IntPoint(), mItemsInfo[index].size);
300 
301  requestDrawItem(this, mVectorItems[mIndexActive - start], data, coord);
302 
303  mItemsInfo[index].size = coord.size();
304 
305  }*/
306  }
307  }
308 
310  {
311  MYGUI_DEBUG_ASSERT(mIndexActive == ITEM_NONE, "use : resetCurrentActiveItem() before findCurrentActiveItem()");
312 
314 
315  // сначала проверяем клиентскую зону
316  const IntRect& rect = _getClientWidget()->getAbsoluteRect();
317  if ((point.left < rect.left) || (point.left > rect.right) || (point.top < rect.top) || (point.top > rect.bottom))
318  {
319  return;
320  }
321 
322  for (size_t pos=0; pos<mVectorItems.size(); ++pos)
323  {
324  Widget* item = mVectorItems[pos];
325  const IntRect& abs_rect = item->getAbsoluteRect();
326  if ((point.left>= abs_rect.left) && (point.left <= abs_rect.right) && (point.top>= abs_rect.top) && (point.top <= abs_rect.bottom))
327  {
328 
329  size_t index = calcIndexByWidget(item);
330  // при переборе индекс может быть больше, так как может создасться сколько угодно
331  if (index < mItemsInfo.size())
332  {
333 
334  mIndexActive = index;
335  //FIXME потом только один попробовать обновить
336  _updateAllVisible(index, true, false);
337 
338  /*IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
339  IntCoord coord(IntPoint(), mItemsInfo[index].size);
340  requestDrawItem(this, item, data, coord);
341  mItemsInfo[index].size = coord.size();*/
342 
343  }
344 
345  break;
346  }
347  }
348  }
349 
350  void ListCtrl::_requestGetContainer(Widget* _sender, Widget*& _container, size_t& _index)
351  {
352  if (_sender == _getClientWidget())
353  {
354  _container = this;
355  _index = ITEM_NONE;
356  }
357  else
358  {
359  size_t index = calcIndexByWidget(_sender);
360  if (index < mItemsInfo.size())
361  {
362  _container = this;
363  _index = index;
364  }
365  }
366  }
367 
368  void ListCtrl::_setContainerItemInfo(size_t _index, bool _set, bool _accept)
369  {
370  if (_index == ITEM_NONE) return;
371  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListCtrl::_setContainerItemInfo");
372 
373  mIndexAccept = (_set && _accept ) ? _index : ITEM_NONE;
374  mIndexRefuse = (_set && !_accept) ? _index : ITEM_NONE;
375 
376  //FIXME потом только один попробовать обновить
377  _updateAllVisible(_index, true, false);
378 
379  /*size_t start = (size_t)mFirstVisibleIndex;
380  if ((_index >= start) && (_index < (start + mVectorItems.size())))
381  {
382 
383  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
384 
385  IntCoord coord(IntPoint(), mItemsInfo[_index].size);
386 
387  requestDrawItem(this, mVectorItems[_index - start], data, coord);
388 
389  mItemsInfo[_index].size = coord.size();
390 
391  }*/
392  }
393 
394  void ListCtrl::setItemDataAt(size_t _index, Any _data)
395  {
396  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListCtrl::setItemData");
397  mItemsInfo[_index].data = _data;
398 
399  //FIXME потом только один попробовать обновить
400  _updateAllVisible(_index, true, true);
401 
402  /*size_t start = (size_t)mFirstVisibleIndex;
403  if ((_index >= start) && (_index < (start + mVectorItems.size())))
404  {
405  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
406  IntCoord coord(IntPoint(), mItemsInfo[_index].size);
407  requestDrawItem(this, mVectorItems[_index - start], data, coord);
408  mItemsInfo[_index].size = coord.size();
409  }*/
410 
411  _resetContainer(true);
412  }
413 
414  void ListCtrl::insertItemAt(size_t _index, Any _data)
415  {
416  MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "ListCtrl::insertItemAt");
417  if (_index == ITEM_NONE) _index = mItemsInfo.size();
418 
419  _resetContainer(false);
420 
422 
423  mItemsInfo.insert(mItemsInfo.begin() + _index, ItemDataInfo(_data));
424 
425  // расчитываем новый индекс выделения
426  if (mIndexSelect != ITEM_NONE)
427  {
428  if (mIndexSelect >= _index)
429  {
430  mIndexSelect ++;
431  }
432  }
433 
436 
438 
439  _updateAllVisible(ITEM_NONE, true, true);
440  }
441 
442  void ListCtrl::removeItemAt(size_t _index)
443  {
444  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListCtrl::removeItemAt");
445 
446  _resetContainer(false);
448 
449  mItemsInfo.erase(mItemsInfo.begin() + _index);
450 
451  // расчитываем новый индекс выделения
452  if (mIndexSelect != ITEM_NONE)
453  {
454  if (mItemsInfo.empty())
455  {
456  mIndexSelect = ITEM_NONE;
457  }
458  else if ((mIndexSelect > _index) || (mIndexSelect == mItemsInfo.size()))
459  {
460  mIndexSelect --;
461  }
462  }
463 
466 
468 
469  _updateAllVisible(ITEM_NONE, true, true);
470  }
471 
473  {
474  if (0 == mItemsInfo.size()) return;
475  _resetContainer(false);
476 
477  mItemsInfo.clear();
478 
479  mIndexSelect = ITEM_NONE;
480  mIndexActive = ITEM_NONE;
481 
484 
485  _updateAllVisible(ITEM_NONE, true, true);
486  }
487 
488  void ListCtrl::redrawItemAt(size_t _index)
489  {
490  MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListCtrl::redrawItemAt");
491 
492  //FIXME потом только один попробовать обновить
493  _updateAllVisible(_index, true, true);
494 
495  /*size_t start = (size_t)mFirstVisibleIndex;
496  if ((_index >= start) && (_index < (start + mVectorItems.size())))
497  {
498  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false);
499  IntCoord coord(IntPoint(), mItemsInfo[_index].size);
500  requestDrawItem(this, mVectorItems[_index - start], data, coord);
501  mItemsInfo[_index].size = coord.size();
502  }*/
503  }
504 
505  void ListCtrl::setIndexSelected(size_t _index)
506  {
507  MYGUI_ASSERT_RANGE_AND_NONE(_index, mItemsInfo.size(), "ListCtrl::setIndexSelected");
508  if (_index == mIndexSelect) return;
509 
510  //size_t start = (size_t)mFirstVisibleIndex;
511 
512  // сбрасываем старое выделение
513  if (mIndexSelect != ITEM_NONE)
514  {
515 
516  size_t index = mIndexSelect;
517  mIndexSelect = ITEM_NONE;
518 
519  //FIXME потом только один попробовать обновить
520  _updateAllVisible(index, true, false);
521 
522  /*if ((index >= start) && (index < (start + mVectorItems.size())))
523  {
524  IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
525  IntCoord coord(IntPoint(), mItemsInfo[index].size);
526  requestDrawItem(this, mVectorItems[index - start], data, coord);
527  mItemsInfo[index].size = coord.size();
528  }*/
529  }
530 
531  mIndexSelect = _index;
532  if (mIndexSelect != ITEM_NONE)
533  {
534 
535  //FIXME потом только один попробовать обновить
536  _updateAllVisible(_index, true, false);
537 
538  /*if ((_index >= start) && (_index < (start + mVectorItems.size())))
539  {
540  IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
541  IntCoord coord(IntPoint(), mItemsInfo[_index].size);
542  requestDrawItem(this, mVectorItems[_index - start], data, coord);
543  mItemsInfo[_index].size = coord.size();
544  }*/
545  }
546 
547  }
548 
550  {
551  size_t index = getIndexByWidget(_sender);
552 
553  eventSelectItemAccept(this, index);
554  }
555 
557  {
559  }
560 
562  {
564  }
565 
567  {
568  MYGUI_ASSERT(_widget, "ListCtrl::getIndexByWidget : Widget == nullptr");
569  if (_widget == _getClientWidget()) return ITEM_NONE;
570  MYGUI_ASSERT(_widget->getParent() == _getClientWidget(), "ListCtrl::getIndexByWidget : Widget is not child");
571 
572  size_t index = calcIndexByWidget(_widget);
573  MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ListCtrl::getIndexByWidget");
574 
575  return index;
576  }
577 
579  {
580  for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
581  {
582  if ((*iter)->isVisible())
583  {
584  if ((*iter)->getAbsoluteRect().inside(_point))
585  {
586  return getIndexByWidget(*iter);
587  }
588  }
589  }
590  return ITEM_NONE;
591  }
592 
593  void ListCtrl::_resetContainer(bool _update)
594  {
595  // обязательно у базового
596  Base::_resetContainer(_update);
597 
598  if ( ! _update)
599  {
601  for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
602  {
603  instance.unlinkFromUnlinkers(*iter);
604  }
605  }
606  }
607 
609  {
610  for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter)
611  {
612  if ((*iter)->isVisible())
613  {
614  size_t index = getIndexByWidget(*iter);
615 
616  if (index == _index) return (*iter);
617  }
618  }
619  return nullptr;
620  }
621 
622  void ListCtrl::onMouseButtonPressed(int _left, int _top, MouseButton _id)
623  {
624  Base::onMouseButtonPressed(_left, _top, _id);
625  }
626 
627  void ListCtrl::onMouseButtonReleased(int _left, int _top, MouseButton _id)
628  {
629  Base::onMouseButtonReleased(_left, _top, _id);
630  }
631 
632  void ListCtrl::onMouseDrag(int _left, int _top)
633  {
634  Base::onMouseDrag(_left, _top);
635  }
636 
638  {
639  if (mItemDrag) mItemDrag->setVisible(false);
640  }
641 
643  {
644  if (nullptr == mItemDrag)
645  {
646  // спрашиваем размер иконок
647  IntCoord coord(0, 0, 50, 50);
648 
649  //requestCoordItem(this, coord, true);
650 
651  mPointDragOffset = coord.point();
652 
653  // создаем и запрашиваем детей
654  mItemDrag = Gui::getInstance().createWidget<Widget>("Default", IntCoord(0, 0, coord.width, coord.height), Align::Default, mDragLayer);
655  requestCreateWidgetItem(this, mItemDrag);
656  }
657 
659 
660  mItemDrag->setPosition(point.left - mClickInWidget.left + mPointDragOffset.left, point.top - mClickInWidget.top + mPointDragOffset.top);
661  mItemDrag->setVisible(true);
662  }
663 
665  {
666  IBDrawItemInfo data;
667  data.drop_accept = _state.accept;
668  data.drop_refuse = _state.refuse;
669 
670  data.select = false;
671  data.active = false;
672 
673  data.index = mDropSenderIndex;
674  data.update = _state.update;
675  data.drag = true;
676 
677  IntCoord coord;
678 
679  requestDrawItem(this, mItemDrag, data, coord);
680 
681  }
682 
683  void ListCtrl::notifyMouseDrag(Widget* _sender, int _left, int _top)
684  {
685  mouseDrag();
686  }
687 
688  void ListCtrl::notifyMouseButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id)
689  {
690  mouseButtonPressed(_id);
691 
692  if ( MouseButton::Left == _id)
693  {
694  size_t old = mIndexSelect;
695 
696  if (_sender == _getClientWidget())
697  {
698  // сбрасываем выделение
700  }
701  else
702  {
703  // индекс отправителя
705 
706  // выделенный елемент
708  }
709 
710  // смещение внутри виджета, куда кликнули мышкой
712 
713  // отсылаем событие
714  eventMouseItemActivate(this, mIndexSelect);
715  // смену позиции отсылаем только при реальном изменении
716  if (old != mIndexSelect) eventChangeItemPosition(this, mIndexSelect);
717  }
718 
720  }
721 
722  void ListCtrl::notifyMouseButtonReleased(Widget* _sender, int _left, int _top, MouseButton _id)
723  {
724  mouseButtonReleased(_id);
726  }
727 
728  void ListCtrl::notifyRootMouseChangeFocus(Widget* _sender, bool _focus)
729  {
730  size_t index = calcIndexByWidget(_sender);
731  if (_focus)
732  {
733  MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ListCtrl::notifyRootMouseChangeFocus");
734 
735  // сбрасываем старый
736  if (mIndexActive != ITEM_NONE)
737  {
738  size_t old_index = mIndexActive;
739  mIndexActive = ITEM_NONE;
740 
741  //FIXME потом только один попробовать обновить
742  _updateAllVisible(old_index, true, false);
743 
744  /*IBDrawItemInfo data(old_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
745  IntCoord coord(IntPoint(), mItemsInfo[old_index].size);
746  requestDrawItem(this, mVectorItems[old_index - mFirstVisibleIndex], data, coord);
747  mItemsInfo[old_index].size = coord.size();*/
748 
749  }
750 
751  mIndexActive = index;
752 
753  //FIXME потом только один попробовать обновить
754  _updateAllVisible(index, true, false);
755 
756  /*IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
757  IntCoord coord(IntPoint(), mItemsInfo[index].size);
758  requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data, coord);
759  mItemsInfo[index].size = coord.size();*/
760 
761  }
762  else
763  {
764  // при сбросе виджет может быть уже скрыт, и соответсвенно отсутсвовать индекс
765  // сбрасываем индекс, только если мы и есть актив
766  if (index < mItemsInfo.size() && mIndexActive == index)
767  {
768  mIndexActive = ITEM_NONE;
769 
770  //FIXME потом только один попробовать обновить
771  _updateAllVisible(index, true, false);
772 
773  /*IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false);
774  IntCoord coord(IntPoint(), mItemsInfo[index].size);
775  requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data, coord);
776  mItemsInfo[index].size = coord.size();*/
777 
778  }
779  }
780  }
781 
783  {
784  IntSize size;
785 
786  for (VectorItemInfo::const_iterator item=mItemsInfo.begin(); item!=mItemsInfo.end(); ++item)
787  {
788  if (size.width < item->size.width)
789  size.width = item->size.width;
790  size.height += item->size.height;
791  }
792 
793  mContentSize = size;
794  }
795 
796  void ListCtrl::notifyScrollChangePosition(VScroll* _sender, size_t _index)
797  {
798  if (_sender == mVScroll)
799  {
800  mContentPosition.top = (int)_index;
801  }
802  else if (_sender == mHScroll)
803  {
804  mContentPosition.left = (int)_index;
805  }
806 
807  setContentPosition(mContentPosition);
808  }
809 
810  void ListCtrl::setContentPosition(const IntPoint& _point)
811  {
812  mContentPosition = _point;
813 
814  _updateAllVisible(ITEM_NONE, true, true);
815  _resetContainer(true);
816  }
817 
818  void ListCtrl::notifyMouseWheel(Widget* _sender, int _rel)
819  {
820  if (mContentSize.height <= 0) return;
821 
822  int offset = mContentPosition.top;
823  if (_rel < 0) offset += mScrollViewPage;
824  else offset -= mScrollViewPage;
825 
826  if (mContentSize.height <= _getClientWidget()->getHeight()) return;
827 
828  if (offset >= mContentSize.height - _getClientWidget()->getHeight()) offset = mContentSize.height - _getClientWidget()->getHeight();
829  else if (offset < 0) offset = 0;
830 
831  if (mContentPosition.top == offset) return;
832 
833  // сбрасываем старую подсветку
834  // так как при прокрутке, мышь может находиться над окном
836 
837  mContentPosition.top = offset;
838 
839  setContentPosition(mContentPosition);
840 
841  // заново ищем и подсвечиваем айтем
842  if (!mNeedDrop)
844 
845  if (nullptr != mVScroll) mVScroll->setScrollPosition(mContentPosition.top);
846  if (nullptr != mHScroll) mHScroll->setScrollPosition(mContentPosition.left);
847  }
848 
850  {
851  endDrop(true);
852  }
853 
854  IntSize ListCtrl::getContentSize()
855  {
856  return mContentSize;
857  }
858 
859  IntPoint ListCtrl::getContentPosition()
860  {
861  return mContentPosition;
862  }
863 
864  IntSize ListCtrl::getViewSize() const
865  {
866  return _getClientWidget()->getSize();
867  }
868 
869  void ListCtrl::eraseContent()
870  {
871  _updateAllVisible(ITEM_NONE, false, true);
872  updateMetrics();
873  }
874 
875  Align ListCtrl::getContentAlign()
876  {
877  return Align::Default;
878  }
879 
880  Widget* ListCtrl::_getClientWidget()
881  {
882  return mWidgetClient == nullptr ? this : mWidgetClient;
883  }
884 
885  const Widget* ListCtrl::_getClientWidget() const
886  {
887  return mWidgetClient == nullptr ? this : mWidgetClient;
888  }
889 
890 } // namespace MyGUI