36 using namespace Drawing;
42 const SDst defMarginH(2);
43 const SDst defMarginV(1);
49 TextList::TextList(
const Rect& r,
const shared_ptr<ListType>&
h,
50 pair<Color, Color> hilight_pair)
51 : Control(r), MTextList(h),
52 HilightBackColor(hilight_pair.
first),
53 HilightTextColor(hilight_pair.
second), CyclicTraverse(false),
54 viewer(GetListRef()), top_offset(0)
56 Margin = Padding(defMarginH, defMarginH, defMarginV, defMarginV);
58 FetchEvent<KeyDown>(*
this) += [
this](KeyEventArgs&& e){
59 if(viewer.GetTotal() != 0)
61 using namespace KeyCodes;
62 const auto& k(e.GetKeys());
68 const auto old_sel(viewer.GetSelectedIndex());
69 const auto old_off(viewer.GetOffset());
70 const auto old_hid(viewer.GetHeadIndex());
71 const auto old_top(top_offset);
74 const bool up(k[
Up] || k[
PgUp]);
76 if(viewer.IsSelected())
78 viewer.IncreaseSelected((up ? -1 : 1) * (k[
Up]
79 || k[
Down] ? 1 : GetHeight()
81 if(old_sel == viewer.GetSelectedIndex()
84 if(viewer.GetOffset() == (up ? 0 : ViewerType
85 ::DifferenceType(viewer.GetLength() - 1)))
90 up ? SelectLast() : SelectFirst();
93 const auto new_off(viewer.GetOffset());
95 if(viewer.GetSelectedIndex() != old_sel)
97 if(old_top != top_offset || viewer.GetHeadIndex()
100 else if(old_off != new_off)
101 InvalidateSelected2(old_off, new_off);
103 else if(viewer.IsSelected())
107 InvokeConfirmed(viewer.GetSelectedIndex());
110 InvalidateSelected(viewer.GetOffset());
119 FetchEvent<TouchDown>(*this) += [
this](TouchEventArgs&& e){
123 FetchEvent<TouchMove>(*this) += [
this](TouchEventArgs&& e){
124 if(&e.GetSender() ==
this)
130 FetchEvent<Click>(*this) += [
this](TouchEventArgs&& e){
131 InvokeConfirmed(CheckPoint(e));
139 TextList::GetFullViewHeight()
const
141 return GetItemHeight() * viewer.GetTotal();
144 TextList::GetViewPosition()
const
146 return GetItemHeight() * viewer.GetHeadIndex() + top_offset;
150 TextList::SetList(
const shared_ptr<ListType>& h)
154 MTextList::SetList(h);
155 viewer.SetContainer(*h);
161 TextList::SetSelected(ListType::size_type i)
163 if(viewer.Contains(i))
165 const auto old_off(viewer.GetOffset());
167 if(viewer.SetSelectedIndex(i))
170 InvalidateSelected2(old_off, viewer.GetOffset());
175 TextList::SetSelected(
SPos x,
SPos y)
177 SetSelected(CheckPoint(x, y));
181 TextList::AdjustOffset(
bool is_top)
183 if(GetFullViewHeight() > GetHeight())
185 viewer.RestrictSelected();
189 const auto d(top_offset);
197 const SDst item_height(GetItemHeight());
198 const auto d((GetHeight() + top_offset) % item_height);
202 const auto tmp(top_offset + item_height - d);
204 top_offset = tmp % item_height;
206 viewer.IncreaseHead(tmp / item_height);
215 TextList::AdjustViewForContent()
217 const bool b(viewer.AdjustForContent());
219 if(viewer.IsSelected() && b)
221 AdjustOffset(viewer.GetSelectedIndex() == viewer.GetHeadIndex());
224 if(GetFullViewHeight() < GetViewPosition() + GetHeight())
230 TextList::AdjustViewLength()
232 const auto h(GetHeight());
236 const auto ln_h(GetItemHeight());
238 viewer.SetLength(h / ln_h + (top_offset != 0 || h % ln_h != 0));
243 TextList::CheckConfirmed(ListType::size_type idx)
const
245 return viewer.IsSelected() && viewer.GetSelectedIndex() == idx;
248 TextList::ListType::size_type
249 TextList::CheckPoint(
SPos x,
SPos y)
252 / GetItemHeight() + viewer.GetHeadIndex() : ListType::size_type(-1);
256 TextList::InvalidateSelected(ListType::difference_type offset,
257 ListType::size_type n)
259 if(offset >= 0 && n != 0)
261 const auto ln_h(GetItemHeight());
262 Rect r(0, ln_h * offset - top_offset, GetWidth(), ln_h * n);
264 if(r.
Y < GetHeight())
266 r.
Y = max<int>(0, r.
Y);
274 TextList::InvalidateSelected2(ListType::difference_type x,
275 ListType::difference_type y)
279 InvalidateSelected(x < 0 ? 0 : x, y - x + 1);
283 TextList::LocateViewPosition(
SDst h)
287 if(GetViewPosition() != h)
289 const SDst item_height(GetItemHeight());
293 viewer.SetHeadIndex(h / item_height);
294 top_offset = h % item_height;
302 ListType::size_type i)
304 DrawClippedText(g, mask & (unit + Margin), tsList, GetList()[i],
false);
318 const auto h(GetHeight());
326 if(viewer.GetTotal() != 0 && bool(r))
330 const auto ln_w(GetWidth());
331 const auto ln_h(GetItemHeight());
336 const SPos lbound(r.
Y - pt.Y);
337 const auto last(viewer.GetHeadIndex()
338 + min<ViewerType::SizeType>((lbound + r.
Height + top_offset
339 - 1) / ln_h + 1, viewer.GetValid()));
340 SPos y(ln_h * ((min<SPos>(0, lbound) + top_offset - 1) / ln_h)
343 for(
auto i(viewer.GetHeadIndex()); i < last;
yunseq(y += ln_h, ++i))
345 SPos top(y), tmp(y + ln_h);
347 RestrictInInterval<SPos>(top, 0,
h);
348 RestrictInInterval<SPos>(tmp, 1, h + 1);
351 const Rect unit(pt.X, top + pt.Y, ln_w, tmp);
353 if(viewer.IsSelected() && i == viewer.GetSelectedIndex())
355 tsList.Color = HilightTextColor;
356 DrawItemBackground(pc, unit);
359 tsList.Color = ForeColor;
361 tsList.ResetPen(unit.
GetPoint(), Margin);
363 tsList.Pen.Y -= top_offset;
378 TextList::ResetView()
380 bool b(viewer.IsSelected());
384 viewer.SetSelectedIndex(0);
390 TextList::SelectFirst()
392 viewer.SetSelectedIndex(0);
397 TextList::SelectLast()
399 viewer.SetSelectedIndex(GetList().size() - 1);
404 TextList::CallSelected()
410 TextList::InvokeConfirmed(ListType::size_type idx)
412 if(CheckConfirmed(idx))
421 tl.GetFullViewHeight()));
422 tl.AdjustViewLength();
428 tl.GetViewChanged()(TextList::ViewArgs(tl, is_active));
429 tl.AdjustViewLength();