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 
33 
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  {
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
124 {
125  return IsSelected() ? Directory / (GetList()[GetSelectedIndex()])
126  : Directory;
127 }
128 
129 bool
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 }
206 {
207  DetachTopWidget();
208 }
209 
210 void
212 {
214 }
215 
216 void
218 {
219  bool b(bPressed);
220 
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 
229 
230 YSL_END
231