29 #include YFM_YSLib_UI_TextList
30 #include YFM_YSLib_UI_YWindow
31 #include YFM_YSLib_UI_Border
32 #include YFM_YSLib_Service_YBlit
33 #include YFM_YSLib_Service_TextLayout
38 using namespace Drawing;
45 const SDst defMarginH(2);
46 const SDst defMarginV(1);
47 const SDst defMinScrollBarWidth(16);
52 TextList::TextList(
const Rect&
r,
const shared_ptr<ListType>& h,
53 const pair<Color, Color>& hilight_pair)
54 : Control(r, MakeBlankBrush()), MTextList(h), MHilightText(hilight_pair),
57 const auto invalidator([
this]{
61 Margin = Padding(defMarginH, defMarginH, defMarginV, defMarginV);
63 FetchEvent<KeyDown>(*
this) += [
this](KeyEventArgs&& e){
66 using namespace KeyCodes;
67 const auto& k(e.GetKeys());
71 if(k[Up] || k[Down] || k[PgUp] || k[PgDn])
73 const auto old_sel(
viewer.GetSelectedIndex());
74 const auto old_off(
viewer.GetOffset());
75 const auto old_hid(
viewer.GetHeadIndex());
79 const bool up(k[Up] || k[PgUp]);
83 viewer.IncreaseSelected((up ? -1 : 1) * (k[Up]
84 || k[Down] ? 1 : GetHeight() / GetItemHeight()));
85 if(old_sel ==
viewer.GetSelectedIndex()
97 const auto new_off(
viewer.GetOffset());
99 if(
viewer.GetSelectedIndex() != old_sel)
103 else if(old_off != new_off)
106 else if(
viewer.IsSelected())
109 if(k[KeyCodes::Enter])
122 FetchEvent<TouchDown>(*this) += [
this](CursorEventArgs&& e){
126 FetchEvent<TouchHeld>(*this) += [
this](CursorEventArgs&& e){
127 if(&e.GetSender() ==
this)
133 FetchEvent<Click>(*this) += [
this](CursorEventArgs&& e){
137 FetchEvent<GotFocus>(*this) += invalidator,
138 FetchEvent<LostFocus>(*this) += invalidator
144 TextList::GetFullViewHeight()
const
146 return GetItemHeight() *
viewer.GetTotal();
170 const auto old_off(
viewer.GetOffset());
188 if(GetFullViewHeight() > GetHeight())
190 viewer.RestrictSelected();
202 const SDst item_height(GetItemHeight());
203 const auto d((GetHeight() +
top_offset) % item_height);
211 viewer.IncreaseHead(tmp / item_height);
224 if(
viewer.IsSelected() && b)
237 const auto h(GetHeight());
241 const auto ln_h(GetItemHeight());
250 return viewer.IsSelected() &&
viewer.GetSelectedIndex() == idx;
253 TextList::ListType::size_type
257 / GetItemHeight() +
viewer.GetHeadIndex() : ListType::size_type(-1);
262 ListType::size_type n)
264 if(offset >= 0 && n != 0)
266 const auto ln_h(GetItemHeight());
269 if(r.
Y < GetHeight())
271 r.
Y = max<int>(0, r.
Y);
280 ListType::difference_type y)
294 const SDst item_height(GetItemHeight());
307 ListType::size_type i)
316 FillRectRaw<PixelType>(pc.Target.GetBufferPtr(), pc.Target.GetSize(),
324 const auto h(GetHeight());
330 const Rect&
r(pc.ClipArea);
332 if(
viewer.GetTotal() != 0 && bool(r))
334 const auto&
g(pc.Target);
335 const auto& pt(pc.Location);
336 const auto ln_w(GetWidth());
337 const auto ln_h(GetItemHeight());
342 const SPos lbound(r.
Y - pt.Y);
343 const auto last(
viewer.GetHeadIndex()
345 - 1) / ln_h + 1,
viewer.GetValid()));
349 for(
auto i(
viewer.GetHeadIndex()); i < last;
yunseq(y += ln_h, ++i))
351 SPos top(y), tmp(y + ln_h);
353 RestrictInInterval<SPos>(top, 0, h);
354 RestrictInInterval<SPos>(tmp, 1, h + 1);
357 const Rect unit(pt.X, top + pt.Y, ln_w, tmp);
359 if(
viewer.IsSelected() && i ==
viewer.GetSelectedIndex())
361 tsList.Color = HilightTextColor;
365 tsList.Color = ForeColor;
366 AdjustEndOfLine(tsList, unit + Margin, g.GetWidth()),
367 tsList.ResetPen(unit.GetPoint(), Margin);
385 bool b(
viewer.IsSelected());
425 SetSizeOf(tl,
Size(tl.GetMaxTextWidth() + GetHorizontalOf(tl.Margin),
426 tl.GetFullViewHeight()));
427 tl.AdjustViewLength();
434 tl.AdjustViewLength();
void InvalidateSelected(ListType::difference_type offset, ListType::size_type diff=1)
无效化偏移量对应的列表项区域。
typename _tCon::difference_type DifferenceType
项目索引差值类型。
SDst GetViewPosition() const
取视图顶端竖直位置。
pt pt Y const IWidget &wgt const IWidget &wgt GetSizeOf
无效化:使相对于部件的子部件的指定区域在直接和间接的窗口缓冲区中无效。
void Refresh(PaintEventArgs &&) override
刷新:按指定参数绘制界面并更新状态。
YF_API void OnKeyHeld(KeyEventArgs &&)
处理键接触保持事件。
GValueEventArgs< MTextList::IndexType > IndexEventArgs
索引事件。
SDst AdjustOffset(bool)
调整列表视图底项目的竖直偏移量为零。
YF_API void Invalidate(IWidget &, const Rect &)
无效化:使相对于部件的指定区域在直接和间接的窗口缓冲区中无效。
YF_API void DrawClippedText(const Graphics &g, const Rect &mask, TextState &ts, const String &str, bool line_wrap)
绘制剪切区域的文本。
void UpdateView(TextList &tl, bool is_active)
bool SetSelectedIndex(SizeType t)
设置选中项目的索引。
void InvalidateSelected2(ListType::difference_type, ListType::difference_type)
无效化偏移量对应的列表项区域。
void SelectLast()
选择最后一个项目。
YF_API void SetSizeOf(IWidget &, const Size &)
设置部件大小。
bool SetHeadIndex(SizeType t)
设置视图中首个项目的索引。
yconstexpr EventPriority BoundaryPriority(0x60)
void SetList(const shared_ptr< ListType > &h)
设置文本列表。
std::uint16_t SDst
屏幕坐标距离。
virtual bool CheckConfirmed(ListType::size_type) const
检查列表中的指定项是否有效。
void swap(any &x, any &y)
交换对象。
virtual void DrawItemBackground(const PaintContext &, const Rect &r)
描画列表项背景。
bool CyclicTraverse
循环选择遍历。
void SetSelected(ListType::size_type)
按指定项目索引设置选中项目。
void SetList(const shared_ptr< ListType > &)
设置文本列表。
#define yunseq
无序列依赖表达式组求值。
bool Contains(int px, int py) const ynothrow
判断点 (px, py) 是否在矩形内或边上。
void SelectFirst()
选择第一个项目。
void RestrictUnsignedStrict(_type &u, unsigned b) ynothrow
约束无符号整数 u 在区间上界 b 内。
void LocateViewPosition(SDst)
定位视图顶端至指定竖直位置。
bool AdjustForContent()
按序列内容大小依次调整选中和首个项目的索引。
virtual void DrawItem(const Graphics &, const Rect &mask, const Rect &, ListType::size_type)
绘制列表项。
void AdjustViewForContent()
按内容大小依次调整视图中选中和首个项目的索引,然后按需调整竖直偏移量。
SDst top_offset
列表视图首项目超出上边界的竖直偏移量。
void RestrictInInterval(_type &i, int a, int b) ynothrow
约束整数 i 在左闭右开区间 [a, b) 中。
ListType::size_type CheckPoint(SPos, SPos)
检查点(相对于所在缓冲区的控件坐标)是否在选择范围内,
void InvokeConfirmed(ListType::size_type)
检查和调用确认事件处理器。
void AdjustViewLength()
调整视图长度。
void CallSelected()
调用选中事件处理器。
void ResizeForContent(TextList &tl)
bool SetLength(SizeType l)
设置长度。
virtual void DrawItems(const PaintContext &)
绘制列表。
int int is_selected bool Contains(SizeType i) const
判断是否在有效范围内包含指定项目索引。
Selected const shared_ptr< ListType > const pair< Color, Color > Selected
GValueEventArgs< bool > ViewArgs
视图参数类型。