YSTest  PreAlpha_b500_20140530
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
ComboList.cpp
浏览该文件的文档.
1 /*
2  © 2011-2014 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 
33 namespace YSLib
34 {
35 
36 namespace UI
37 {
38 
39 namespace
40 {
41  const SDst defMinScrollBarWidth(16);
42 // const SDst defMinScrollBarHeight(16); //!< 默认最小滚动条高。
43 
44 
49  void
50  Detach(IWidget* pCon, IWidget& wgt)
51  {
52  if(const auto p = dynamic_cast<Panel*>(pCon))
53  {
54  Invalidate(wgt);
55  *p -= wgt;
56  }
57  }
58 }
59 
60 
61 ListBox::ListBox(const Rect& r, const shared_ptr<ListType>& h)
63  tlContent(Rect(r.GetSize()), h)
64 {
65  Background = nullptr,
66  SetContainerPtrOf(tlContent, this),
67  vsbVertical.GetTrackRef().GetScroll() += [this](ScrollEventArgs&& e){
68  tlContent.LocateViewPosition(SDst(round(e.GetValue())));
69  },
70  tlContent.ViewChanged += [this](ViewArgs&& e){
71  if(!e.Value && GetWidth() > defMinScrollBarWidth)
72  {
73  const Size view_arena(GetWidth() - defMinScrollBarWidth,
74  tlContent.GetFullViewHeight());
75 
76  SetSizeOf(tlContent, FixLayout(view_arena));
77  if(view_arena.Height > tlContent.GetHeight())
78  {
79  vsbVertical.SetSmallDelta(tlContent.GetItemHeight());
80  vsbVertical.SetMaxValue(view_arena.Height
81  - tlContent.GetHeight());
82  vsbVertical.SetLargeDelta(tlContent.GetHeight());
83  vsbVertical.SetValue(tlContent.GetViewPosition());
84  }
85  }
86  },
87  RequestFocus(tlContent);
88  //刷新文本状态,防止第一次绘制时无法正确决定是否需要滚动条。
89  tlContent.RefreshTextState();
90 }
91 
92 void
93 ListBox::ResizeForPreferred(const Size& sup, Size s)
94 {
95  if(s.Width == 0)
96  s.Width = tlContent.GetMaxTextWidth()
97  + GetHorizontalOf(tlContent.Margin);
98  if(s.Height == 0)
99  s.Height = tlContent.GetFullViewHeight();
100  if(sup.Width != 0 && s.Width > sup.Width)
101  s.Width = sup.Width;
102  if(sup.Height != 0 && s.Height > sup.Height)
103  {
104  yunseq(s.Width = s.Width + defMinScrollBarWidth, s.Height = sup.Height);
105  if(sup.Width != 0 && sup.Width < s.Width)
106  s.Width = sup.Width;
107  }
108  SetSizeOf(*this, s);
110  UpdateView();
111 }
112 
113 
115  : ListBox(r), pthDirectory()
116 {
117  GetConfirmed() += [this](IndexEventArgs&& e){
118  if(Contains(e) && bool(*this /= GetList()[e.Value]))
119  {
120  GetListRef() = ListItems();
121  ResetView();
122  }
123  };
124  ListItems();
125  UpdateView();
126 }
127 
128 IO::Path
129 FileBox::GetPath() const
130 {
131  return IsSelected() ? pthDirectory / (GetList()[GetSelectedIndex()])
132  : pthDirectory;
133 }
134 
135 bool
137 {
138  if(VerifyDirectory(d))
139  {
140  pthDirectory = d;
141  return true;
142  }
143  return false;
144 }
145 bool
147 {
148  return *this = pthDirectory / d;
149 }
150 bool
152 {
153  return *this = pthDirectory / d;
154 }
155 
156 bool
157 FileBox::SetPath(const IO::Path& pth)
158 {
159  if(operator=(pth))
160  {
161  GetListRef() = ListItems();
162  UpdateView();
163  return true;
164  }
165  return false;
166 }
167 
170 {
171  ListType lst;
172 
173  ListFiles(pthDirectory, lst);
174  // TODO: Platform-dependent name converting.
175  return lst;
176 }
177 
178 
179 DropDownList::DropDownList(const Rect& r, const shared_ptr<ListType>& h)
180  : Button(r),
181  lbContent({}, h)
182 {
183  const auto detacher([this](UIEventArgs&& e){
184  if(!dynamic_cast<RoutedEventArgs*>(&e))
185  DetachTopWidget();
186  });
187 
188  yunseq(
189  Margin.Left = 4,
190  Margin.Right = 18,
191  HorizontalAlignment = TextAlignment::Left,
192  lbContent.GetView().DependencyPtr = this,
193  FetchEvent<TouchDown>(*this) += [this](CursorEventArgs&& e){
194  if(!FetchContainerPtr(lbContent))
195  {
196  Point pt;
197 
198  if(const auto p
199  = dynamic_cast<Panel*>(&FetchTopLevel(e.GetSender(), pt)))
200  {
201  // NOTE: Get height of top widget, top and bottom spaces.
202  const SDst h0(GetSizeOf(*p).Height);
203  const SDst h1(max<SPos>(0, pt.Y)), h2(max<SPos>(0, h0 - pt.Y
204  - GetHeight()));
205 
206  if(IsInOpenInterval(h1, h0) || IsInOpenInterval(h2, h0))
207  {
208  lbContent.ResizeForPreferred(Size(0, max(h1, h2)),
209  Size(GetWidth(), 0));
210 
211  const SDst h(lbContent.GetHeight());
212 
213  // NOTE: Bottom space is preferred.
214  pt.Y += h2 < h ? -h : GetHeight();
215  SetLocationOf(lbContent, pt);
216  lbContent.AdjustViewLength();
217  {
218  const auto idx(lbContent.Find(Text));
219 
220  if(idx + 1 != 0)
221  lbContent.SetSelected(idx);
222  else
223  lbContent.ClearSelected();
224  }
225  p->Add(lbContent, 224U); // TODO: Use non-magic number.
226  RequestFocus(lbContent);
227  e.Handled = true;
228  }
229  }
230  }
231  },
232  FetchEvent<LostFocus>(*this) += detacher,
233  FetchEvent<LostFocus>(lbContent) += detacher,
234  lbContent.GetConfirmed() += [this](IndexEventArgs&& e){
235  YAssert(e.Value < lbContent.GetList().size(), "Invalid index found.");
236 
237  Text = lbContent.GetList()[e.Value];
238  Invalidate(e.GetSender()),
239  DetachTopWidget();
240  }
241  );
242 }
243 DropDownList::~DropDownList()
244 {
245  DetachTopWidget();
246 }
247 
248 void
249 DropDownList::DetachTopWidget()
250 {
251  Detach(FetchContainerPtr(lbContent), lbContent);
252 }
253 
254 void
256 {
257  const auto cs(GetCursorState());
258 
259  if(FetchContainerPtr(lbContent))
261  Button::Refresh(std::move(e));
262  csCurrent = cs;
263  DrawArrow(e.Target, Rect(e.Location + Vec(GetWidth() - 16, 0),
264  Size(16, GetHeight())) & e.ClipArea, 4, RDeg270, ForeColor);
265 }
266 
267 } // namespace UI;
268 
269 } // namespace YSLib;
270 
TextList tlContent
Definition: ComboList.h:66
pt pt Y const IWidget &wgt const IWidget &wgt GetSizeOf
无效化:使相对于部件的子部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: ywidget.h:156
GValueEventArgs< MTextList::IndexType > IndexEventArgs
索引事件。
Definition: textlist.h:47
ListType ListItems() const
遍历目录中的项目,更新至列表。
Definition: ComboList.cpp:169
YF_API void SetLocationOf(IWidget &, const Point &)
设置部件左上角所在位置(相对于容器的偏移坐标)。
Definition: ywidget.cpp:73
带滚动条的文本列表框。
Definition: ComboList.h:48
void ListFiles(const Path &pth, vector< String > &lst)
滚动事件参数类。
Definition: scroll.h:67
tlContent ListType::size_type i tlContent const ListType tlContent tlContent ViewChanged tlContent Confirmed ListType::size_type i const ItemType &text ResetView
Definition: ComboList.h:141
YF_API void Invalidate(IWidget &, const Rect &)
无效化:使相对于部件的指定区域在直接和间接的窗口缓冲区中无效。
Definition: ywidget.cpp:111
_iCOM * Detach(COMPtr< _iCOM > &ptr) ynothrow
部件绘制参数。
Definition: ywgtevt.h:276
void UpdateView(TextList &tl, bool is_active)
Definition: textlist.cpp:431
TextList::ViewArgs ViewArgs
Definition: ComboList.h:52
tlContent Contains
Definition: ComboList.h:78
IO::Path pthDirectory
目录的完整路径。
Definition: ComboList.h:169
SDst Height
宽和高。
Definition: ygdibase.h:258
bool IsInOpenInterval(_type i, _type b) ynothrow
判断 i 是否在开区间 (FetchZero<_type>(), b) 内。
Definition: ycutil.h:192
YF_API void SetSizeOf(IWidget &, const Size &)
设置部件大小。
Definition: ywidget.cpp:83
Size FixLayout(const Size &)
固定布局。
Definition: scroll.cpp:467
按钮。
Definition: button.h:116
用户界面事件参数基类。
Definition: ywgtevt.h:59
std::uint16_t SDst
屏幕坐标距离。
Definition: Video.h:39
CompactPixmapEx & operator=(const CompactPixmapEx &buf)
Definition: ygdi.h:328
VerticalScrollBar vsbVertical
控制竖直可视区域的竖直滚动条。
Definition: scroll.h:431
YSLib 标准字符串(使用 UCS-2 作为内部编码)。
Definition: ystring.h:47
HBrush Background
背景。
Definition: ywidget.h:374
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:748
带滚动条的容器。
Definition: scroll.h:414
CursorState csCurrent
指针设备光标状态。
Definition: button.h:64
_tWidget & wgt
Definition: ywgtevt.h:596
ATrack *pTrack GetTrackRef()) DefGetterMem(const ynothrow
ListBox(const Rect &={}, const shared_ptr< ListType > &={})
Definition: ComboList.cpp:61
屏幕标准矩形:表示屏幕矩形区域。
Definition: ygdibase.h:416
YF_API IWidget & FetchTopLevel(IWidget &)
取指定部件的顶层部件。
Definition: yuicont.cpp:40
bool operator/=(const String &)
导航至子目录。
Definition: ComboList.cpp:146
FileBox(const Rect &={})
Definition: ComboList.cpp:114
简单 UI 事件参数类。
Definition: ywgtevt.h:252
DefGetter(const ynothrow, const IO::Path &, Directory, pthDirectory) IO bool SetPath(const IO::Path &)
取目录的完整路径。
Definition: ComboList.h:214
YF_API void DrawArrow(const Graphics &, const Rect &, SDst=4, Rotation=RDeg0, Color=ColorSpace::Black)
在指定图形接口上下文上描画箭头。
Definition: ystyle.cpp:100
DropDownList(const Rect &={}, const shared_ptr< ListType > &={})
Definition: ComboList.cpp:179
void Refresh(PaintEventArgs &&) override
分离顶层子部件。
Definition: ComboList.cpp:255
bounds & r
Definition: ydraw.h:220
Color ForeColor
默认前景色。
Definition: ywidget.h:375
virtual void Refresh(PaintEventArgs &&)
刷新:按指定参数绘制界面并更新状态。
Definition: ywidget.cpp:264
屏幕区域大小。
Definition: ygdibase.h:249
指针设备输入事件参数类。
Definition: ywgtevt.h:183
TextList::ListType ListType
Definition: ComboList.h:51
#define YAssert(_expr, _msg)
Definition: cassert.h:73