YSTest: ycontrol.cpp 源文件

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
36 YSL_BEGIN
37
38 YSL_BEGIN_NAMESPACE(UI)
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
52 EventMapping::ItemType&
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
82 OnTouchDown_RequestToTopFocused(TouchEventArgs&& e)
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,
123 Timers::TimeSpan(240), Timers::TimeSpan(80)))
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
171 OnKey_Bound_TouchUpAndLeave(KeyEventArgs&& e)
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
184 OnKey_Bound_EnterAndTouchDown(KeyEventArgs&& e)
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 {
220 Background = SolidBrush(ColorSpace::White);
221 }
222 Control::Control(const Rect& r, NoBackgroundTag)
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)
240 : Widget(ctl), BoundControlPtr(ctl.BoundControlPtr)
241 {}
242
243 void
244 Control::OnTouch_Close(TouchEventArgs&&)
245 {
246 Close(*this);
247 }
248
249 YSL_END_NAMESPACE(UI)
250
251 YSL_END
252