YSTest  PreAlpha_b400_20130424
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
ycontrol.cpp
浏览该文件的文档.
1 /*
2  Copyright by FrankHB 2010 - 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/ycontrol.h"
29 #include "YSLib/UI/ygui.h"
30 #include "YSLib/UI/yuicont.h"
31 #include "YSLib/Core/ystorage.hpp"
32 #include <ystdex/algorithm.hpp>
33 #include "YSLib/UI/yrender.h"
34 #include "YSLib/UI/YBrush.h"
35 
37 
39 
40 EventMapping::ItemType&
41 GetEvent(EventMapping::MapType& m, const VisualEvent& id,
42  EventMapping::MappedType(&f)())
43 {
44  auto pr(ystdex::search_map(m, id));
45 
46  if(pr.second)
47  pr.first = m.insert(pr.first, EventMapping::PairType(id, f()));
48  return pr.first->second;
49 }
50 
51 
53 Controller::GetItemRef(const VisualEvent& id, EventMapping::MappedType(&f)())
54 {
55  return GetEvent(EventMap, id, f);
56 }
57 
58 
59 bool
60 Enable(IWidget& wgt, bool b)
61 {
62  const auto enability_changed(IsEnabled(wgt) != b);
63 
64  SetEnabledOf(wgt, b);
65  if(enability_changed)
66  Invalidate(wgt);
67  return enability_changed;
68 }
69 
70 
71 void
72 OnKeyHeld(KeyEventArgs&& e)
73 {
74  auto& st(FetchGUIState());
75 
76  if(st.HeldTimer.Refresh(st.KeyHeldState, Timers::TimeSpan(240),
77  Timers::TimeSpan(60)))
78  CallEvent<KeyDown>(e.GetSender(), e);
79 }
80 
81 void
83 {
84  IWidget& wgt(e.GetSender());
85 
86  if(e.Strategy != RoutedEventArgs::Bubble)
87  RequestToTop(wgt);
88  if(e.Strategy == RoutedEventArgs::Direct)
89  ClearFocusingOf(wgt);
90  if(e.Strategy != RoutedEventArgs::Tunnel)
91  RequestFocus(wgt);
92 }
93 
94 void
95 OnTouchHeld(TouchEventArgs&& e)
96 {
97  if(e.Strategy == RoutedEventArgs::Direct)
98  {
99  auto& st(FetchGUIState());
100 
101  if(st.GetTouchDownPtr())
102  {
103  auto& wgt(*st.GetTouchDownPtr());
104 
105  if(st.DraggingOffset == Vec::Invalid)
106  st.DraggingOffset = GetLocationOf(wgt)
107  - st.ControlLocation;
108  else
109  CallEvent<TouchMove>(wgt, e);
110  st.LastControlLocation = st.ControlLocation;
111  }
112  }
113 }
114 
115 void
116 OnTouchMove(TouchEventArgs&& e)
117 {
118  if(e.Strategy == RoutedEventArgs::Direct)
119  {
120  auto& st(FetchGUIState());
121 
122  if(st.GetTouchDownPtr() && st.HeldTimer.Refresh(st.TouchHeldState,
124  CallEvent<TouchDown>(*st.GetTouchDownPtr(), e);
125  }
126 }
127 
128 void
129 OnTouchMove_Dragging(TouchEventArgs&& e)
130 {
131  if(e.Strategy == RoutedEventArgs::Direct)
132  {
133  auto& st(FetchGUIState());
134 
135  if(st.GetTouchDownPtr())
136  {
137  auto& wgt(*st.GetTouchDownPtr());
138 
139  // TODO: Analysis buffered coordinate delayed painting bug.
140  // if(st.LastControlLocation != st.ControlLocation)
141  // {
142  // TODO: Merge state to make a more efficient implementation.
143  Invalidate(wgt);
144  SetLocationOf(wgt, st.LastControlLocation + st.DraggingOffset);
145  // }
146  }
147  }
148 }
149 
150 namespace
151 {
152  IWidget*
153  FetchEnabledBoundControlPtr(KeyEventArgs&& e)
154  {
155  try
156  {
157  auto pCtl(dynamic_cast<Control&>(e.GetSender())
158  .BoundControlPtr(e.GetKeys()));
159 
160  return pCtl && IsEnabled(*pCtl) ? pCtl : nullptr;
161  }
162  catch(std::bad_function_call&)
163  {}
164  catch(std::bad_cast&)
165  {}
166  return nullptr;
167  }
168 }
169 
170 void
172 {
173  if(const auto pCtl = FetchEnabledBoundControlPtr(std::move(e)))
174  {
175  TouchEventArgs et(*pCtl, e.Keys, TouchEventArgs::Invalid);
176 
177  CallEvent<TouchUp>(*pCtl, et);
178  CallEvent<Leave>(*pCtl, et);
179  e.Handled = true;
180  }
181 }
182 
183 void
185 {
186  if(const auto pCtl = FetchEnabledBoundControlPtr(std::move(e)))
187  {
188  TouchEventArgs et(*pCtl, e.Keys, TouchEventArgs::Invalid);
189 
190  CallEvent<Enter>(*pCtl, et);
191  CallEvent<TouchDown>(*pCtl, et);
192  e.Handled = true;
193  }
194 }
195 
196 void
197 OnKey_Bound_Click(KeyEventArgs&& e)
198 {
199  if(const auto pCtl = FetchEnabledBoundControlPtr(std::move(e)))
200  {
201  TouchEventArgs et(*pCtl, e.Keys, TouchEventArgs::Invalid);
202 
203  CallEvent<Click>(*pCtl, et);
204  e.Handled = true;
205  }
206 }
207 
208 
209 Control::ControlEventMap::ControlEventMap()
210 {
211  yunseq(
212  FetchEvent<TouchDown>(*this) += OnTouchDown_RequestToTopFocused,
213  FetchEvent<TouchHeld>(*this) += OnTouchHeld
214  );
215 }
216 
217 Control::Control(const Rect& r)
218  : Control(r, NoBackgroundTag())
219 {
221 }
223  : Widget(new View(r), new Renderer(),
224  new Controller(true, FetchPrototype<ControlEventMap>())),
225  BoundControlPtr(std::bind(&Control::GetBoundControlPtr, this,
226  std::placeholders::_1))
227 {
228  const auto h([this](UIEventArgs&&){
229  Invalidate(*this);
230  });
231 
232  yunseq(
233  FetchEvent<Move>(*this) += h,
234  FetchEvent<Resize>(*this) += h,
235  FetchEvent<GotFocus>(*this) += h,
236  FetchEvent<LostFocus>(*this) += h
237  );
238 }
239 Control::Control(const Control& ctl)
241 {}
242 
243 void
245 {
246  Close(*this);
247 }
248 
250 
251 YSL_END
252