5 #include "../UI/ComponentStackWidget.h"
6 #include "../Property.h"
7 #include "../Input/KeyRepeater.h"
13 namespace Gorgon {
namespace Widgets {
19 template<
class T_,
class W_>
67 template <
class T_,
class W_,
class F_>
79 void prepare(W_ &) { }
80 void insert(
long,
long) { }
81 void move(
long,
long) { }
82 void remove(
long,
long) { }
86 template <
class T_,
class W_,
class F_>
87 class LBTRF_ListItem {
91 void SetOddEven(
bool value) {
96 dynamic_cast<F_*
>(
this)->Refresh();
100 bool GetOddEven()
const {
106 ~LBTRF_ListItem() { }
121 void prepare(W_ &) { }
122 void insert(
long,
long) { }
123 void move(
long,
long) { }
124 void remove(
long,
long) { }
129 template<
class T_,
class W_>
130 void SetTextUsingFrom(
const T_ &val, W_ &w) {
134 template<
class T_,
class W_,
class F_, F_ f>
135 void SetTextUsingFn(
const T_ &val, W_ &w) {
139 template<
class T_,
class W_>
140 void GetTextUsingTo(W_ &w, T_ &val) {
141 val = String::To<T_>(w.GetText());
146 template<
class T_,
class W_,
class F_>
147 class LBSELTR_Single {
150 bool HasSelectedItem()
const {
151 return selectedindex != -1;
157 const T_ &GetSelectedItem()
const {
158 if(selectedindex == -1)
159 throw std::runtime_error(
"Nothing is selected.");
161 return dynamic_cast<const F_&
>(*this)[selectedindex];
168 T_ &GetSelectedItem() {
169 if(selectedindex == -1)
170 throw std::runtime_error(
"Nothing is selected.");
172 return dynamic_cast<F_&
>(*this)[selectedindex];
177 long GetSelectedIndex()
const {
178 return selectedindex;
184 void SetSelectedIndex(
long index) {
185 if(index < -1 || index >=
dynamic_cast<F_&
>(*this).GetCount())
186 throw std::out_of_range(
"Selected index does not exits");
188 if(index == selectedindex)
193 W_ *elm =
dynamic_cast<F_&
>(*this).getrepresentation();
194 if(elm !=
nullptr && elm->HasParent()) {
195 elm->GetParent().RemoveFocus();
199 W_ *elm =
dynamic_cast<F_&
>(*this).getrepresentation(index);
204 elm =
dynamic_cast<F_&
>(*this).getrepresentation();
206 if(elm !=
nullptr && elm->HasParent()) {
207 elm->GetParent().RemoveFocus();
216 selected->SetSelected(
false);
219 W_ *elm =
dynamic_cast<F_&
>(*this).getrepresentation(index);
222 elm->SetSelected(
true);
227 selectedindex = index;
228 ChangedEvent(selectedindex);
233 void SetFocusIndex(
long value) {
234 if(focusindex == value)
238 SetSelectedIndex(value);
243 auto w =
dynamic_cast<F_*
>(
this)->getrepresentation(value);
248 auto w =
dynamic_cast<F_*
>(
this)->getrepresentation(focusindex);
258 long GetFocusIndex()
const {
262 void RemoveSelection() {
263 SetSelectedIndex(-1);
268 void SetSelection(T_ item) {
269 auto &me =
dynamic_cast<F_&
>(*this);
271 for(
long i=0; i<me.GetSize(); i++) {
278 SetSelectedIndex(-1);
285 bool IsSelectionFollowingFocus()
const {
293 void SetSelectionFollowsFocus(
bool value) {
294 if(!focusonly && value) {
295 if(focusindex != -1) {
296 if(selectedindex != focusindex) {
297 selectedindex = focusindex;
298 ChangedEvent(selectedindex);
302 focusindex = selectedindex;
310 return GetSelectedItem();
313 operator T_()
const {
314 return GetSelectedItem();
317 Event<LBSELTR_Single, long> ChangedEvent = Event<LBSELTR_Single, long>{
this};
323 virtual ~LBSELTR_Single() { }
325 void sel_clicked(
long index, W_ &w) {
327 if(selectedindex == index)
331 selected->SetSelected(
false);
335 if(
dynamic_cast<UI::Widget*
>(
this)->IsFocused())
339 selectedindex = index;
345 if(focusindex == index)
348 if(
dynamic_cast<UI::Widget*
>(
this)->IsFocused())
354 dynamic_cast<UI::Widget*
>(
this)->Focus();
357 void sel_toggled(
long index, W_ &w) {
358 if(selectedindex == index || focusonly)
362 selected->SetSelected(
false);
365 selectedindex = index;
369 if(
dynamic_cast<UI::Widget*
>(
this)->IsFocused())
378 void sel_apply(
long index, W_ &w,
const T_ &) {
379 if(index == focusindex) {
382 else if(w.IsFocused()) {
386 if(index == selectedindex) {
391 w.SetSelected(
false);
398 void sel_prepare(W_ &w) {
399 w.ClickEvent.Register([&w,
this] {
400 sel_clicked(
dynamic_cast<F_*
>(
this)->getindex(w), w);
402 w.ToggleEvent.Register([&w,
this] {
403 sel_toggled(
dynamic_cast<F_*
>(
this)->getindex(w), w);
407 void sel_insert(
long index,
long count) {
408 if(index <= focusindex)
411 if(index <= selectedindex)
412 selectedindex += count;
415 void sel_move(
long index,
long target) {
418 if(index == focusindex) {
421 else if(index > focusindex && target <= focusindex) {
424 else if(index < focusindex && target > focusindex) {
428 if(index == selectedindex) {
429 selectedindex = target;
431 else if(index > selectedindex && target <= selectedindex) {
434 else if(index < selectedindex && target > selectedindex) {
439 void sel_remove(
long index,
long count) {
441 if(index <= focusindex) {
442 if(index+count > focusindex) {
451 if(index <= selectedindex) {
452 if(index+count > selectedindex) {
457 selectedindex -= count;
462 void sel_destroy(W_ &w) {
472 void reapplyfocus() {
473 if(focusindex != -1) {
474 auto w =
dynamic_cast<F_*
>(
this)->getrepresentation(focusindex);
480 bool focusonly =
true;
482 long focusindex = -1, selectedindex = -1;
484 W_ *selected =
nullptr;
489 template<
class T_,
class W_,
class F_>
490 class LBSELTR_Multi {
491 template <
class F1_>
friend class ItemIterator_;
492 friend class SelectionHelper;
494 class SelectionIndexHelper {
496 SelectionIndexHelper(
const std::vector<long> &v) : v(v) {
508 const std::vector<long> &v;
511 class SelectionHelper {
513 SelectionHelper(LBSELTR_Multi &l) : l(l) {
517 auto &me =
dynamic_cast<F_ &
>(l);
518 return ItemIterator(me, l.selected, 0);
522 auto &me =
dynamic_cast<F_ &
>(l);
523 return ItemIterator(me, l.selected, l.selected.size());
527 auto &me =
dynamic_cast<F_ &
>(l);
528 return ConstItemIterator(me, l.selected, 0);
532 auto &me =
dynamic_cast<F_ &
>(l);
533 return ConstItemIterator(me, l.selected, l.selected.size());
541 template <
class O_,
class F1_>
542 class ItemIterator_ :
public Containers::Iterator<ItemIterator_<O_, F1_>, O_> {
543 friend class SelectionHelper;
544 friend class ConstItemIterator;
545 friend class Containers::Iterator<ItemIterator_<O_, F1_>, O_>;
548 ItemIterator_(): list(NULL), offset(-1) {
551 ItemIterator_(
const ItemIterator_ &it): list(it.list), offset(it.offset) {
555 ItemIterator_(F1_ &list,
const std::vector<long> &inds,
long offset = 0): list(&list), offset(offset), inds(&inds) {
559 O_ ¤t()
const {
561 throw std::out_of_range(
"Iterator is not valid.");
563 return (*list)[(*inds)[offset]];
566 bool isvalid()
const {
567 return list && inds && offset>=0 && offset<(inds->size());
570 bool moveby(
long amount) {
572 if(amount==0)
return isvalid();
579 bool compare(
const ItemIterator_ &it)
const {
580 if(!it.isvalid() && !isvalid())
return true;
581 return it.offset==offset;
584 void set(
const ItemIterator_ &it) {
589 long distance(
const ItemIterator_ &it)
const {
590 return it.offset-offset;
593 bool isbefore(
const ItemIterator_ &it)
const {
594 return offset<it.offset;
599 const std::vector<long> *inds =
nullptr;
603 typedef ItemIterator_<T_, F_> ItemIterator;
606 class ConstItemIterator :
public ItemIterator_<const T_, const F_> {
607 friend class SelectionHelper;
608 friend class Containers::Iterator<ItemIterator_<const T_, const F_>, T_>;
612 ConstItemIterator(
const ItemIterator &it) {
613 this->list = it.list;
614 this->offset = it.offset;
618 ConstItemIterator(
const F_ &c,
const std::vector<long> &inds,
long offset = 0): ItemIterator_<const T_, const F_>(c, inds, offset) {
622 enum SelectionMethod {
644 void SetSelectionMethod(SelectionMethod value) {
649 SelectionMethod GetSelectionMethod()
const {
659 void SetEventMethod(EventMethod value) {
664 EventMethod GetEventMethod()
const {
670 long GetFocusIndex()
const {
676 void SetFocusIndex(
long value) {
677 if(focusindex == value)
681 auto w =
dynamic_cast<F_*
>(
this)->getrepresentation(value);
686 auto w =
dynamic_cast<F_*
>(
this)->getrepresentation(focusindex);
695 void ClearSelection() {
698 ChangedEvent(-1,
false);
701 std::vector<long> old;
704 for(
auto ind : old) {
705 ChangedEvent(ind,
false);
709 dynamic_cast<F_*
>(
this)->Refresh();
713 void SetSelection(
long ind) {
714 SetSelection(std::vector<long>{ind});
718 void SetSelection(std::vector<long> indices) {
719 if(event == ForEachItem)
722 selected = std::move(indices);
723 std::sort(selected.begin(), selected.end());
726 selected.erase(std::unique(selected.begin(), selected.end()), selected.end());
728 if(event == ForEachItem) {
729 for(
auto ind : selected) {
730 ChangedEvent(ind,
true);
734 ChangedEvent(-1,
false);
737 dynamic_cast<F_*
>(
this)->Refresh();
741 template<
class ...P_>
742 void SetSelection(P_&&... elms) {
743 SetSelection({elms...});
747 void AddToSelection(
long ind) {
748 AddToSelection(std::vector<long>{ind});
752 void AddToSelection(std::vector<long> indices) {
753 std::sort(indices.begin(), indices.end());
755 selected.resize(selected.size() + indices.size());
756 auto sel = selected.rbegin();
757 auto cur = selected.rbegin() + indices.size();
758 auto ind = indices.rbegin();
760 while(ind != indices.rend()) {
761 if(cur == selected.rend() || *cur < *ind) {
764 if(event == ForEachItem)
765 ChangedEvent(*ind,
true);
777 selected.erase(std::unique(selected.begin(), selected.end()), selected.end());
780 ChangedEvent(-1,
false);
783 dynamic_cast<F_*
>(
this)->Refresh();
787 template<
class ...P_>
788 void AddToSelection(P_&&... elms) {
789 AddToSelection({elms...});
793 bool IsSelected(
long index)
const {
794 return std::binary_search(selected.begin(), selected.end(), index);
798 long GetSelectionCount()
const {
799 return long(selected.size());
803 void RemoveFromSelection(
long index) {
804 auto item = std::lower_bound(selected.begin(), selected.end(), index);
806 if(item != selected.end() && *item == index) {
807 selected.erase(item);
808 ChangedEvent(index,
false);
811 dynamic_cast<F_*
>(
this)->Refresh();
816 auto elms =
dynamic_cast<F_*
>(
this)->GetCount();
818 std::vector<long> old;
823 auto sel = old.begin();
824 for(
int i=0; i<elms; i++) {
825 if(sel != old.end() && *sel == i)
827 else if(event == ForEachItem)
828 ChangedEvent(i,
true);
830 selected.push_back(i);
834 ChangedEvent(-1,
false);
837 dynamic_cast<F_*
>(
this)->Refresh();
841 void InvertSelection() {
842 std::vector<long> old;
844 auto elms =
dynamic_cast<F_*
>(
this)->GetCount();
845 old.reserve(elms-selected.size());
849 auto sel = old.begin();
850 for(
int i=0; i<elms; i++) {
851 if(sel != old.end() && *sel == i) {
854 if(event == ForEachItem)
855 ChangedEvent(i,
false);
858 selected.push_back(i);
860 if(event == ForEachItem)
861 ChangedEvent(i,
true);
866 ChangedEvent(-1,
false);
868 dynamic_cast<F_*
>(
this)->Refresh();
872 SelectionIndexHelper SelectedIndices;
876 SelectionHelper Selection;
878 Event<LBSELTR_Multi, long, bool> ChangedEvent = Event<LBSELTR_Multi, long, bool>{
this};
882 SelectedIndices(selected),
887 virtual ~LBSELTR_Multi() { }
889 void sel_clicked(
long index, W_ &w) {
890 if(focusindex == index)
893 if(
dynamic_cast<UI::Widget*
>(
this)->IsFocused())
898 dynamic_cast<UI::Widget*
>(
this)->Focus();
901 void sel_toggled(
long index, W_ &w,
bool forcetoggle =
true) {
902 if(method == Toggle || forcetoggle) {
903 auto item = std::lower_bound(selected.begin(), selected.end(), index);
905 if(item != selected.end() && *item == index) {
906 w.SetSelected(
false);
907 selected.erase(item);
909 ChangedEvent(index,
false);
913 selected.insert(item, index);
915 ChangedEvent(index,
true);
920 auto item = std::lower_bound(selected.begin(), selected.end(), index);
922 if(item != selected.end() && *item == index) {
923 w.SetSelected(
false);
924 selected.erase(item);
926 ChangedEvent(index,
false);
930 selected.insert(item, index);
932 ChangedEvent(index,
true);
941 void sel_apply(
long index, W_ &w,
const T_ &) {
942 if(index == focusindex) {
945 else if(w.IsFocused()) {
949 if(std::binary_search(selected.begin(), selected.end(), index)) {
953 w.SetSelected(
false);
957 void sel_prepare(W_ &w) {
958 w.ClickEvent.Register([&w,
this] {
959 sel_clicked(
dynamic_cast<F_*
>(
this)->getindex(w), w);
961 w.ToggleEvent.Register([&w,
this] {
962 sel_toggled(
dynamic_cast<F_*
>(
this)->getindex(w), w,
false);
966 void sel_insert(
long index,
long count) {
967 if(index <= focusindex)
970 auto item = std::lower_bound(selected.begin(), selected.end(), index);
971 for(; item != selected.end(); ++item) {
976 void sel_move(
long index,
long target) {
981 if(index == focusindex) {
984 else if(index > focusindex && target <= focusindex) {
987 else if(index < focusindex && target > focusindex) {
992 auto from = std::lower_bound(selected.begin(), selected.end(), index);
993 auto to = std::lower_bound(selected.begin(), selected.end(), target+1);
1001 *from = *shifted - 1;
1007 if(shifted != from) {
1012 auto from = std::lower_bound(selected.begin(), selected.end(), index-1);
1013 auto to = std::upper_bound(selected.begin(), selected.end(), target);
1015 auto shifted = from;
1021 *from = *shifted + 1;
1027 if(shifted != from) {
1033 void sel_remove(
long index,
long count) {
1035 if(index <= focusindex) {
1036 if(index+count > focusindex) {
1040 focusindex -= count;
1045 auto item = std::lower_bound(selected.begin(), selected.end(), index);
1046 auto shifted = item;
1047 while(shifted != selected.end()) {
1048 if(*item < index+count) {
1052 *item = *shifted - count;
1059 if(item != selected.end())
1060 selected.erase(item, selected.end());
1063 void sel_destroy(W_ &w) {
1070 void reapplyfocus() {
1071 if(focusindex != -1) {
1072 auto w =
dynamic_cast<F_*
>(
this)->getrepresentation(focusindex);
1078 long focusindex = -1;
1079 std::vector<long> selected;
1080 SelectionMethod method = Toggle;
1081 EventMethod
event = ForEachItem;
1084 template<
class T_,
class W_,
class S_,
class F_>
1085 class LBSTR_STLVector {
1091 storage.push_back(val);
1093 dynamic_cast<F_*
>(
this)->Refresh();
1097 template<
class... A_>
1098 void Add(T_ val, A_&& ...rest) {
1099 storage.push_back(val);
1101 Add(std::forward<A_>(rest)...);
1107 void Insert(
long before, T_ val) {
1113 storage.insert(storage.begin()+before, val);
1115 dynamic_cast<F_*
>(
this)->sel_insert(before, 1);
1116 dynamic_cast<F_*
>(
this)->Refresh();
1122 template<
class... A_>
1123 void Insert(
long before, T_ val, A_&& ...rest) {
1130 Insert(std::forward<A_>(rest)...);
1132 storage.insert(storage.begin()+before, val);
1133 dynamic_cast<F_*
>(
this)->sel_insert(before, 1);
1137 void Remove(
long index) {
1138 storage.erase(storage.begin()+index);
1140 dynamic_cast<F_*
>(
this)->sel_remove(index, 1);
1141 dynamic_cast<F_*
>(
this)->Refresh();
1147 void MoveBefore(
long index,
long before) {
1151 if(before >= storage.size() || before == -1) {
1152 auto t = storage[index];
1154 for(
unsigned i=index; i<storage.size()-1; i++)
1155 storage[i] = storage[i+1];
1157 storage[storage.size()-1] = t;
1159 else if(index>before) {
1160 auto t = storage[index];
1161 for(
unsigned i=index; i>before; i--)
1162 storage[i] = storage[i-1];
1167 auto t = storage[index];
1168 for(
unsigned i=index; i<before; i++)
1169 storage[i] = storage[i+1];
1171 storage[before] = t;
1174 dynamic_cast<F_*
>(
this)->sel_move(index, before);
1175 dynamic_cast<F_*
>(
this)->Refresh();
1180 long Find(
const T_ item,
long start = 0) {
1181 auto it = std::find(storage.begin() + start, storage.end(), item);
1182 if(it == storage.end())
1185 return it-storage.begin();
1189 void Reserve(
long amount) {
1190 storage.reserve(amount);
1203 return storage.begin();
1206 auto begin()
const {
1207 return storage.begin();
1211 return storage.end();
1215 return storage.end();
1221 LBSTR_STLVector() {}
1222 virtual ~LBSTR_STLVector() {}
1224 long getsize()
const {
1225 return storage.size();
1228 T_ &getelm(
long index) {
1229 return storage[index];
1232 const T_ &getelm(
long index)
const {
1233 return storage[index];
1239 template<
class T_,
class W_,
class F_>
1240 class LBSTR_Collection {
1242 using Storage = Containers::Collection<T_>;
1248 dynamic_cast<F_*
>(
this)->Refresh();
1251 template<
class... A_>
1252 T_ &AddNew(A_&& ...args) {
1253 auto &t = storage.AddNew(args...);
1255 dynamic_cast<F_*
>(
this)->Refresh();
1260 template<
class... A_>
1261 void Add(T_ &val, A_& ...rest) {
1264 Add(std::forward<A_>(rest)...);
1267 void Insert(
long before, T_ &val) {
1268 if(storage.Insert(before, val)) {
1269 dynamic_cast<F_*
>(
this)->sel_insert(before, 1);
1270 dynamic_cast<F_*
>(
this)->Refresh();
1274 void Insert(
const T_ &before, T_ &val) {
1275 Insert(FindLocation(before), val);
1278 template<
class... A_>
1279 T_ &InsertNew(
const T_ &before, A_&& ...args) {
1280 auto &t = storage.InsertNew(FindLocation(before), args...);
1282 dynamic_cast<F_*
>(
this)->sel_insert(before, 1);
1283 dynamic_cast<F_*
>(
this)->Refresh();
1288 void Remove(
long index) {
1289 storage.Remove(index);
1291 dynamic_cast<F_*
>(
this)->sel_remove(index, 1);
1292 dynamic_cast<F_*
>(
this)->Refresh();
1295 void Remove(
const T_ &item) {
1296 long index = storage.FindLocation(item);
1300 storage.Remove(index);
1302 dynamic_cast<F_*
>(
this)->sel_remove(index, 1);
1303 dynamic_cast<F_*
>(
this)->Refresh();
1309 void Delete(
const T_ &item) {
1310 long index = storage.FindLocation(item);
1317 storage.Delete(index);
1319 dynamic_cast<F_*
>(
this)->sel_remove(index, 1);
1320 dynamic_cast<F_*
>(
this)->Refresh();
1324 void Delete(
long index) {
1325 storage.Delete(index);
1327 dynamic_cast<F_*
>(
this)->sel_remove(index, 1);
1328 dynamic_cast<F_*
>(
this)->Refresh();
1331 void MoveBefore(
long index,
long before) {
1335 storage.MoveBefore(index, before);
1337 dynamic_cast<F_*
>(
this)->sel_move(index, before);
1338 dynamic_cast<F_*
>(
this)->Refresh();
1343 long Find(
const T_ &item) {
1344 return storage.FindLocation(item);
1349 auto s = storage.GetSize();
1351 storage.DeleteAll();
1353 dynamic_cast<F_*
>(
this)->sel_remove(0, s);
1354 dynamic_cast<F_*
>(
this)->Refresh();
1360 auto s = storage.GetSize();
1364 dynamic_cast<F_*
>(
this)->sel_remove(0, s);
1365 dynamic_cast<F_*
>(
this)->Refresh();
1369 void Reserve(
long amount) {
1370 storage.Reserve(amount);
1383 return storage.begin();
1386 auto begin()
const {
1387 return storage.begin();
1391 return storage.end();
1395 return storage.end();
1401 LBSTR_Collection() {}
1402 virtual ~LBSTR_Collection() {}
1404 long getsize()
const {
1405 return storage.GetSize();
1408 T_ &getelm(
long index) {
1409 return storage[index];
1412 const T_ &getelm(
long index)
const {
1413 return storage[index];
1517 class T_,
class W_,
class TRF_,
1518 class STR_,
class SELTR_,
1520 void (*TW_)(
const T_ &, W_ &)
1537 return this->getelm(index);
1543 return this->getelm(index);
1548 return this->STR_::getsize();
1559 class T_,
class W_,
class TRF_,
1560 class STR_,
class SELTR_,
1562 void (*TW_)(
const T_ &, W_ &)
1572 if(!contents.IsReady())
1575 auto elms = this->STR_::getsize();
1577 std::map<UI::ComponentTemplate::Tag, int> tagcounts;
1582 for(
auto &p : widgetlist) {
1589 if(b.Width() == 0 || b.Height() == 0)
1593 long i = int(scrolloffset), c = 0;
1597 while(y < b.Height() && i < elms) {
1598 auto &v = this->getelm(i);
1599 auto tag = this->tag(i, v, {0, (int)i}, {1, (int)elms});
1601 auto w = getwidget(tag, tagcounts[tag]++);
1609 this->apply(i, *w, v, {0, (int)i}, {1, (int)elms});
1610 this->sel_apply(i, *w, v);
1613 y = -int(std::round(w->GetHeight() * (scrolloffset -
int(scrolloffset))));
1616 indexes.insert({w, i});
1617 widgetlist.insert({i, w});
1622 w->SetWidth(b.Width());
1623 auto advance = w->GetHeight() + stack.GetTemplate().GetSpacing() / 2;
1633 maxdisplay = b.Height() / (float(totalh) / c);
1644 scroller->Range = maxdisplay;
1645 scroller->LargeChange = maxdisplay * 0.8f;
1647 if(scroller->Range >= scroller->Maximum) {
1652 contents.Displaced();
1659 float max = this->STR_::getsize() + overscroll - maxdisplay;
1672 if(scrollspeed == 0) {
1692 ScrollTo(ScrollOffset() + y);
1697 return scrolloffset;
1704 if(overscroll == value)
1711 scroller->
SetMaximum(this->STR_::getsize() + overscroll);
1733 SetSmoothScrollSpeed(0);
1739 scrollspeed = value;
1745 auto elms = this->STR_::getsize();
1748 stack.SetValueTransitionSpeed({elms > 0 ? float(value)/elms : 0, 0, 0, 0});
1759 return scrollspeed != 0;
1773 int curh = GetInteriorSize().Height;
1774 int overhead = GetHeight() - curh;
1775 int expected = int( std::ceil( (this->GetCount()+overscroll) * (curh/maxdisplay) ) ) + overhead;
1776 bool smalldone =
false;
1779 if(expected < maxpixels) {
1782 SetHeight(expected);
1786 auto diff = maxdisplay - (this->GetCount()+overscroll);
1789 if(diff < 1 && diff >= -overscroll/2)
1792 curh = GetInteriorSize().Height;
1793 overhead = GetHeight() - curh;
1794 int curexpected = int( std::ceil( (this->GetCount()+overscroll) * (curh/maxdisplay) ) ) + overhead;
1796 if(abs(expected - curexpected) == 0) {
1799 else if(abs(expected - curexpected) < 0.1 && smalldone) {
1802 else if(abs(expected - curexpected) < 0.1) {
1805 expected = curexpected;
1806 }
while(expected < maxpixels);
1810 SetHeight(maxpixels);
1816 if(b.Width() == 0 || b.Height() == 0)
1826 float targetind = float(index);
1828 auto md = maxdisplay;
1830 if(targetind >= target && targetind < floor(target + md)) {
1833 else if(targetind >= floor(target + md)) {
1834 targetind -= md - 1.5;
1840 auto elms = this->GetCount();
1844 if(targetind > overscroll + elms)
1845 targetind = overscroll + elms;
1847 ScrollTo(targetind);
1850 if(md != maxdisplay)
1851 EnsureVisible(index);
1855 namespace Keycodes = Input::Keyboard::Keycodes;
1857 if(repeater.KeyEvent(key, state))
1861 if(contents.HasFocusedWidget() && state != 0) {
1862 auto w =
dynamic_cast<W_*
>(&contents.GetFocus());
1864 this->sel_toggled(indexes.count(w) ? indexes[w] : -1, *w);
1876 ComponentStackWidget(temp, {
1885 stack.HandleMouse();
1887 stack.SetClickEvent([&](
auto,
auto,
auto) {
1893 ScrollBy(-amount*scrolldist);
1910 repeater.Repeat.Register([
this](
Input::Key key) {
1911 namespace Keycodes = Input::Keyboard::Keycodes;
1912 using Input::Keyboard::Modifier;
1914 long org = this->GetFocusIndex();
1927 ind += long(floor(maxdisplay));
1931 ind -= long(floor(maxdisplay));
1937 if(ind >= this->GetCount())
1938 ind = this->GetCount() - 1;
1941 this->SetFocusIndex(ind);
1949 for(
auto &p : widgets) {
1957 auto temp = stack.GetTemplate(tag);
1962 auto &ws = widgets[tag];
1964 while(ws.GetSize() <= order) {
1965 auto &w = ws.AddNew(*temp);
1966 this->TRF_::prepare(w);
1967 this->sel_prepare(w);
1974 ComponentStackWidget::focused();
1975 this->reapplyfocus();
1979 ComponentStackWidget::focuslost();
1980 contents.RemoveFocus();
1985 vscroller->Maximum = this->STR_::getsize();
1986 vscroller->Range = 1;
1987 *vscroller = scrolloffset;
1988 vscroller->SmallChange = scrolldist;
1998 auto cur = scrolloffset;
2005 if(cur - dist <= target) {
2012 else if(target > cur) {
2013 if(cur + dist >= target) {
2029 isscrolling =
false;
2030 stack.RemoveFrameEvent();
2040 return widgetlist.count(index) ? widgetlist[index] :
nullptr;
2052 return indexes.count(&widget) ? indexes[&widget] : -1;
2059 std::map<UI::ComponentTemplate::Tag, Containers::Collection<W_>>
widgets;
2063 float scrolloffset = 0.f;
2065 float overscroll = 1;
2066 int scrollspeed = 20;
2068 bool isscrolling =
false;
2069 float maxdisplay = 0;
2079 template<
class T_,
void (*TW_)(const T_ &, ListItem &) =
internal::SetTextUsingFrom<T_, ListItem>>
2082 internal::LBTRF_ListItem<T_, ListItem, SimpleListbox<T_, TW_>>,
2083 internal::LBSTR_STLVector<T_, ListItem, std::vector<T_>, SimpleListbox<T_, TW_>>,
2084 internal::LBSELTR_Single<T_, ListItem, SimpleListbox<T_, TW_>>,
2089 internal::LBTRF_ListItem<T_, ListItem, SimpleListbox<T_, TW_>>,
2091 internal::LBSELTR_Single<T_, ListItem, SimpleListbox<T_, TW_>>,
2095 friend internal::LBTRF_ListItem<T_, ListItem, SimpleListbox<T_, TW_>>;
2097 friend internal::LBSELTR_Single<T_, ListItem, SimpleListbox<T_, TW_>>;
2111 this->SetSelection(value);
2130 template<
class T_,
void (*TW_)(const T_ &, ListItem &) =
internal::SetTextUsingFrom<T_, ListItem>>
2133 internal::LBTRF_ListItem<T_, ListItem, MultiListbox<T_, TW_>>,
2134 internal::LBSTR_STLVector<T_, ListItem, std::vector<T_>, MultiListbox<T_, TW_>>,
2135 internal::LBSELTR_Multi<T_, ListItem, MultiListbox<T_, TW_>>,
2140 internal::LBTRF_ListItem<T_, ListItem, MultiListbox<T_, TW_>>,
2142 internal::LBSELTR_Multi<T_, ListItem, MultiListbox<T_, TW_>>,
2146 friend internal::LBTRF_ListItem<T_, ListItem, MultiListbox<T_, TW_>>;
2148 friend internal::LBSELTR_Multi<T_, ListItem, MultiListbox<T_, TW_>>;
2162 this->SetSelection(value);
2176 template<
class T_,
void (*TW_)(const T_ &, ListItem &) =
internal::SetTextUsingFrom<T_, ListItem>>
2179 internal::LBTRF_ListItem<T_, ListItem, SimpleCollectionbox<T_, TW_>>,
2180 internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_, TW_>>,
2181 internal::LBSELTR_Single<T_, ListItem, SimpleCollectionbox<T_, TW_>>,
2186 internal::LBTRF_ListItem<T_, ListItem, SimpleCollectionbox<T_, TW_>>,
2187 internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_, TW_>>,
2188 internal::LBSELTR_Single<T_, ListItem, SimpleCollectionbox<T_, TW_>>,
2192 friend internal::LBTRF_ListItem<T_, ListItem, SimpleCollectionbox<T_, TW_>>;
2193 friend internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_, TW_>>;
2194 friend internal::LBSELTR_Single<T_, ListItem, SimpleCollectionbox<T_, TW_>>;
2208 this->SetSelection(value);
2214 using internal::LBSTR_Collection<T_, ListItem, SimpleCollectionbox<T_>>
::Remove;
2227 template<
class T_,
void (*TW_)(const T_ &, ListItem &) =
internal::SetTextUsingFrom<T_, ListItem>>
2230 internal::LBTRF_ListItem<T_, ListItem, MultiCollectionbox<T_, TW_>>,
2231 internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_, TW_>>,
2232 internal::LBSELTR_Multi<T_, ListItem, MultiCollectionbox<T_, TW_>>,
2237 internal::LBTRF_ListItem<T_, ListItem, MultiCollectionbox<T_, TW_>>,
2238 internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_, TW_>>,
2239 internal::LBSELTR_Multi<T_, ListItem, MultiCollectionbox<T_, TW_>>,
2243 friend internal::LBTRF_ListItem<T_, ListItem, MultiCollectionbox<T_, TW_>>;
2244 friend internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_, TW_>>;
2245 friend internal::LBSELTR_Multi<T_, ListItem, MultiCollectionbox<T_, TW_>>;
2259 this->SetSelection(value);
2265 using internal::LBSTR_Collection<T_, ListItem, MultiCollectionbox<T_>>
::Remove;