MyGUI 3.4.2
MyGUI_ListBox.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_ListBox.h"
9#include "MyGUI_Button.h"
10#include "MyGUI_ScrollBar.h"
11#include "MyGUI_ResourceSkin.h"
12#include "MyGUI_InputManager.h"
13#include "MyGUI_WidgetManager.h"
15
16namespace MyGUI
17{
18
20 mWidgetScroll(nullptr),
21 mActivateOnClick(false),
22 mHeightLine(1),
23 mTopIndex(0),
24 mOffsetTop(0),
25 mRangeIndex(-1),
26 mLastRedrawLine(0),
27 mIndexSelect(ITEM_NONE),
28 mLineActive(ITEM_NONE),
29 mNeedVisibleScroll(true)
30 {
31 }
32
34 {
36
37 // FIXME нам нужен фокус клавы
38 setNeedKeyFocus(true);
39
40 // парсим свойства
41 if (isUserString("SkinLine"))
42 mSkinLine = getUserString("SkinLine");
43
44 if (isUserString("HeightLine"))
45 mHeightLine = utility::parseInt(getUserString("HeightLine"));
46
47 if (mHeightLine < 1)
48 mHeightLine = 1;
49
50 if (getClientWidget() != nullptr)
51 {
56 }
57
59 assignWidget(mWidgetScroll, "VScroll");
60 if (mWidgetScroll != nullptr)
61 {
63 mWidgetScroll->setScrollPage((size_t)mHeightLine);
64 }
65
67 updateLine();
68 }
69
71 {
72 mWidgetScroll = nullptr;
73
75 }
76
78 {
79 notifyMouseWheel(nullptr, _rel);
80
82 }
83
85 {
86 if (getItemCount() == 0)
87 {
90 return;
91 }
92
93 // очень секретный метод, запатентованный механизм движения курсора
94 size_t sel = mIndexSelect;
95
97 {
98 if (sel != 0)
99 {
100 if (sel == ITEM_NONE)
101 sel = 0;
102 else
103 sel --;
104 }
105 }
106 else if (_key == KeyCode::ArrowDown)
107 {
108 if (sel == ITEM_NONE)
109 sel = 0;
110 else
111 sel ++;
112
113 if (sel >= getItemCount())
114 {
115 // старое значение
116 sel = mIndexSelect;
117 }
118 }
119 else if (_key == KeyCode::Home)
120 {
121 sel = 0;
122 }
123 else if (_key == KeyCode::End)
124 {
125 sel = getItemCount() - 1;
126 }
127 else if (_key == KeyCode::PageUp)
128 {
129 if (sel != 0)
130 {
131 if (sel == ITEM_NONE)
132 {
133 sel = 0;
134 }
135 else
136 {
137 size_t page = _getClientWidget()->getHeight() / mHeightLine;
138 if (sel <= page)
139 sel = 0;
140 else
141 sel -= page;
142 }
143 }
144 }
145 else if (_key == KeyCode::PageDown)
146 {
147 if (sel != (getItemCount() - 1))
148 {
149 if (sel == ITEM_NONE)
150 {
151 sel = 0;
152 }
153 else
154 {
155 sel += _getClientWidget()->getHeight() / mHeightLine;
156 if (sel >= getItemCount())
157 sel = getItemCount() - 1;
158 }
159 }
160 }
161 else if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter))
162 {
163 if (sel != ITEM_NONE)
164 {
165 //FIXME нас могут удалить
167
169
171 // выходим, так как изменили колличество строк
172 return;
173 }
174 }
175
176 if (sel != mIndexSelect)
177 {
178 _resetContainer(true);
179
180 if (!isItemVisibleAt(sel))
181 {
183 if (mWidgetScroll != nullptr)
185 }
187
188 // изменилась позиция
189 // FIXME нас могут удалить
190 eventListChangePosition(this, mIndexSelect);
191 }
192
195 }
196
198 {
199 if (mRangeIndex <= 0)
200 return;
201
202 if (mWidgetScroll == nullptr)
203 return;
204
205 int offset = (int)mWidgetScroll->getScrollPosition();
206 if (_rel < 0)
207 offset += mHeightLine;
208 else
209 offset -= mHeightLine;
210
211 if (offset >= mRangeIndex)
212 offset = mRangeIndex;
213 else if (offset < 0)
214 offset = 0;
215
216 if ((int)mWidgetScroll->getScrollPosition() == offset)
217 return;
218
219 mWidgetScroll->setScrollPosition(offset);
220 _setScrollView(offset);
222
223 _resetContainer(true);
224 }
225
227 {
230 }
231
233 {
234 if (MouseButton::Left == _id && !mActivateOnClick)
236
238 }
239
241 {
242 if (mActivateOnClick)
244 }
245
247 {
248 if (mIndexSelect != ITEM_NONE)
249 eventListSelectAccept(this, mIndexSelect);
250 }
251
253 {
255 }
256
258 {
260
261 updateScroll();
262 updateLine();
263 }
264
266 {
268
269 updateScroll();
270 updateLine();
271 }
272
274 {
275 mRangeIndex = (mHeightLine * (int)mItemsInfo.size()) - _getClientWidget()->getHeight();
276
277 if (mWidgetScroll == nullptr)
278 return;
279
280 if ((!mNeedVisibleScroll) || (mRangeIndex < 1) || (mWidgetScroll->getLeft() <= _getClientWidget()->getLeft()))
281 {
282 if (mWidgetScroll->getVisible())
283 {
284 mWidgetScroll->setVisible(false);
285 // увеличиваем клиентскую зону на ширину скрола
286 if (getClientWidget() != nullptr)
288 }
289 }
290 else if (!mWidgetScroll->getVisible())
291 {
292 if (getClientWidget() != nullptr)
294 mWidgetScroll->setVisible(true);
295 }
296
297 mWidgetScroll->setScrollRange(mRangeIndex + 1);
298 mWidgetScroll->setScrollViewPage(_getClientWidget()->getHeight());
299 if (!mItemsInfo.empty())
300 mWidgetScroll->setTrackSize(mWidgetScroll->getLineSize() * _getClientWidget()->getHeight() / mHeightLine / (int)mItemsInfo.size());
301 }
302
304 {
305 // сбрасываем
306 if (_reset)
307 {
308 mOldSize.clear();
309 mLastRedrawLine = 0;
310 _resetContainer(false);
311 }
312
313 // позиция скролла
314 int position = mTopIndex * mHeightLine + mOffsetTop;
315
316 // если высота увеличивалась то добавляем виджеты
317 if (mOldSize.height < mCoord.height)
318 {
319 int height = (int)mWidgetLines.size() * mHeightLine - mOffsetTop;
320
321 // до тех пор, пока не достигнем максимального колличества, и всегда на одну больше
322 while ( (height <= (_getClientWidget()->getHeight() + mHeightLine)) && (mWidgetLines.size() < mItemsInfo.size()) )
323 {
324 // создаем линию
325 Widget* widget = _getClientWidget()->createWidgetT("Button", mSkinLine, 0, height, _getClientWidget()->getWidth(), mHeightLine, Align::Top | Align::HStretch);
326 Button* line = widget->castType<Button>();
327 // подписываемся на всякие там события
328 line->eventMouseButtonPressed += newDelegate(this, &ListBox::notifyMousePressed);
329 line->eventMouseButtonReleased += newDelegate(this, &ListBox::notifyMouseButtonReleased);
330 line->eventMouseButtonClick += newDelegate(this, &ListBox::notifyMouseClick);
331 line->eventMouseButtonDoubleClick += newDelegate(this, &ListBox::notifyMouseDoubleClick);
332 line->eventMouseWheel += newDelegate(this, &ListBox::notifyMouseWheel);
333 line->eventKeyButtonPressed += newDelegate(this, &ListBox::notifyKeyButtonPressed);
334 line->eventKeyButtonReleased += newDelegate(this, &ListBox::notifyKeyButtonReleased);
335 line->eventMouseSetFocus += newDelegate(this, &ListBox::notifyMouseSetFocus);
336 line->eventMouseLostFocus += newDelegate(this, &ListBox::notifyMouseLostFocus);
337 line->_setContainer(this);
338 // присваиваем порядковый номер, для простоты просчета
339 line->_setInternalData((size_t)mWidgetLines.size());
340 // и сохраняем
341 mWidgetLines.push_back(line);
342 height += mHeightLine;
343 }
344
345 // проверяем на возможность не менять положение списка
346 if (position >= mRangeIndex)
347 {
348 // размер всех помещается в клиент
349 if (mRangeIndex <= 0)
350 {
351 // обнуляем, если надо
352 if (position || mOffsetTop || mTopIndex)
353 {
354 position = 0;
355 mTopIndex = 0;
356 mOffsetTop = 0;
357 mLastRedrawLine = 0; // чтобы все перерисовалось
358
359 // выравниваем
360 int offset = 0;
361 for (size_t pos = 0; pos < mWidgetLines.size(); pos++)
362 {
363 mWidgetLines[pos]->setPosition(0, offset);
364 offset += mHeightLine;
365 }
366 }
367 }
368 else
369 {
370 // прижимаем список к нижней границе
371 int count = _getClientWidget()->getHeight() / mHeightLine;
372 mOffsetTop = mHeightLine - (_getClientWidget()->getHeight() % mHeightLine);
373
374 if (mOffsetTop == mHeightLine)
375 {
376 mOffsetTop = 0;
377 count --;
378 }
379
380 int top = (int)mItemsInfo.size() - count - 1;
381
382 // выравниваем
383 int offset = 0 - mOffsetTop;
384 for (size_t pos = 0; pos < mWidgetLines.size(); pos++)
385 {
386 mWidgetLines[pos]->setPosition(0, offset);
387 offset += mHeightLine;
388 }
389
390 // высчитываем положение, должно быть максимальным
391 position = top * mHeightLine + mOffsetTop;
392
393 // если индех изменился, то перерисовываем линии
394 if (top != mTopIndex)
395 {
396 mTopIndex = top;
398 }
399 }
400 }
401
402 // увеличился размер, но прокрутки вниз небыло, обновляем линии снизу
403 _redrawItemRange(mLastRedrawLine);
404
405 } // if (old_cy < mCoord.height)
406
407 // просчитываем положение скролла
408 if (mWidgetScroll != nullptr)
409 mWidgetScroll->setScrollPosition(position);
410
411 mOldSize.width = mCoord.width;
412 mOldSize.height = mCoord.height;
413 }
414
416 {
417 // перерисовываем линии, только те, что видны
418 size_t pos = _start;
419 for (; pos < mWidgetLines.size(); pos++)
420 {
421 // индекс в нашем массиве
422 size_t index = pos + (size_t)mTopIndex;
423
424 // не будем заходить слишком далеко
425 if (index >= mItemsInfo.size())
426 {
427 // запоминаем последнюю перерисованную линию
428 mLastRedrawLine = pos;
429 break;
430 }
431 if (mWidgetLines[pos]->getTop() > _getClientWidget()->getHeight())
432 {
433 // запоминаем последнюю перерисованную линию
434 mLastRedrawLine = pos;
435 break;
436 }
437
438 // если был скрыт, то покажем
439 mWidgetLines[pos]->setVisible(true);
440 // обновляем текст
441 mWidgetLines[pos]->setCaption(mItemsInfo[index].first);
442
443 // если нужно выделить ,то выделим
444 static_cast<Button*>(mWidgetLines[pos])->setStateSelected(index == mIndexSelect);
445 }
446
447 // если цикл весь прошли, то ставим максимальную линию
448 if (pos >= mWidgetLines.size())
449 {
450 mLastRedrawLine = pos;
451 }
452 else
453 {
454 //Widget* focus = InputManager::getInstance().getMouseFocusWidget();
455 for (; pos < mWidgetLines.size(); pos++)
456 {
457 static_cast<Button*>(mWidgetLines[pos])->setStateSelected(false);
458 static_cast<Button*>(mWidgetLines[pos])->setVisible(false);
459 //if (focus == mWidgetLines[pos]) InputManager::getInstance()._unlinkWidget(focus);
460 }
461 }
462 }
463
464 // перерисовывает индекс
466 {
467 // невидно
468 if (_index < (size_t)mTopIndex)
469 return;
470 _index -= (size_t)mTopIndex;
471 // тоже невидно
472 if (_index >= mLastRedrawLine)
473 return;
474
475 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListBox::_redrawItem");
476 // перерисовываем
477 mWidgetLines[_index]->setCaption(mItemsInfo[_index + mTopIndex].first);
478 }
479
481 {
482 MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "ListBox::insertItemAt");
483 if (_index == ITEM_NONE)
484 _index = mItemsInfo.size();
485
486 // вставляем физически
487 mItemsInfo.insert(mItemsInfo.begin() + _index, PairItem(_name, _data));
488
489 // если надо, то меняем выделенный элемент
490 if ((mIndexSelect != ITEM_NONE) && (_index <= mIndexSelect))
491 mIndexSelect++;
492
493 // строка, до первого видимого элемента
494 if ((_index <= (size_t)mTopIndex) && (mRangeIndex > 0))
495 {
496 mTopIndex ++;
497 // просчитываем положение скролла
498 if (mWidgetScroll != nullptr)
499 {
500 mWidgetScroll->setScrollRange(mWidgetScroll->getScrollRange() + mHeightLine);
501 if (!mItemsInfo.empty())
502 mWidgetScroll->setTrackSize( mWidgetScroll->getLineSize() * _getClientWidget()->getHeight() / mHeightLine / (int)mItemsInfo.size() );
503 mWidgetScroll->setScrollPosition(mTopIndex * mHeightLine + mOffsetTop);
504 }
505 mRangeIndex += mHeightLine;
506 }
507 else
508 {
509 // высчитывам положение строки
510 int offset = ((int)_index - mTopIndex) * mHeightLine - mOffsetTop;
511
512 // строка, после последнего видимого элемента, плюс одна строка (потому что для прокрутки нужно на одну строчку больше)
513 if (_getClientWidget()->getHeight() < (offset - mHeightLine))
514 {
515 // просчитываем положение скролла
516 if (mWidgetScroll != nullptr)
517 {
518 mWidgetScroll->setScrollRange(mWidgetScroll->getScrollRange() + mHeightLine);
519 if (!mItemsInfo.empty())
520 mWidgetScroll->setTrackSize( mWidgetScroll->getLineSize() * _getClientWidget()->getHeight() / mHeightLine / (int)mItemsInfo.size() );
521 mWidgetScroll->setScrollPosition(mTopIndex * mHeightLine + mOffsetTop);
522 }
523 mRangeIndex += mHeightLine;
524
525 // строка в видимой области
526 }
527 else
528 {
529 // обновляем все
530 updateScroll();
531 updateLine(true);
532
533 // позже сюда еще оптимизацию по колличеству перерисовок
534 }
535 }
536 }
537
539 {
540 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListBox::removeItemAt");
541
542 // удяляем физически строку
543 mItemsInfo.erase(mItemsInfo.begin() + _index);
544
545 // если надо, то меняем выделенный элемент
546 if (mItemsInfo.empty()) mIndexSelect = ITEM_NONE;
547 else if (mIndexSelect != ITEM_NONE)
548 {
549 if (_index < mIndexSelect)
550 mIndexSelect--;
551 else if ((_index == mIndexSelect) && (mIndexSelect == (mItemsInfo.size())))
552 mIndexSelect--;
553 }
554
555 // если виджетов стало больше , то скрываем крайний
556 if (mWidgetLines.size() > mItemsInfo.size())
557 {
558 mWidgetLines[mItemsInfo.size()]->setVisible(false);
559 }
560
561 // строка, до первого видимого элемента
562 if (_index < (size_t)mTopIndex)
563 {
564 mTopIndex --;
565 // просчитываем положение скролла
566 if (mWidgetScroll != nullptr)
567 {
568 mWidgetScroll->setScrollRange(mWidgetScroll->getScrollRange() - mHeightLine);
569 if (!mItemsInfo.empty())
570 mWidgetScroll->setTrackSize( mWidgetScroll->getLineSize() * _getClientWidget()->getHeight() / mHeightLine / (int)mItemsInfo.size() );
571 mWidgetScroll->setScrollPosition(mTopIndex * mHeightLine + mOffsetTop);
572 }
573 mRangeIndex -= mHeightLine;
574 }
575 else
576 {
577 // высчитывам положение удаляемой строки
578 int offset = ((int)_index - mTopIndex) * mHeightLine - mOffsetTop;
579
580 // строка, после последнего видимого элемента
581 if (_getClientWidget()->getHeight() < offset)
582 {
583 // просчитываем положение скролла
584 if (mWidgetScroll != nullptr)
585 {
586 mWidgetScroll->setScrollRange(mWidgetScroll->getScrollRange() - mHeightLine);
587 if (!mItemsInfo.empty())
588 mWidgetScroll->setTrackSize( mWidgetScroll->getLineSize() * _getClientWidget()->getHeight() / mHeightLine / (int)mItemsInfo.size() );
589 mWidgetScroll->setScrollPosition(mTopIndex * mHeightLine + mOffsetTop);
590 }
591 mRangeIndex -= mHeightLine;
592
593 // строка в видимой области
594 }
595 else
596 {
597 // обновляем все
598 updateScroll();
599 updateLine(true);
600
601 // позже сюда еще оптимизацию по колличеству перерисовок
602 }
603 }
604 }
605
607 {
608 MYGUI_ASSERT_RANGE_AND_NONE(_index, mItemsInfo.size(), "ListBox::setIndexSelected");
609 if (mIndexSelect != _index)
610 {
611 _selectIndex(mIndexSelect, false);
612 _selectIndex(_index, true);
613 mIndexSelect = _index;
614 }
615 }
616
618 {
619 if (_index == ITEM_NONE)
620 return;
621 // не видно строки
622 if (_index < (size_t)mTopIndex)
623 return;
624 // высчитывам положение строки
625 int offset = ((int)_index - mTopIndex) * mHeightLine - mOffsetTop;
626 // строка, после последнего видимого элемента
627 if (_getClientWidget()->getHeight() < offset)
628 return;
629
630 size_t index = _index - mTopIndex;
631 if (index < mWidgetLines.size())
632 static_cast<Button*>(mWidgetLines[index])->setStateSelected(_select);
633 }
634
636 {
637 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListBox::beginToItemAt");
638 if (mRangeIndex <= 0)
639 return;
640
641 int offset = (int)_index * mHeightLine;
642 if (offset >= mRangeIndex) offset = mRangeIndex;
643
644 if (mWidgetScroll != nullptr)
645 {
646 if ((int)mWidgetScroll->getScrollPosition() == offset)
647 return;
648 mWidgetScroll->setScrollPosition(offset);
649 }
650 notifyScrollChangePosition(nullptr, offset);
651 }
652
653 // видим ли мы элемент, полностью или нет
655 {
656 // если элемента нет, то мы его не видим (в том числе когда их вообще нет)
657 if (_index >= mItemsInfo.size())
658 return false;
659 // если скрола нет, то мы палюбак видим
660 if (mRangeIndex <= 0)
661 return true;
662
663 // строка, до первого видимого элемента
664 if (_index < (size_t)mTopIndex)
665 return false;
666
667 // строка это верхний выделенный
668 if (_index == (size_t)mTopIndex)
669 {
670 if ((mOffsetTop != 0) && (_fill))
671 return false; // нам нужна полностью видимость
672 return true;
673 }
674
675 // высчитывам положение строки
676 int offset = ((int)_index - mTopIndex) * mHeightLine - mOffsetTop;
677
678 // строка, после последнего видимого элемента
679 if (_getClientWidget()->getHeight() < offset)
680 return false;
681
682 // если мы внизу и нам нужен целый
683 if (_getClientWidget()->getHeight() < (offset + mHeightLine) && _fill)
684 return false;
685
686 return true;
687 }
688
690 {
691 mTopIndex = 0;
692 mIndexSelect = ITEM_NONE;
693 mOffsetTop = 0;
694
695 mItemsInfo.clear();
696
697 int offset = 0;
698 for (size_t pos = 0; pos < mWidgetLines.size(); pos++)
699 {
700 mWidgetLines[pos]->setVisible(false);
701 mWidgetLines[pos]->setPosition(0, offset);
702 offset += mHeightLine;
703 }
704
705 // обновляем все
706 updateScroll();
707 updateLine(true);
708 }
709
711 {
712 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListBox::setItemNameAt");
713 mItemsInfo[_index].first = _name;
715 }
716
718 {
719 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListBox::setItemDataAt");
720 mItemsInfo[_index].second = _data;
722 }
723
725 {
726 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ListBox::getItemNameAt");
727 return mItemsInfo[_index].first;
728 }
729
731 {
732
733#if MYGUI_DEBUG_MODE == 1
734 MYGUI_ASSERT_RANGE(*_sender->_getInternalData<size_t>(), mWidgetLines.size(), "ListBox::notifyMouseSetFocus");
735#endif
736
737 mLineActive = *_sender->_getInternalData<size_t>();
738 eventListMouseItemFocus(this, mLineActive);
739 }
740
742 {
743 if ((nullptr == _new) || (_new->getParent() != _getClientWidget()))
744 {
745 mLineActive = ITEM_NONE;
747 }
748 }
749
751 {
752 MYGUI_ASSERT_RANGE(_index, mWidgetLines.size(), "ListBox::_setItemFocus");
753 static_cast<Button*>(mWidgetLines[_index])->_setMouseFocus(_focus);
754 }
755
757 {
758 if (mNeedVisibleScroll == _visible)
759 return;
760 mNeedVisibleScroll = _visible;
761 updateScroll();
762 }
763
765 {
766 if (mWidgetScroll != nullptr)
767 {
768 if (mWidgetScroll->getScrollRange() > _position)
769 {
770 mWidgetScroll->setScrollPosition(_position);
772 }
773 }
774 }
775
777 {
778 mOffsetTop = ((int)_position % mHeightLine);
779
780 // смещение с отрицательной стороны
781 int offset = 0 - mOffsetTop;
782
783 for (size_t pos = 0; pos < mWidgetLines.size(); pos++)
784 {
785 mWidgetLines[pos]->setPosition(IntPoint(0, offset));
786 offset += mHeightLine;
787 }
788
789 // если индех изменился, то перерисовываем линии
790 int top = ((int)_position / mHeightLine);
791 if (top != mTopIndex)
792 {
793 mTopIndex = top;
795 }
796
797 // прорисовываем все нижние строки, если они появились
798 _redrawItemRange(mLastRedrawLine);
799 }
800
802 {
804 if (ITEM_NONE != mLineActive)
805 eventListMouseItemFocus(this, mLineActive);
806 }
807
809 {
810 MYGUI_ASSERT_RANGE(_index1, mItemsInfo.size(), "ListBox::swapItemsAt");
811 MYGUI_ASSERT_RANGE(_index2, mItemsInfo.size(), "ListBox::swapItemsAt");
812
813 if (_index1 == _index2)
814 return;
815
816 std::swap(mItemsInfo[_index1], mItemsInfo[_index2]);
817
820 }
821
823 {
824 // максимальная высота всех строк
825 int max_height = mItemsInfo.size() * mHeightLine;
826 // видимая высота
828
829 // все строки помещаются
831 {
832 MYGUI_ASSERT(mTopIndex == 0, "mTopIndex == 0");
833 MYGUI_ASSERT(mOffsetTop == 0, "mOffsetTop == 0");
834 int height = 0;
835 for (size_t pos = 0; pos < mWidgetLines.size(); pos++)
836 {
837 if (pos >= mItemsInfo.size())
838 break;
839 MYGUI_ASSERT(mWidgetLines[pos]->getTop() == height, "mWidgetLines[pos]->getTop() == height");
840 height += mWidgetLines[pos]->getHeight();
841 }
842 }
843 }
844
846 {
847 for (size_t pos = 0; pos < mItemsInfo.size(); pos++)
848 {
849 if (mItemsInfo[pos].first == _name)
850 return pos;
851 }
852 return ITEM_NONE;
853 }
854
856 {
857 return (int)((mCoord.height - _getClientWidget()->getHeight()) + (mItemsInfo.size() * mHeightLine));
858 }
859
861 {
862 return mItemsInfo.size();
863 }
864
866 {
868 }
869
871 {
872 return mIndexSelect;
873 }
874
876 {
878 }
879
881 {
883 }
884
886 {
887 if (getItemCount())
888 beginToItemAt(0);
889 }
890
892 {
893 if (getItemCount())
895 }
896
898 {
901 }
902
904 {
905 return isItemVisibleAt(mIndexSelect, _fill);
906 }
907
909 {
910 for (const auto& line : mWidgetLines)
911 {
912 if (line == _item)
913 return *line->_getInternalData<size_t>() + mTopIndex;
914 }
915 return ITEM_NONE;
916 }
917
919 {
920 // обязательно у базового
922
923 if (!_update)
924 {
926 for (const auto& line : mWidgetLines)
927 instance.unlinkFromUnlinkers(line);
928 }
929 }
930
931 void ListBox::setPropertyOverride(const std::string& _key, const std::string& _value)
932 {
933 // не коментировать
934 if (_key == "AddItem")
936 else if (_key == "ActivateOnClick")
937 mActivateOnClick = utility::parseBool(_value);
938 else
939 {
941 return;
942 }
943
945 }
946
948 {
949 // если выделен клиент, то сбрасываем
950 if (_sender == _getClientWidget())
951 {
952 if (mIndexSelect != ITEM_NONE)
953 {
954 _selectIndex(mIndexSelect, false);
955 mIndexSelect = ITEM_NONE;
956 eventListChangePosition(this, mIndexSelect);
957 }
958 eventListMouseItemActivate(this, mIndexSelect);
959
960 // если не клиент, то просчитывам
961 }
962 // ячейка может быть скрыта
963 else if (_sender->getVisible())
964 {
965
966#if MYGUI_DEBUG_MODE == 1
967 MYGUI_ASSERT_RANGE(*_sender->_getInternalData<size_t>(), mWidgetLines.size(), "ListBox::notifyMousePressed");
968 MYGUI_ASSERT_RANGE(*_sender->_getInternalData<size_t>() + mTopIndex, mItemsInfo.size(), "ListBox::notifyMousePressed");
969#endif
970
971 size_t index = *_sender->_getInternalData<size_t>() + mTopIndex;
972
973 if (mIndexSelect != index)
974 {
975 _selectIndex(mIndexSelect, false);
976 _selectIndex(index, true);
977 mIndexSelect = index;
978 eventListChangePosition(this, mIndexSelect);
979 }
980 eventListMouseItemActivate(this, mIndexSelect);
981 }
982
983 _resetContainer(true);
984 }
985
987 {
988 return getItemCount();
989 }
990
992 {
993 addItem(_name);
994 }
995
997 {
999 }
1000
1002 {
1004 }
1005
1007 {
1008 return getItemNameAt(_index);
1009 }
1010
1011 size_t ListBox::getIndexByWidget(Widget* _widget) const
1012 {
1013 if (_widget == getClientWidget())
1014 return ITEM_NONE;
1015 return *_widget->_getInternalData<size_t>() + mTopIndex;
1016 }
1017
1019 {
1021 }
1022
1024 {
1026 }
1027
1029 {
1031 }
1032
1034 {
1036
1038 }
1039
1041 {
1042 mActivateOnClick = activateOnClick;
1043 }
1044
1046 {
1047 if (_index == MyGUI::ITEM_NONE)
1048 return nullptr;
1049
1050 // индекс в нашем массиве
1051 size_t index = _index - (size_t)mTopIndex;
1052
1053 if (index < mWidgetLines.size())
1054 return mWidgetLines[index];
1055 return nullptr;
1056 }
1057
1058} // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_ASSERT_RANGE_INSERT(index, size, owner)
#define MYGUI_ASSERT_RANGE(index, size, owner)
#define MYGUI_ASSERT_RANGE_AND_NONE(index, size, owner)
static AnyEmpty Null
Definition MyGUI_Any.h:59
widget description should be here.
void setStateSelected(bool _value)
Set button selected state.
static LanguageManager & getInstance()
void _setItemNameAt(size_t _index, const UString &_name) override
void addItem(const UString &_name, Any _data=Any::Null)
Add an item to the end of a array.
void notifyMouseWheel(Widget *_sender, int _rel)
void _removeItemAt(size_t _index) override
void updateLine(bool _reset=false)
EventHandle_ListBoxPtrCIBNotifyCellDataRef eventNotifyItem
void beginToItemAt(size_t _index)
Move all elements so specified becomes visible.
void _redrawItem(size_t _index)
size_t _getItemIndex(Widget *_item) const override
void _setScrollView(size_t _position)
void notifyKeyButtonReleased(Widget *_sender, KeyCode _key)
void notifyMousePressed(Widget *_sender, int _left, int _top, MouseButton _id)
void _sendEventChangeScroll(size_t _position)
void setPosition(const IntPoint &_value) override
void setScrollPosition(size_t _position)
Set scroll position.
void notifyMouseButtonReleased(Widget *_sender, int _left, int _top, MouseButton _id)
bool isItemSelectedVisible(bool _fill=true)
Same as ListBox::isItemVisibleAt for selected item.
void _resetContainer(bool _update) override
const UString & _getItemNameAt(size_t _index) const override
bool isItemVisibleAt(size_t _index, bool _fill=true)
const UString & getItemNameAt(size_t _index) const
Get item name from specified position.
void notifyMouseClick(Widget *_sender)
void setActivateOnClick(bool activateOnClick)
void setPropertyOverride(const std::string &_key, const std::string &_value) override
void _addItem(const MyGUI::UString &_name) override
void setScrollVisible(bool _visible)
Set scroll visible when it needed.
void _activateItem(Widget *_sender)
void setSize(const IntSize &_value) override
void _redrawItemRange(size_t _start=0)
void notifyMouseLostFocus(Widget *_sender, Widget *_new)
void shutdownOverride() override
size_t getItemCount() const
Get number of items.
void notifyScrollChangePosition(ScrollBar *_sender, size_t _rel)
void initialiseOverride() override
void notifyMouseSetFocus(Widget *_sender, Widget *_old)
void swapItemsAt(size_t _index1, size_t _index2)
Swap items at a specified positions.
int getOptimalHeight() const
Return optimal height to fit all items in ListBox.
void onKeyButtonReleased(KeyCode _key) override
void insertItemAt(size_t _index, const UString &_name, Any _data=Any::Null)
Insert an item into a array at a specified position.
void removeAllItems()
Remove all items.
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListChangePosition
void onMouseWheel(int _rel) override
void clearItemDataAt(size_t _index)
Clear an item data at a specified position.
size_t getIndexSelected() const
void _selectIndex(size_t _index, bool _select)
size_t _getItemCount() const override
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListMouseItemFocus
size_t findItemIndexWith(const UString &_name)
Search item, returns the position of the first occurrence in array or ITEM_NONE if item not found.
void beginToItemFirst()
Move all elements so first becomes visible.
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListChangeScroll
void notifyKeyButtonPressed(Widget *_sender, KeyCode _key, Char _char)
void onKeyButtonPressed(KeyCode _key, Char _char) override
void setItemDataAt(size_t _index, Any _data)
Replace an item data at a specified position.
void notifyMouseDoubleClick(Widget *_sender)
Widget * getWidgetByIndex(size_t _index)
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListSelectAccept
void beginToItemSelected()
Move all elements so selected becomes visible.
void removeItemAt(size_t _index)
Remove item at a specified position.
void setItemNameAt(size_t _index, const UString &_name)
Replace an item name at a specified position.
void setIndexSelected(size_t _index)
void _setItemFocus(size_t _position, bool _focus)
void beginToItemLast()
Move all elements so last becomes visible.
void setCoord(const IntCoord &_value) override
EventPair< EventHandle_WidgetSizeT, EventHandle_ListPtrSizeT > eventListMouseItemActivate
widget description should be here.
EventHandle_ScrollBarPtrSizeT eventScrollChangePosition
void setScrollRange(size_t _value)
void setTrackSize(int _value)
size_t getScrollPosition() const
void setScrollPosition(size_t _value)
size_t getScrollRange() const
void setScrollViewPage(size_t _value)
void setScrollPage(size_t _value)
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
bool isUserString(const std::string &_key) const
const std::string & getUserString(const std::string &_key) const
widget description should be here.
Widget * createWidgetT(const std::string &_type, const std::string &_skin, const IntCoord &_coord, Align _align, const std::string &_name="")
EventHandle_WidgetStringString eventChangeProperty
void assignWidget(T *&_widget, const std::string &_name)
virtual void setVisible(bool _value)
bool getVisible() const
void setSize(const IntSize &_value) override
Widget * getClientWidget()
Widget * _getClientWidget()
If there is client widget return it, otherwise return this.
EventHandle_WidgetIntIntButton eventMouseButtonReleased
void setNeedKeyFocus(bool _value)
EventHandle_WidgetIntIntButton eventMouseButtonPressed
EventHandle_WidgetKeyCodeChar eventKeyButtonPressed
EventHandle_WidgetKeyCode eventKeyButtonReleased
static WidgetManager & getInstance()
int parseInt(const std::string &_value)
bool parseBool(const std::string &_value)
const size_t ITEM_NONE
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
types::TPoint< int > IntPoint
Definition MyGUI_Types.h:27
unsigned int Char
Definition MyGUI_Types.h:50