YSTest: ComboList.cpp 源文件

YSTest PreAlpha_b400_20130424 The YSLib Test Project

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

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
ComboList.cpp
浏览该文件的文档.
1 ﻿/*
2 Copyright by FrankHB 2011 - 2013.
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/ComboList.h"
29 #include "YSLib/UI/ystyle.h"
30 #include "YSLib/UI/ypanel.h"
31
32 YSL_BEGIN
33
34 YSL_BEGIN_NAMESPACE(UI)
35
36 namespace
37 {
38 const SDst defMinScrollBarWidth(16);
39 // const SDst defMinScrollBarHeight(16); //!< 默认最小滚动条高。
40
41
46 void
47 Detach(IWidget* pCon, IWidget& wgt)
48 {
49 if(const auto p = dynamic_cast<Panel*>(pCon))
50 {
51 Invalidate(wgt);
52 *p -= wgt;
53 }
54 }
55 }
56
57
58 ListBox::ListBox(const Rect& r, const shared_ptr<ListType>& h)
59 : ScrollableContainer(r),
60 tlContent(Rect(r.GetSize()), h)
61 {
62 Background = nullptr,
63 SetContainerPtrOf(tlContent, this),
64 vsbVertical.GetTrack().GetScroll() += [this](ScrollEventArgs&& e){
65 tlContent.LocateViewPosition(SDst(round(e.GetValue())));
66 },
67 tlContent.GetViewChanged() += [this](ViewArgs&& e){
68 if(!e.Value && GetWidth() > defMinScrollBarWidth)
69 {
70 const Size view_arena(GetWidth() - defMinScrollBarWidth,
71 tlContent.GetFullViewHeight());
72
73 SetSizeOf(tlContent, FixLayout(view_arena));
74 if(view_arena.Height > tlContent.GetHeight())
75 {
76 vsbVertical.SetSmallDelta(tlContent.GetItemHeight());
77 vsbVertical.SetMaxValue(view_arena.Height
78 - tlContent.GetHeight());
79 vsbVertical.SetLargeDelta(tlContent.GetHeight());
80 vsbVertical.SetValue(tlContent.GetViewPosition());
81 }
82 }
83 },
84 RequestFocus(tlContent);
85 //刷新文本状态，防止第一次绘制时无法正确决定是否需要滚动条。
86 tlContent.RefreshTextState();
87 }
88
89 void
90 ListBox::ResizeForPreferred(const Size& sup, Size s)
91 {
92 if(s.Width == 0)
93 s.Width = tlContent.GetMaxTextWidth()
94 + GetHorizontalOf(tlContent.Margin);
95 if(s.Height == 0)
96 s.Height = tlContent.GetFullViewHeight();
97 if(sup.Width != 0 && s.Width > sup.Width)
98 s.Width = sup.Width;
99 if(sup.Height != 0 && s.Height > sup.Height)
100 {
101 yunseq(s.Width = s.Width + defMinScrollBarWidth, s.Height = sup.Height);
102 if(sup.Width != 0 && sup.Width < s.Width)
103 s.Width = sup.Width;
104 }
105 SetSizeOf(*this, s);
106 SetSizeOf(tlContent, FixLayout(s));
107 UpdateView();
108 }
109
110
111 FileBox::FileBox(const Rect& r)
112 : FileList(), ListBox(r, GetListPtr())
113 {
114 GetConfirmed() += [this](IndexEventArgs&& e){
115 if(Contains(e) && bool(*this /= GetList()[e.Value]))
116 ResetView();
117 };
118 ListItems();
119 UpdateView();
120 }
121
122 IO::Path
123 FileBox::GetPath() const
124 {
125 return IsSelected() ? Directory / (GetList()[GetSelectedIndex()])
126 : Directory;
127 }
128
129 bool
130 FileBox::SetPath(const IO::Path& pth)
131 {
132 if(FileList::operator=(pth))
133 {
134 UpdateView();
135 return true;
136 }
137 return false;
138 }
139
140
141 DropDownList::DropDownList(const Rect& r, const shared_ptr<ListType>& h)
142 : Button(r),
143 lbContent({}, h)
144 {
145 const auto detacher([this](UIEventArgs&&){
146 DetachTopWidget();
147 });
148
149 yunseq(
150 Margin.Left = 4,
151 Margin.Right = 18,
152 HorizontalAlignment = TextAlignment::Left,
153 lbContent.GetView().DependencyPtr = this,
154 FetchEvent<TouchDown>(*this) += [this](TouchEventArgs&& e){
155 if(!FetchContainerPtr(lbContent))
156 {
157 Point pt;
158
159 if(const auto p = dynamic_cast<Panel*>(
160 &FetchTopLevel(*this, pt)))
161 {
162 // NOTE: Get height of top widget, top and bottom spaces.
163 const SDst h0(GetSizeOf(*p).Height);
164 const SDst h1(max<SPos>(0, pt.Y)), h2(max<SPos>(0, h0 - pt.Y
165 - GetHeight()));
166
167 if(IsInOpenInterval(h1, h0) || IsInOpenInterval(h2, h0))
168 {
169 lbContent.ResizeForPreferred(Size(0, max(h1, h2)),
170 Size(GetWidth(), 0));
171
172 const SDst h(lbContent.GetHeight());
173
174 // NOTE: Bottom space is preferred.
175 pt.Y += h2 < h ? -h : GetHeight();
176 SetLocationOf(lbContent, pt);
177 lbContent.AdjustViewLength();
178 {
179 const auto idx(lbContent.Find(Text));
180
181 if(idx + 1 != 0)
182 lbContent.SetSelected(idx);
183 else
184 lbContent.ClearSelected();
185 }
186 p->Add(lbContent, 224U); // TODO: Use non-magic number.
187 RequestFocus(lbContent);
188 e.Handled = true;
189 }
190 }
191 }
192 },
193 FetchEvent<LostFocus>(*this) += detacher,
194 FetchEvent<LostFocus>(lbContent) += detacher,
195 lbContent.GetConfirmed() += [this](IndexEventArgs&& e){
196 YAssert(e.Value < lbContent.GetList().size(),
197 "Invalid index found.");
198
199 Text = lbContent.GetList()[e.Value];
200 Invalidate(*this),
201 DetachTopWidget();
202 }
203 );
204 }
205 DropDownList::~DropDownList()
206 {
207 DetachTopWidget();
208 }
209
210 void
211 DropDownList::DetachTopWidget()
212 {
213 Detach(FetchContainerPtr(lbContent), lbContent);
214 }
215
216 void
217 DropDownList::Refresh(PaintEventArgs&& e)
218 {
219 bool b(bPressed);
220
221 bPressed = bPressed || FetchContainerPtr(lbContent);
222 Button::Refresh(std::move(e));
223 bPressed = b;
224 DrawArrow(e.Target, Rect(e.Location + Vec(GetWidth() - 16, 0),
225 Size(16, GetHeight())), 4, RDeg270, ForeColor);
226 }
227
228 YSL_END_NAMESPACE(UI)
229
230 YSL_END
231