YSTest: TreeView.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

TreeView.cpp
浏览该文件的文档.
1 /*
2 © 2014-2016, 2020 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "YSLib/UI/YModules.h"
29 #include YFM_YSLib_UI_TreeView
30 #include <ystdex/utility.hpp> // for ystdex::as_const;
31
32 namespace YSLib
33 {
34
35 namespace UI
36 {
37
38 namespace
39 {
40
45 template<class _tNode, typename _fCallable, typename _fPred, class _tPath>
46 void
47 bind_node(const _tNode& node, _fCallable f, _fPred pred, const _tPath& pth,
48 size_t depth = 0)
49 {
50 if(!node.empty() && pred(pth, depth))
51 {
52 auto cur_path(pth);
53
54 cur_path.push_back(0),
55 ++depth;
56 for(const auto& nd : node)
57 {
58 f(nd, cur_path, depth);
59 bind_node(nd, f, pred, cur_path, depth);
60 ++cur_path.back();
61 }
62 }
63 }
64
65 } // unnamed namespace;
66
67 TreeList::TreeList(const Rect& r, const shared_ptr<ListType>& h,
68 const pair<Color, Color>& hilight_pair)
69 : TextList(r, h, hilight_pair)
70 {
71 auto& unit(GetUnitRef());
72
73 yunseq(
74 FetchEvent<KeyDown>(*this) += [&](KeyEventArgs&& e){
75 if(!GetList().empty() && IsSelected())
76 {
77 using namespace KeyCodes;
78 const auto& k(e.GetKeys());
79
80 if(k.count() == 1)
81 {
82 if(k[Left])
83 {
84 const auto idx(GetSelectedIndex());
85
86 if(CollapseNode(idx) == NodeState::Expanded)
87 UpdateView(*this);
88 else
89 {
90 auto i(indent_map.lower_bound(idx));
91
92 SetSelected(
93 i != indent_map.cbegin() ? (--i)->first : 0);
94 }
95 }
96 else if(k[Right])
97 {
98 const auto idx(GetSelectedIndex());
99 const auto st(ExpandNode(idx));
100
101 if(st == NodeState::Branch)
102 UpdateView(*this);
103 else if(st == NodeState::Expanded)
104 {
105 const auto i(indent_map.lower_bound(idx + 1));
106
107 if(i != indent_map.cend() && i->first > idx)
108 SetSelected(idx + 1);
109 }
110 }
111 }
112 }
113 e.Handled = true;
114 },
115 FetchEvent<TouchDown>(unit) += [this](CursorEventArgs&& e){
116 const auto st(QueryNodeState(idxShared));
117
118 if(st != NodeState::None)
119 {
120 Rect box(GetIndentBox());
121
122 // XXX: Conversion to 'SPos' might be implementation-defined.
123 box.X += SPos(GetIndentWidth(idxShared));
124 if(box.Contains(e) || FetchGUIState().RefreshTap(e) > 1)
125 {
126 ExpandOrCollapseNodeImpl(st, idxShared);
127 UpdateView(*this);
128 }
129 }
130 },
131 FetchEvent<CursorOver>(unit) += [this](CursorEventArgs&& e)
132 {
133 if(QueryNodeState(idxShared) != NodeState::None)
134 {
135 const Rect& box(GetIndentBoxBounds(idxShared));
136 const auto old(idxCursorOver);
137
138 idxCursorOver = box.Contains(e) ? idxShared : size_t(-1);
139 if(old != idxCursorOver)
140 Invalidate(e.GetSender(), box);
141 }
142 },
143 FetchEvent<Leave>(unit) += [this]{
144 if(idxCursorOver != size_t(-1)
145 && QueryNodeState(idxCursorOver) != NodeState::None)
146 {
147 Invalidate(GetUnitRef(), GetIndentBoxBounds(idxCursorOver));
148 idxCursorOver = size_t(-1);
149 }
150 },
151 // TODO: Add %AddFront method.
152 FetchEvent<Paint>(unit).Add([this](PaintEventArgs&& e){
153 tmp_margin_left = LabelBrush.Margin.Left;
154 // XXX: Conversion to 'SPos' might be implementation-defined.
155 LabelBrush.Margin.Left += SPos(GetIndentWidth(idxShared));
156 switch(QueryNodeState(idxShared))
157 {
158 case NodeState::Branch:
159 DrawArrow(e.Target, e.ClipArea, GetIndentBox() + Vec(e.Location.X,
160 e.Location.Y - 1), 5, RDeg0, idxCursorOver == idxShared
161 ? CursorOverColor : LabelBrush.ForeColor, true);
162 break;
163 case NodeState::Expanded:
164 // XXX: Conversion to 'SPos' might be implementation-defined.
165 DrawCornerArrow(e.Target, e.ClipArea, e.Location
166 + Vec(LabelBrush.Margin.Left - SPos(UnitIndent) + 2, 2), 7,
167 RDeg0, idxCursorOver == idxShared ? CursorOverColor
168 : LabelBrush.ForeColor);
169 break;
170 default:
171 ;
172 }
173 }, BackgroundPriority - 1).Add([this]{
174 LabelBrush.Margin.Left = tmp_margin_left;
175 }, 0)
176 );
177 }
178 ImplDeDtor(TreeList)
179
180 String
181 TreeList::DefaultExtractText(const ValueNode& node)
182 {
183 return Access<string>(node);
184 }
185
186 String
187 TreeList::ExtractNodeName(const ValueNode& node)
188 {
189 return node.GetName();
190 }
191
192 Rect
193 TreeList::GetIndentBox() const
194 {
195 // XXX: Conversion to 'SPos' might be implementation-defined.
196 return Rect(LabelBrush.Margin.Left - SPos(UnitIndent) - 2, 0,
197 GetIndentBoxSize());
198 }
199 Rect
200 TreeList::GetIndentBoxBounds(size_t idx) const
201 {
202 // XXX: Conversion to 'SPos' might be implementation-defined.
203 return GetIndentBox() + Vec(SPos(GetIndentWidth(idx)),
204 (ptrdiff_t(idx) - ptrdiff_t(idxShared)) * SPos(GetItemHeight()));
205 }
206
207 SDst
208 TreeList::GetIndentWidth(IndexType idx) const
209 {
210 const auto i(indent_map.lower_bound(idx));
211
212 return SDst((i != indent_map.cend() ? i->second : 0) * UnitIndent);
213 // TODO: Use more concrete exception class.
214 // throw std::runtime_error("Invalid tree list state found.");
215 }
216 TreeList::NodePath
217 TreeList::GetNodePath(TreeList::IndexType idx) const
218 {
219 const auto i(indent_map.lower_bound(idx));
220
221 if(i != indent_map.cend())
222 {
223 auto indent(i->second);
224 vector<IndexType> seq(indent);
225 size_t n(0);
226 pair<IndexType, IndentType> last(idx, indent);
227
228 std::for_each(ystdex::make_reverse_iterator(i), indent_map.crend(),
229 [&](decltype(*indent_map.crbegin()) pr){
230 if(last.second <= indent)
231 {
232 YAssert(pr.first < last.first, "Invalid state found.");
233 n += last.first - pr.first;
234 }
235 if(pr.second < indent)
236 {
237 YAssert(indent > 0, "Invalid indent found");
238 seq[indent - 1] += n - 1;
239 yunseq(n = 0, indent = pr.second);
240 }
241 last = pr;
242 });
243 YAssert(indent > 0, "Invalid indent found");
244 seq[indent - 1] += n + last.first;
245 return seq;
246 }
247 return {};
248 }
249 const ValueNode&
250 TreeList::GetNodeRef(IndexType idx) const
251 {
252 return AccessNode(TreeRoot, GetNodePath(idx));
253 }
254
255 void
256 TreeList::Bind(size_t max_depth)
257 {
258 IndentMap imap;
259 ListType lst;
260 decltype(expanded) exp;
261 // TODO: Simplify using tuple or similar construct?
262 #if false
263 // XXX: These checks cannot be used since %propagate_on_container_swap or
264 // ISO C++17 %is_always_equal member of %allocator_traits
265 // is not used and container types are meeting nothrow swapping guarantee
266 // but not noexcept specificication yet.
267 static_assert(ystdex::is_nothrow_swappable<ListType>(),
268 "Invalid type found.");
269 static_assert(ystdex::is_nothrow_swappable<IndentMap>(),
270 "Invalid type found.");
271 static_assert(ystdex::is_nothrow_swappable<decltype(exp)>(),
272 "Invalid type found.");
273 #endif
274 IndentType indent(1);
275 auto index(IndexType(-1));
276 const auto bind_insert([&](size_t depth){
277 imap.emplace(index, indent);
278 indent = depth;
279 });
280
281 // TODO: Optimize implementation.
282 // TODO: Merge implementation with %ExpandOrCollapseNodeImpl?
283 bind_node(TreeRoot, [&, this](const ValueNode& node,
284 const NodePath& pth, size_t depth){
285 lst.push_back(ExtractText(node));
286 if(indent != depth)
287 bind_insert(depth);
288 if(depth < max_depth && !node.empty())
289 exp.insert(pth);
290 ++index;
291 }, [&](const NodePath&, size_t depth) ynothrow -> bool{
292 if(depth < max_depth)
293 return true;
294 bind_insert(depth);
295 return {};
296 }, NodePath());
297 if(index != IndexType(-1))
298 imap.emplace(index, indent);
299 std::swap(GetListRef(), lst),
300 std::swap(indent_map, imap),
301 std::swap(expanded, exp);
302 }
303
304 TreeList::NodeState
305 TreeList::ExpandOrCollapseNode(NodeState expected, size_t idx)
306 {
307 const auto st(QueryNodeState(idx));
308
309 if(st == expected)
310 ExpandOrCollapseNodeImpl(expected, idx);
311 return st;
312 }
313
314 void
315 TreeList::ExpandOrCollapseNodeImpl(NodeState st, size_t idx)
316 {
317 YAssert(QueryNodeState(idx) == st, "Invalid internal state found."),
318 YAssert(st != NodeState::None, "Invalid state argument found.");
319
320 const auto& branch_pth(GetNodePath(idx));
321
322 if(YB_UNLIKELY(branch_pth.empty()))
323 throw std::runtime_error("Invalid state found.");
324 // FIXME: Strong exception safety guarantee.
325 if(st == NodeState::Branch)
326 {
327 Expand(idx);
328 // TODO: Check state.
329 expanded.insert(branch_pth);
330
331 const auto& branch(AccessNode(TreeRoot, branch_pth));
332 auto i(ystdex::as_const(indent_map).lower_bound(idx));
333
334 YAssert(i != indent_map.cend(), "Invalid state found.");
335
336 const auto idt(i->second);
337 auto j(i);
338
339 if(i->first != idx)
340 j = indent_map.emplace_hint(i, idx, idt);
341 else
342 {
343 ++i;
344 YAssert(i == indent_map.cend() || i->second <= idt,
345 "Invalid state found.");
346 }
347
348 IndexType index(idx);
349 IndentType indent(idt + 1);
350 vector<pair<IndexType, IndentType>> vec_ins;
351 vector<String> text_list;
352 const auto bind_insert([&](size_t depth){
353 vec_ins.emplace_back(index, indent);
354 indent = depth;
355 });
356
357 // TODO: Optimize implementation.
358 // TODO: Merge implementation with %Bind?
359 bind_node(branch,
360 [&, this](const ValueNode& node, const NodePath&, size_t depth){
361 text_list.push_back(ExtractText(node));
362 if(indent != depth)
363 bind_insert(depth);
364 ++index;
365 }, [&, this](const NodePath& pth, size_t depth) -> bool{
366 if(ystdex::exists(expanded, pth))
367 return true;
368 bind_insert(depth);
369 return {};
370 }, branch_pth, idt);
371 YAssert(index != idx, "Invalid state found.");
372 vec_ins.emplace_back(index, indent);
373 YAssert(vec_ins.back().first > j->first,
374 "Invalid insertion sequence found");
375 // FIXME: Strong exception safety guarantee.
376 // NOTE: See $2014-09 @ %Documentation::Workflow.
377 {
378 // XXX: Use %std::make_move_iterator if proper.
379 vector<pair<IndentType, IndexType>>
380 vec(i, indent_map.cend());
381 const auto n(vec_ins.back().first - j->first);
382
383 for(auto& pr : vec)
384 pr.first += n;
385 i = ystdex::insert_reversed(indent_map,
386 indent_map.erase(i, indent_map.end()),
387 vec.rbegin(), vec.rend());
388 }
389 ystdex::insert_reversed(indent_map, i,
390 vec_ins.crbegin(), vec_ins.crend());
391
392 auto& lst(GetListRef());
393
394 // XXX: Reuse previous operation.
395 lst.insert(lst.cbegin() + ptrdiff_t(idx) + 1, std::make_move_iterator(
396 text_list.begin()), std::make_move_iterator(text_list.end()));
397 }
398 else
399 {
400 auto i(ystdex::as_const(indent_map).find(idx));
401
402 YAssert(i != indent_map.cend(), "Invalid state found.");
403
404 const auto idt(i->second);
405
406 if(++i != indent_map.cend())
407 {
408 auto& lst(GetListRef());
409
410 YAssert(idx < i->first, "Invalid state found.");
411 YAssert(i->first < lst.size(), "Invalid list found.");
412
413 auto j(std::find_if_not(i, indent_map.cend(),
414 [&, idt](decltype(*i) pr) ynothrow{
415 return idt < pr.second;
416 }));
417
418 const auto n(std::prev(j)->first - idx);
419
420 // XXX: Conversion to 'SPos' might be implementation-defined.
421 yunseq(ystdex::erase_n(lst, std::next(lst.cbegin(),
422 ptrdiff_t(idx + 1)), ptrdiff_t(n)), indent_map.erase(i, j));
423 #if true
424 {
425 // XXX: Use %std::make_move_iterator if proper.
426 vector<pair<IndentType, IndexType>>
427 vec(j, indent_map.cend());
428
429 for(auto& pr : vec)
430 pr.first -= n;
431 ystdex::insert_reversed(indent_map, indent_map.erase(j,
432 indent_map.end()), vec.rbegin(), vec.rend());
433 }
434 #else
435 // NOTE: See $2014-09 @ %Documentation::Workflow.
436 for(; j != indent_map.cend(); ++j)
437 j = ystdex::replace_value(indent_map, j->first,
438 [n](decltype(*indent_map.cbegin()) pr){
439 return make_pair(pr.first - n, pr.second);
440 });
441 #endif
442 // TODO: Check state.
443 expanded.erase(branch_pth);
444 Collapse(idx);
445 }
446 }
447 }
448
449 TreeList::NodeState
450 TreeList::QueryNodeState(IndexType idx) const
451 {
452 if(!GetNodeRef(idx).empty())
453 {
454 auto i(indent_map.find(idx));
455 const auto e(indent_map.cend());
456
457 if(i != e)
458 {
459 const auto indent(i->second);
460
461 // TODO: Optimize.
462 return ++i != e && i->second == indent + 1
463 && ystdex::exists(expanded, GetNodePath(idx))
464 ? NodeState::Expanded : NodeState::Branch;
465 }
466 }
467 return NodeState::None;
468 }
469
470
471 TreeView::TreeView(const Rect& r, const shared_ptr<ListType>& h)
472 : ListBox(r, unique_ptr<TextList>(new TreeList(Rect(r.GetSize()), h)))
473 {}
474 ImplDeDtor(TreeView)
475
476 } // namespace UI;
477
478 } // namespace YSLib;
479
ystdex::cpp2017::is_nothrow_swappable
Definition: swap.hpp:77
ystdex::cpp2014::make_reverse_iterator
reverse_iterator< _tIter > make_reverse_iterator(_tIter i)
构造反向迭代器。
Definition: iterator_op.hpp:110
ystdex::cpp2017::swap
void swap(optional< _type > &x, optional< _type > &y)
Definition: optional.h:888
YSLib::UI::UpdateView
YF_API void UpdateView(TextList &, bool is_active={})
更新文本列表视图。
Definition: ListControl.cpp:425
YSLib::UI::ynothrow
AView &y ynothrow
Definition: YWidgetView.cpp:47
YSLib::UI::TreeList
树形列表。
Definition: TreeView.h:51
YSLib::UI::TreeList::GetNodePath
YB_ATTR_nodiscard NodePath GetNodePath(IndexType) const
Definition: TreeView.cpp:217
ystdex::map::find
iterator find(const key_type &x)
Definition: map.hpp:619
YSLib::UI::TreeList::GetIndentBoxBounds
Rect GetIndentBoxBounds(IndexType) const
取相对部件的指定索引的缩进框边界。
Definition: TreeView.cpp:200
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
YSLib::UI::TreeList::TreeList
TreeList(const Rect &={}, const shared_ptr< ListType > &={}, const pair< Color, Color > &=FetchGUIConfiguration().Colors.GetPair(Styles::Highlight, Styles::HighlightText))
构造：使用指定边界、文本列表和高亮背景色/文本色对。
Definition: TreeView.cpp:67
YSLib::UI::TreeList::UnitIndent
SDst UnitIndent
单元缩进：指定在界面上显示层次的水平距离和缩进值的比。
Definition: TreeView.h:88
YSLib::UI::TreeList::NodeState
NodeState
节点状态。
Definition: TreeView.h:57
YSLib::Drawing::DrawArrow
YF_API void DrawArrow(const Graphics &, const Rect &, const Rect &, SDst=4, Rotation=RDeg0, Color=ColorSpace::Black, bool={})
在指定图形接口上下文上描画底边和坐标轴共线的等腰直角三角形箭头。
Definition: YStyle.cpp:202
YSLib::UI::CursorEventArgs
指针设备输入事件参数类。
Definition: YWidgetEvent.h:216
next
tidy_ptr< slink > next
Definition: memory_resource.cpp:223
YSLib::UI::TreeList::NodeState::Expanded
@ Expanded
YSLib::UI::TreeList::GetIndentWidth
const IndentMap indent_map YB_ATTR_nodiscard YB_PURE SDst GetIndentWidth(IndexType) const
Definition: TreeView.cpp:208
YSLib::UI::Widget::SPos
Renderer AView SPos
Definition: YWidget.h:463
YSLib::UI::TextList::SetSelected
void SetSelected(ListType::size_type)
按指定项目索引设置选中项目。
Definition: ListControl.cpp:275
YSLib::UI::AMUnitControlList::GetUnitRef
YB_ATTR_nodiscard YB_PURE IWidget & GetUnitRef() const ImplI(AMUnitList)
Definition: ListControl.cpp:50
ystdex::map::erase
iterator erase(iterator position)
Definition: map.hpp:563
ystdex::map::emplace
std::pair< iterator, bool > emplace(_tParams &&... args)
Definition: map.hpp:358
YSLib::Drawing::Padding::Left
SPos Left
空白距离：左、右、上、下。
Definition: YGDI.h:52
YSLib::UI::AMUnitList::idxShared
size_t idxShared
Definition: Viewer.h:211
YSLib::UI::TreeList::QueryNodeState
NodeState QueryNodeState(IndexType) const
查询指定索引的列表项对应的节点状态。
Definition: TreeView.cpp:450
CHRLib::f
f(d, s)
YSLib::UI::ImplDeDtor
ImplDeDtor(Thumb) void DecorateAsCloseButton(Thumb &tmb)
Definition: Button.cpp:125
ystdex::erase_n
_tCon::const_iterator erase_n(_tCon &con, typename _tCon::const_iterator i, typename _tCon::difference_type n)
删除指定容器中指定迭代器起始指定数量的元素。
Definition: container.hpp:597
ystdex::map
映射容器。
Definition: map.hpp:79
YSLib::Drawing::Rect::Contains
YB_ATTR_nodiscard YB_PURE bool Contains(SPos px, SPos py) const ynothrow
判断点 (px, py) 是否在矩形内或边上。
Definition: YGDIBase.cpp:91
YSLib::UI::BackgroundPriority
yconstexpr const EventPriority BackgroundPriority(0xC0)
用户界面绘制优先级。
ystdex::replace_value
auto replace_value(_tAssocCon &con, const _tKey &k, _func f) -> decltype(con.emplace_hint(con.erase(con.find(k)), f(*con.find(k))))
替换关联容器的值。
Definition: container.hpp:774
YSLib::UI::Invalidate
YF_API void Invalidate(IWidget &, const Rect &)
无效化：使相对部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: YWidget.cpp:108
ystdex::map::emplace_hint
iterator emplace_hint(const_iterator position, _tParams &&... args)
Definition: map.hpp:365
YSLib::UI::TreeList::TreeRoot
ValueNode TreeRoot
数据源。
Definition: TreeView.h:86
YSLib::UI::TreeList::NodeState::None
@ None
YSLib::UI::TreeList::Expand
GEvent< void(IndexType)> Expand
展开节点前的回调。
Definition: TreeView.h:70
YSLib::YAssert
YAssert(!(v< Deref(a)), "Value less than lower bound found.")
ystdex::map::lower_bound
iterator lower_bound(const key_type &x)
Definition: map.hpp:672
ystdex::map::crbegin
const_reverse_iterator crbegin() const
Definition: map.hpp:283
YSLib::Text::String
YSLib 标准字符串（使用 UCS-2 作为内部编码）。
Definition: YString.h:47
YSLib::ValueNode
值类型节点。
Definition: ValueNode.h:73
YSLib::UI::MTextList::ListType
vector< ItemType > ListType
列表类型。
Definition: ListControl.h:143
YSLib::UI::TreeView::TreeView
TreeView(const Rect &={}, const shared_ptr< ListType > &={})
Definition: TreeView.cpp:471
YSLib::Drawing::GBinaryGroup< SPos >
YSLib::i
return i
Definition: YCoreUtilities.h:177
ystdex::exists
bool exists(const _tCon &con, const _tKey &key)
判断指定的容器中存在指定的键。
Definition: container.hpp:462
YSLib::Drawing::GetSize
dst GetSize()
platform::KeyCodes
本机按键编码。
Definition: Keys.h:204
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1535
ystdex::map::end
iterator end()
Definition: map.hpp:238
platform::SDst
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:44
YSLib::UI::TreeView
带滚动条的树形视图。
Definition: TreeView.h:220
utility.hpp
实用设施。
YSLib::UI::MLabel::ForeColor
Color ForeColor
默认前景色。
Definition: Label.h:77
YSLib::UI::TreeList::GetIndentBox
Rect GetIndentBox() const
取相对单元部件的基准缩进框边界。
Definition: TreeView.cpp:193
YSLib::UI::TreeList::NodeState::Branch
@ Branch
YSLib::UI::KeyEventArgs
按键输入事件参数类。
Definition: YWidgetEvent.h:193
platform::containers::vector
std::vector< _type, _tAlloc > vector
Definition: Container.h:102
YSLib::Drawing::GBinaryGroup::X
_type X
分量。
Definition: YGDIBase.h:305
YSLib::UI::TreeList::indent_map
IndentMap indent_map
列表项位置索引。
Definition: TreeView.h:107
YSLib::UI::e
void e
Definition: YWidget.h:356
YSLib::UI::empty
!sv empty() &&sv.front() !
YSLib::Drawing::Rect
屏幕标准矩形：表示屏幕矩形区域。
Definition: YGDIBase.h:788
YSLib::UI::ListBox
带滚动条的文本列表框。
Definition: ComboList.h:50
YSLib::UI::TreeList::ExtractText
function< String(const ValueNode &)> ExtractText
提取文本。
Definition: TreeView.h:76
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:46
YSLib::UI::TreeList::IndentType
size_t IndentType
缩进类型：用于表示视图中项目的层次。
Definition: TreeView.h:54
YModules.h
YSLib 用户界面模块配置文件。
YSLib::UI::TextList
文本列表。
Definition: ListControl.h:205
YSLib::UI::MLabel::Margin
Drawing::Padding Margin
文本和容器的间距。
Definition: Label.h:79
YSLib::UI::AMUnitList::GetItemHeight
YB_ATTR_nodiscard SDst GetItemHeight() const
取项目行高：调用 GetItemHeightCore 取结果。
Definition: Viewer.cpp:166
YSLib::UI::TreeList::ExtractNodeName
static String ExtractNodeName(const ValueNode &)
Definition: TreeView.cpp:187
YSLib::UI::MTextList::IndexType
typename ListType::size_type IndexType
索引类型。
Definition: ListControl.h:145
YSLib::Drawing::DrawCornerArrow
YF_API void DrawCornerArrow(const Graphics &, const Rect &, const Point &, SDst=4, Rotation=RDeg0, Color=ColorSpace::Black, bool={})
在指定图形接口上下文上描画腰和坐标轴共线的等腰直角三角形箭头。
Definition: YStyle.cpp:230
YSLib::Drawing::RDeg0
@ RDeg0
Definition: YGDIBase.h:1146
YSLib::UI::TreeList::tmp_margin_left
SPos tmp_margin_left
Definition: TreeView.h:108
YSLib::UI::PaintEventArgs
部件绘制参数。
Definition: YWidgetEvent.h:330
YSLib::UI::TreeList::Collapse
GEvent< void(IndexType)> Collapse
收缩节点后的回调。
Definition: TreeView.h:68
ystdex::map::cend
const_iterator cend() const
Definition: map.hpp:277
YSLib::UI::TreeList::expanded
set< NodePath > expanded
判断是否已经展开的索引。
Definition: TreeView.h:117
ystdex::insert_reversed
_tCon::const_iterator insert_reversed(_tCon &con, typename _tCon::const_iterator i, _tIn first, _tIn last)
逆向插入范围到容器的指定位置。
Definition: container.hpp:202
YSLib::UI::TreeList::NodePath
vector< IndexType > NodePath
Definition: TreeView.h:65
YSLib::UI::TreeList::Bind
void Bind(size_t=size_t(-1))
绑定数据源，展开不超过指定深度的节点。
Definition: TreeView.cpp:256
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:828
YSLib::UI::MTextList::LabelBrush
MLabel LabelBrush
Definition: ListControl.h:153
YSLib::UI::TreeList::CursorOverColor
Color CursorOverColor
响应 CursorOver 事件时节点分支图标的颜色。
Definition: TreeView.h:81
YSLib::size_t
YF_API const char size_t
Definition: YException.h:149
YSLib::Drawing::Vec
GBinaryGroup< SPos > Vec
屏幕二维向量（直角坐标表示）。
Definition: YGDIBase.h:527
ystdex::map::crend
const_reverse_iterator crend() const
Definition: map.hpp:289
platform::SPos
std::int16_t SPos
屏幕坐标度量。
Definition: Video.h:43
ystdex::path_category::node
@ node
YSLib::UI::FetchGUIState
GUIState & FetchGUIState() ynothrow
Definition: YGUI.cpp:506
YSLib::UI::TreeList::idxCursorOver
size_t idxCursorOver
最近响应 CursorOver 的项的索引。
Definition: TreeView.h:96
YSLib::UI::TreeList::GetNodeRef
YB_ATTR_nodiscard const ValueNode & GetNodeRef(IndexType) const
Definition: TreeView.cpp:250
ystdex::map::cbegin
const_iterator cbegin() const
Definition: map.hpp:271
YSLib::UI::TreeList::CollapseNode
CollapseNode
Definition: TreeView.h:175
YSLib::AccessNode
YB_ATTR_nodiscard YF_API YB_PURE ValueNode & AccessNode(ValueNode::Container *, const string &)
访问节点。
Definition: ValueNode.cpp:102
YSLib::UI::Widget::SDst
SDst
Definition: YWidget.h:458
ystdex::cpp2017::as_const
add_const_t< _type > & as_const(_type &t)
转换 const 引用。
Definition: utility.hpp:77