YSTest: ygui.cpp 源文件

YSTest PreAlpha_b400_20130424 The YSLib Test Project

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

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
ygui.cpp
浏览该文件的文档.
1 ﻿/*
2 Copyright by FrankHB 2009 - 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/ygui.h"
29 #include "YSLib/UI/ydesktop.h"
30
31 YSL_BEGIN
32
33 using namespace Drawing;
34
35 YSL_BEGIN_NAMESPACE(UI)
36
37 namespace
38 {
39
41 IWidget*
42 FetchTopEnabledAndVisibleWidgetPtr(IWidget& con, const Point& pt)
43 {
44 for(auto pr = con.GetChildren(); pr.first != pr.second; ++pr.first)
45 {
46 IWidget& wgt(*pr.first);
47
48 if(Contains(wgt, pt) && IsEnabled(wgt) && IsVisible(wgt))
49 return &wgt;
50 }
51 return nullptr;
52 }
53
54 } // unnamed namespace;
55
56
57 InputTimer::InputTimer(const Duration& d)
58 : timer(d)
59 {}
60
61 bool
62 InputTimer::Refresh(HeldStateType& s,
63 const Duration& initial_delay, const Duration& repeated_delay)
64 {
65 switch(s)
66 {
67 case Free:
68 s = Pressed,
69 timer.SetInterval(initial_delay);
70 Activate(timer);
71 break;
72 case Pressed:
73 case Held:
74 if(YB_UNLIKELY(timer.Refresh()))
75 {
76 if(s == Pressed)
77 {
78 s = Held,
79 timer.SetInterval(repeated_delay);
80 }
81 return true;
82 }
83 break;
84 }
85 return false;
86 }
87
88 void
89 InputTimer::Reset()
90 {
91 Deactivate(timer);
92 timer.SetInterval(Timers::TimeSpan(1000));
93 }
94
95
96 bool
97 RepeatHeld(InputTimer& tmr, InputTimer::HeldStateType& st,
98 const Timers::Duration& initial_delay,
99 const Timers::Duration& repeated_delay)
100 {
101 const bool b(st == InputTimer::Free);
102
103 return tmr.Refresh(st, initial_delay, repeated_delay) || b;
104 }
105
106
107 GUIState::GUIState() ynothrow
108 : KeyHeldState(InputTimer::Free), TouchHeldState(InputTimer::Free),
109 DraggingOffset(Vec::Invalid), HeldTimer(),
110 ControlLocation(Point::Invalid),
111 LastControlLocation(Point::Invalid), Colors(),
112 p_KeyDown(), p_TouchDown(), control_entered(false)
113 {}
114
115 void
116 GUIState::Reset()
117 {
118 yunseq(KeyHeldState = InputTimer::Free, TouchHeldState = InputTimer::Free,
119 DraggingOffset = Vec::Invalid),
120 HeldTimer.Reset();
121 yunseq(ControlLocation = Point::Invalid,
122 LastControlLocation = Point::Invalid,
123 p_TouchDown = nullptr, p_KeyDown = nullptr);
124 }
125
126 void
127 GUIState::ResetHeldState(InputTimer::HeldStateType& s)
128 {
129 s = InputTimer::Free,
130 HeldTimer.Reset();
131 }
132
133 void
134 GUIState::TryEntering(TouchEventArgs&& e)
135 {
136 if(!control_entered)
137 {
138 CallEvent<Enter>(e.GetSender(), e);
139 control_entered = true;
140 }
141 }
142
143 void
144 GUIState::TryLeaving(TouchEventArgs&& e)
145 {
146 if(control_entered)
147 {
148 CallEvent<Leave>(e.GetSender(), e);
149 control_entered = false;
150 }
151 }
152
153 bool
154 GUIState::ResponseKeyBase(KeyEventArgs& e, UI::VisualEvent op)
155 {
156 auto& wgt(e.GetSender());
157
158 switch(op)
159 {
160 case KeyUp:
161 ResetHeldState(KeyHeldState);
162 CallEvent<KeyUp>(wgt, e);
163 if(p_KeyDown == &wgt)
164 {
165 CallEvent<KeyPress>(wgt, e);
166 p_KeyDown = nullptr;
167 }
168 break;
169 case KeyDown:
170 p_KeyDown = &wgt;
171 CallEvent<KeyDown>(wgt, e);
172 break;
173 case KeyHeld:
174 /* if(e.Strategy == RoutedEventArgs::Direct && p_KeyDown != &c)
175 {
176 ResetHeldState(KeyHeldState);
177 return false;
178 }*/
179 CallEvent<KeyHeld>(wgt, e);
180 break;
181 default:
182 YAssert(false, "Invalid operation found.");
183 }
184 return true;
185 }
186
187 bool
188 GUIState::ResponseTouchBase(TouchEventArgs& e, UI::VisualEvent op)
189 {
190 auto& wgt(e.GetSender());
191
192 switch(op)
193 {
194 case TouchUp:
195 ResetHeldState(TouchHeldState);
196 DraggingOffset = Vec::Invalid;
197 CallEvent<TouchUp>(wgt, e);
198 if(p_TouchDown)
199 {
200 e.SetSender(*p_TouchDown);
201 TryLeaving(std::move(e));
202 e.SetSender(wgt);
203 }
204 if(p_TouchDown == &wgt)
205 {
206 CallEvent<Click>(wgt, e);
207 p_TouchDown = nullptr;
208 }
209 break;
210 case TouchDown:
211 p_TouchDown = &wgt;
212 TryEntering(std::move(e));
213 CallEvent<TouchDown>(wgt, e);
214 break;
215 case TouchHeld:
216 if(!p_TouchDown)
217 return false;
218 if(p_TouchDown == &wgt)
219 TryEntering(TouchEventArgs(e));
220 else
221 TryLeaving(TouchEventArgs(*p_TouchDown, e.Keys,
222 e - LocateForWidget(wgt, *p_TouchDown)));
223 CallEvent<TouchHeld>(*p_TouchDown, e);
224 break;
225 default:
226 YAssert(false, "Invalid operation found.");
227 }
228 return true;
229 }
230
231 bool
232 GUIState::ResponseKey(KeyEventArgs& e, UI::VisualEvent op)
233 {
234 auto p(&e.GetSender());
235 IWidget* pCon;
236 bool r(false);
237
238 e.Strategy = UI::RoutedEventArgs::Tunnel;
239 while(true)
240 {
241 if(!(IsVisible(*p) && IsEnabled(*p)))
242 return false;
243 if(e.Handled)
244 return true;
245 pCon = p;
246
247 auto t(FetchFocusingPtr(*pCon));
248
249 if(!t || t == pCon)
250 {
251 if(e.Handled)
252 return true;
253 else
254 break;
255 }
256 e.SetSender(*p);
257 r |= ResponseKeyBase(e, op);
258 p = t;
259 }
260
261 YAssert(p, "Null pointer found.");
262
263 e.Strategy = UI::RoutedEventArgs::Direct;
264 e.SetSender(*p);
265 r |= ResponseKeyBase(e, op);
266 e.Strategy = UI::RoutedEventArgs::Bubble;
267 while(!e.Handled && (pCon = FetchContainerPtr(*p)))
268 {
269 e.SetSender(*(p = pCon));
270 r |= ResponseKeyBase(e, op);
271 }
272 return r/* || e.Handled*/;
273 }
274
275 bool
276 GUIState::ResponseTouch(TouchEventArgs& e, UI::VisualEvent op)
277 {
278 ControlLocation = e;
279
280 auto p(&e.GetSender());
281 IWidget* pCon;
282 bool r(false);
283
284 e.Strategy = UI::RoutedEventArgs::Tunnel;
285 while(true)
286 {
287 if(!(IsVisible(*p) && IsEnabled(*p)))
288 return false;
289 if(e.Handled)
290 return true;
291 pCon = p;
292
293 const auto t(FetchTopEnabledAndVisibleWidgetPtr(*pCon, e));
294
295 if(!t || t == pCon)
296 {
297 if(e.Handled)
298 return true;
299 else
300 break;
301 }
302 e.SetSender(*p);
303 r |= DoEvent<HTouchEvent>(p->GetController(), op, e) != 0;
304 p = t;
305 e -= GetLocationOf(*p);
306 };
307
308 YAssert(p, "Null pointer found.");
309
310 e.Strategy = UI::RoutedEventArgs::Direct;
311 e.SetSender(*p);
312 r |= ResponseTouchBase(e, op);
313 e.Strategy = UI::RoutedEventArgs::Bubble;
314 while(!e.Handled && (pCon = FetchContainerPtr(*p)))
315 {
316 e += GetLocationOf(*p);
317 e.SetSender(*(p = pCon));
318 r |= DoEvent<HTouchEvent>(p->GetController(), op, e) != 0;
319 }
320 return r/* || e.Handled*/;
321 }
322
323
324 GUIState&
325 FetchGUIState()
326 {
327 static GUIState* pState(new GUIState());
328
329 return *pState;
330 }
331
332 YSL_END_NAMESPACE(UI)
333
334 YSL_END
335