YSTest: ComboList.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

ComboList.cpp
浏览该文件的文档.
1 /*
2 © 2011-2016 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_ComboList
30 #include YFM_YSLib_UI_YStyle
31 #include YFM_YSLib_UI_YPanel
32 #include YFM_YSLib_Service_TextLayout // for FetchMaxTextWidth;
33 #include <ystdex/scope_guard.hpp> // for ystdex::swap_guard;
34
35 namespace YSLib
36 {
37
38 namespace UI
39 {
40
41 namespace
42 {
43
44 const SDst defMinScrollBarWidth(16);
45
46
51 void
52 Detach(observer_ptr<IWidget> p_con, IWidget& wgt)
53 {
54 if(const auto p = dynamic_cast<Panel*>(p_con.get()))
55 {
56 Invalidate(wgt);
57 *p -= wgt;
58 }
59 }
60
61 } // unnamed namespace;
62
63
64 ListBox::ListBox(const Rect& r, unique_ptr<TextList> p_textlist)
65 : ScrollableContainer(r),
66 pTextList(std::move(p_textlist))
67 {
68 Background = nullptr,
69 SetContainerPtrOf(GetTextListRef(), make_observer(this)),
70 vsbVertical.GetTrackRef().Scroll += [this](ScrollEventArgs&& e){
71 GetTextListRef().LocateViewPosition(SDst(round(e.GetValue())));
72 },
73 GetTextListRef().ViewChanged += [this](ViewArgs&& e){
74 if(!e.Value && GetWidth() > defMinScrollBarWidth)
75 {
76 const Size view_arena(GetWidth() - defMinScrollBarWidth,
77 GetTextListRef().GetFullViewHeight());
78
79 SetSizeOf(GetTextListRef(), FixLayout(view_arena));
80 if(view_arena.Height > GetTextListRef().GetHeight())
81 {
82 vsbVertical.SetSmallDelta(GetTextListRef().GetItemHeight());
83 vsbVertical.SetMaxValue(view_arena.Height
84 - GetTextListRef().GetHeight());
85 vsbVertical.SetLargeDelta(GetTextListRef().GetHeight());
86 vsbVertical.SetValue(GetTextListRef().GetViewPosition());
87 }
88 }
89 },
90 RequestFocus(GetTextListRef());
91 // NOTE: Text state refreshed for correctly showing scroll bars.
92 ResetView();
93 }
94 ListBox::ListBox(const Rect& r, const shared_ptr<ListType>& h)
95 : ListBox(r, make_unique<TextList>(Rect(r.GetSize()), h))
96 {}
97 ImplDeDtor(ListBox)
98
99 void
100 ListBox::ResizeForPreferred(const Size& sup, Size s)
101 {
102 if(s.Width == 0)
103 s.Width = FetchMaxTextWidth(GetTextListRef().LabelBrush.Font,
104 GetTextListRef().GetList().cbegin(),
105 GetTextListRef().GetList().cend())
106 + GetHorizontalOf(GetTextListRef().LabelBrush.Margin);
107 if(s.Height == 0)
108 s.Height = GetTextListRef().GetFullViewHeight();
109 if(sup.Width != 0 && s.Width > sup.Width)
110 s.Width = sup.Width;
111 if(sup.Height != 0 && s.Height > sup.Height)
112 {
113 yunseq(s.Width += defMinScrollBarWidth, s.Height = sup.Height);
114 if(sup.Width != 0 && sup.Width < s.Width)
115 s.Width = sup.Width;
116 }
117 SetSizeOf(*this, s);
118 SetSizeOf(GetTextListRef(), FixLayout(s));
119 UpdateView();
120 }
121
122
123 FileBox::FileBox(const Rect& r)
124 : ListBox(r), pthDirectory()
125 {
126 GetConfirmed() += [this](IndexEventArgs&& e){
127 if(Contains(e))
128 SetPath(GetPath(e.Value));
129 };
130 ListItems();
131 UpdateView();
132 }
133 ImplDeDtor(FileBox)
134
135 IO::Path
136 FileBox::GetPath() const
137 {
138 return IsSelected() ? GetPath(GetSelectedIndex()) : pthDirectory;
139 }
140 IO::Path
141 FileBox::GetPath(typename ListType::size_type i) const
142 {
143 YAssert(i < GetList().size(), "Invalid index found.");
144 return pthDirectory / IO::Path(GetList()[i]);
145 }
146
147 bool
148 FileBox::operator=(const IO::Path& d)
149 {
150 if(VerifyDirectory(d))
151 {
152 pthDirectory = d;
153 return true;
154 }
155 return {};
156 }
157 bool
158 FileBox::operator/=(const String& d)
159 {
160 return *this = pthDirectory / d;
161 }
162 bool
163 FileBox::operator/=(const IO::Path& d)
164 {
165 return *this = pthDirectory / d;
166 }
167
168 bool
169 FileBox::SetPath(const IO::Path& pth)
170 {
171 ystdex::swap_guard<IO::Path> gd(true, pthDirectory, pthDirectory);
172
173 try
174 {
175 if(operator=(pth))
176 {
177 GetListRef() = ListItems();
178 gd.dismiss();
179 ResetView();
180 return true;
181 }
182 }
183 // TODO: Custom platform-dependent name converting.
184 CatchExpr(std::system_error& e, YTraceDe(Warning,
185 "Failed setting path."), ExtractAndTrace(e, Warning))
186 return {};
187 }
188
189 FileBox::ListType
190 FileBox::ListItems() const
191 {
192 ListType lst;
193
194 ListFiles(pthDirectory, lst);
195 return lst;
196 }
197
198
199 DropDownList::DropDownList(const Rect& r, const shared_ptr<ListType>& h)
200 : Button(r),
201 lbContent({}, h)
202 {
203 const auto detacher([this](UIEventArgs&& e){
204 if(!dynamic_cast<RoutedEventArgs*>(&e))
205 DetachTopWidget();
206 });
207
208 yunseq(
209 Margin.Left = 4,
210 Margin.Right = 18,
211 HorizontalAlignment = TextAlignment::Left,
212 lbContent.GetView().DependencyPtr = make_observer(this),
213 FetchEvent<TouchDown>(*this) += [this](CursorEventArgs&& e){
214 if(!FetchContainerPtr(lbContent))
215 {
216 Point pt;
217
218 if(const auto p
219 = dynamic_cast<Panel*>(&FetchTopLevel(e.GetSender(), pt)))
220 {
221 // NOTE: Get height of top widget, top and bottom spaces.
222 const SDst h0(GetSizeOf(*p).Height);
223 // XXX: Conversion to 'SPos' might be implementation-defined.
224 const SDst h1(SDst(max<SPos>(0, pt.Y))), h2(SDst(max<SPos>(0,
225 SPos(h0) - pt.Y - SPos(GetHeight()))));
226
227 if(IsInOpenInterval(h1, h0) || IsInOpenInterval(h2, h0))
228 {
229 lbContent.ResizeForPreferred(Size(0, max(h1, h2)),
230 Size(GetWidth(), 0));
231
232 const SDst h3(lbContent.GetHeight());
233
234 // NOTE: Bottom space is preferred.
235 // XXX: Conversion to 'SPos' might be
236 // implementation-defined.
237 pt.Y += SPos(h2 < h3 ? -h3 : GetHeight());
238 SetLocationOf(lbContent, pt);
239 lbContent.AdjustViewLength();
240 {
241 const auto& lst(lbContent.GetList());
242 const auto i(std::find(lst.cbegin(), lst.cend(), Text));
243
244 if(i != lst.cend())
245 lbContent.SetSelected(size_t(i - lst.cbegin()));
246 else
247 lbContent.ClearSelected();
248 }
249 p->Add(lbContent, 224U); // TODO: Use non-magic number.
250 RequestFocusCascade(lbContent);
251 e.Handled = true;
252 }
253 }
254 }
255 },
256 FetchEvent<LostFocus>(*this) += detacher,
257 FetchEvent<LostFocus>(lbContent) += detacher,
258 lbContent.GetConfirmed() += [this](IndexEventArgs&& e){
259 YAssert(e.Value < lbContent.GetList().size(), "Invalid index found.");
260
261 Text = lbContent.GetList()[e.Value];
262 // XXX: This seems to be redundant if the detached top widget would be
263 // always invalidated, however there is no such guarantee.
264 Invalidate(e.GetSender()),
265 Invalidate(*this);
266 DetachTopWidget();
267 }
268 );
269 }
270 DropDownList::~DropDownList()
271 {
272 DetachTopWidget();
273 }
274
275 void
276 DropDownList::DetachTopWidget()
277 {
278 Detach(FetchContainerPtr(lbContent), lbContent);
279 }
280
281 void
282 DropDownList::Refresh(PaintEventArgs&& e)
283 {
284 const auto cs(GetCursorState());
285
286 if(FetchContainerPtr(lbContent))
287 csCurrent = CursorState::Pressed;
288 Button::Refresh(std::move(e));
289 csCurrent = cs;
290 // XXX: Conversion to 'SPos' might be implementation-defined.
291 DrawArrow(e.Target, e.ClipArea, Rect(e.Location.X + SPos(GetWidth()) - 16,
292 e.Location.Y, Size(16, GetHeight())), 4, RDeg270, ForeColor);
293 }
294
295 } // namespace UI;
296
297 } // namespace YSLib;
298
YSLib::UI::TextAlignment::Left
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
YSLib::Drawing::GetHeight
tr GetHeight())) inline PDefH(void
按字体高度和行距调整文本区域的底边距。
platform_ex::Detach
_iCOM * Detach(COMPtr< _iCOM > &ptr) ynothrow
Definition: COM.h:396
YSLib::UI::GValueEventArgs
简单 UI 事件参数类。
Definition: YWidgetEvent.h:299
YSLib::UI::SetSizeOf
YF_API void SetSizeOf(IWidget &, const Size &)
设置部件大小。
Definition: YWidget.cpp:83
YSLib::Drawing::GBinaryGroup::Y
_type Y
分量。
Definition: YGDIBase.h:63
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
YSLib::UI::FileBox::ListItems
ListType ListItems() const
遍历目录中的项目，更新至列表。 异常中立：文件系统访问操作异常。
Definition: ComboList.cpp:190
UI
YSLib::UI::CursorEventArgs
指针设备输入事件参数类。
Definition: YWidgetEvent.h:210
YSLib::UI::Widget::Width
Renderer AView Width
Definition: YWidget.h:458
ystdex::make_observer
observer_ptr< _type > make_observer(_type *p)
Definition: pointer.hpp:326
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::Button
按钮。
Definition: Button.h:127
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
Text
YSLib::IO::ListFiles
void ListFiles(const Path &pth, vector< String > &lst)
Definition: YSLib/Service/FileSystem.cpp:193
YSLib::UI::wgt
IWidget & wgt
Definition: YControl.h:112
YSLib::IsInOpenInterval
YB_STATELESS bool IsInOpenInterval(_type i, _type b) ynothrow
判断 i 是否在开区间 (_type(0), b) 内。
Definition: YCoreUtilities.h:136
ystdex::cpp2014::make_unique
enable_if_t<!is_array< _type >::value, std::unique_ptr< _type > > make_unique(_tParams &&...args)
使用 new 和指定参数构造指定类型的 std::unique_ptr 对象。
Definition: memory.hpp:852
ystdex::cpp2014::cend
auto cend(const _tRange &c) -> decltype(std::end(c))
Definition: range.hpp:87
ystdex::max
const _type & max(const _type &a, const _type &b, _fComp comp=less< _type >())
取较大的元素。
Definition: algorithm.hpp:549
YSLib::UI::FetchTopLevel
YF_API IWidget & FetchTopLevel(IWidget &)
取指定部件的顶层部件。
Definition: YUIContainer.cpp:41
YSLib::UI::DropDownList::Refresh
void Refresh(PaintEventArgs &&) override
分离顶层子部件。
Definition: ComboList.cpp:282
YSLib::UI::TextList
文本列表。
Definition: ListControl.h:201
YSLib::YAssert
YAssert(!(v< Deref(a)),"Value less than lower bound found.")
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1022
YSLib::UI::ListBox::GetTextListRef
ListType::size_type i const ynothrow GetTextListRef()) DefGetter(
项目选中确定事件。
YSLib::UI::Invalidate
YF_API void Invalidate(IWidget &, const Rect &)
无效化：使相对部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: YWidget.cpp:108
YSLib::UI::DropDownList::DropDownList
DropDownList(const Rect &={}, const shared_ptr< ListType > &={})
Definition: ComboList.cpp:199
YSLib::UI::RequestFocusCascade
YF_API void RequestFocusCascade(IWidget &)
级联请求部件及上层容器焦点。
Definition: YFocus.cpp:137
YSLib::IO::VerifyDirectory
bool VerifyDirectory(const char *path)
Definition: YSLib/Service/FileSystem.cpp:95
platform::SDst
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:44
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YSLib::UI::Thumb::ForeColor
Color ForeColor
默认前景色。
Definition: Button.h:63
YSLib::UI::SetLocationOf
YF_API void SetLocationOf(IWidget &, const Point &)
设置部件左上角所在位置（相对容器的偏移坐标）。
Definition: YWidget.cpp:76
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
YSLib::UI::ListBox::Contains
Contains
Definition: ComboList.h:87
ystdex::cpp2014::cbegin
auto cbegin(const _tRange &c) -> decltype(std::begin(c))
Definition: range.hpp:79
IO
YSLib::UI::FileBox::GetPath
DefGetter(const ynothrow, const IO::Path &, Directory, pthDirectory) IO IO::Path GetPath(typename ListType::size_type i) const
取目录的完整路径。
Definition: ComboList.h:225
YSLib::i
return i
Definition: YCoreUtilities.h:176
YSLib::UI::FileBox::FileBox
FileBox(const Rect &={})
Definition: ComboList.cpp:123
ystdex::state_guard::dismiss
void dismiss()
Definition: scope_guard.hpp:318
YSLib::UI::FileBox::operator=
bool operator=(const IO::Path &)
导航至绝对路径。
platform::SPos
std::int16_t SPos
屏幕坐标度量。
Definition: Video.h:43
YSLib::UI::PaintEventArgs
部件绘制参数。
Definition: YWidgetEvent.h:323
YSLib::UI::Thumb::csCurrent
CursorState csCurrent
指针设备光标状态。
Definition: Button.h:70
YSLib::UI::ScrollEventArgs
滚动事件参数类。
Definition: Scroll.h:67
YSLib::UI::e
void e
Definition: YWidget.h:352
ystdex::state_guard
使用临时状态暂存对象的作用域守护。
Definition: scope_guard.hpp:273
YSLib::Drawing::GBinaryGroup< SPos >
YSLib::UI::DropDownList::lbContent
ListBox lbContent
Definition: ComboList.h:265
YModules.h
YSLib::UI::ListBox
带滚动条的文本列表框。
Definition: ComboList.h:49
YSLib::UI::ScrollableContainer::vsbVertical
ScrollBar vsbVertical
Definition: Scroll.h:419
YSLib::Drawing::Rect
屏幕标准矩形：表示屏幕矩形区域。
Definition: YGDIBase.h:540
YSLib::Drawing::Size::Height
SDst Height
宽和高。
Definition: YGDIBase.h:302
YSLib::UI::ATrack::Scroll
GEvent< void(ScrollEventArgs &&)> Scroll
滚动事件。
Definition: Scroll.h:167
std
Definition: memory.hpp:1183
YSLib::UI::ScrollableContainer
带滚动条的容器。
Definition: Scroll.h:407
YSLib::UI::Widget::Background
HBrush Background
背景。
Definition: YWidget.h:391
platform::Descriptions::Warning
Definition: YCommon.h:167
YSLib::Drawing::FetchMaxTextWidth
SDst FetchMaxTextWidth(const Font &font, _tIn first, _tIn last)
取指定字体显示的迭代器范围中的文本的最大宽度。
Definition: TextLayout.h:330
scope_guard.hpp
作用域守护。
YSLib::UI::FileBox::pthDirectory
IO::Path pthDirectory
目录的完整路径。
Definition: ComboList.h:176
YSLib::Drawing::Size
屏幕区域大小。
Definition: YGDIBase.h:293
YSLib::UI::UIEventArgs
用户界面事件参数基类。
Definition: YWidgetEvent.h:59
YSLib::UI::ListBox::ListBox
ListBox(const Rect &, unique_ptr< TextList >)
Definition: ComboList.cpp:64
YSLib::UI::FileBox::operator/=
bool operator/=(const String &)
导航至子目录。
Definition: ComboList.cpp:158
YSLib::UI::Widget::SDst
SDst
Definition: YWidget.h:454
YSLib::UI::SPos
const IWidget &wgt SPos
Definition: YWidget.h:109
YSLib::IO::Path
路径。
Definition: YSLib/Service/FileSystem.h:214
YSLib::UI::IndexEventArgs
GValueEventArgs< size_t > IndexEventArgs
索引事件。
Definition: ListControl.h:47
CHRLib::d
_tDst * d
Definition: CharacterProcessing.h:139
YSLib::UI::ScrollBar::GetTrackRef
ATrack GetTrackRef()) DefGetterMem(const ynothrow
ystdex::size
auto size(const _tRange &c) -> decltype(c.size())
类容器访问。
Definition: range.hpp:233
YSLib::UI::Widget::Refresh
virtual void Refresh(PaintEventArgs &&)
刷新：按指定参数绘制界面并更新状态。
Definition: YWidget.cpp:264
YSLib::Drawing::RDeg270
Definition: YGDIBase.h:900
YSLib::UI::FileBox::SetPath
bool SetPath(const IO::Path &)
设置路径，若成功则刷新列表。
Definition: ComboList.cpp:169
YSLib::UI::GetSizeOf
pt pt Y const IWidget &wgt const IWidget &wgt GetSizeOf
无效化：使相对部件的子部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: YWidget.h:161
YSLib::UI::UpdateView
void UpdateView(TextList &tl, bool is_active)
Definition: ListControl.cpp:425
YSLib::UI::CursorState::Pressed
YSLib::UI::ListBox::ListType
TextList::ListType ListType
Definition: ComboList.h:52
YSLib::UI::ListBox::ResetView
ListType::size_type i const ynothrow GEvent< void(IndexEventArgs)> const ListType ListType GEvent< void(IndexEventArgs)> TextList GEvent< void(ViewArgs)> const shared_ptr< ListType > ListType::size_type i ResetView
Definition: ComboList.h:148
YSLib::ExtractAndTrace
YF_API void ExtractAndTrace(const std::exception &, RecordLevel=Err) ynothrow
使用 TraceException 展开和跟踪异常类型和信息。
YSLib::UI::FileBox
文件列表框。
Definition: ComboList.h:169
CHRLib::p
const auto p(d)
YSLib::Text::String
YSLib 标准字符串（使用 UCS-2 作为内部编码）。
Definition: YString.h:46
YSLib::UI::ImplDeDtor
ImplDeDtor(Thumb) void DecorateAsCloseButton(Thumb &tmb)
Definition: Button.cpp:125