OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/touch_selection/touch_handle.h" | 5 #include "ui/touch_selection/touch_handle.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 namespace ui { | 9 namespace ui { |
10 | 10 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 TouchHandleOrientation orientation) | 66 TouchHandleOrientation orientation) |
67 : drawable_(client->CreateDrawable()), | 67 : drawable_(client->CreateDrawable()), |
68 client_(client), | 68 client_(client), |
69 orientation_(orientation), | 69 orientation_(orientation), |
70 deferred_orientation_(TouchHandleOrientation::UNDEFINED), | 70 deferred_orientation_(TouchHandleOrientation::UNDEFINED), |
71 alpha_(0.f), | 71 alpha_(0.f), |
72 animate_deferred_fade_(false), | 72 animate_deferred_fade_(false), |
73 enabled_(true), | 73 enabled_(true), |
74 is_visible_(false), | 74 is_visible_(false), |
75 is_dragging_(false), | 75 is_dragging_(false), |
76 is_drag_within_tap_region_(false) { | 76 is_drag_within_tap_region_(false), |
77 mirror_vertical_(false), | |
78 mirror_horizontal_(false) { | |
77 DCHECK_NE(orientation, TouchHandleOrientation::UNDEFINED); | 79 DCHECK_NE(orientation, TouchHandleOrientation::UNDEFINED); |
78 drawable_->SetEnabled(enabled_); | 80 drawable_->SetEnabled(enabled_); |
79 drawable_->SetOrientation(orientation_); | 81 drawable_->SetLayout(focus_bottom_, orientation_, false, false); |
80 drawable_->SetAlpha(alpha_); | 82 drawable_->SetAlpha(alpha_); |
81 drawable_->SetFocus(position_); | |
82 } | 83 } |
83 | 84 |
84 TouchHandle::~TouchHandle() { | 85 TouchHandle::~TouchHandle() { |
85 } | 86 } |
86 | 87 |
87 void TouchHandle::SetEnabled(bool enabled) { | 88 void TouchHandle::SetEnabled(bool enabled) { |
88 if (enabled_ == enabled) | 89 if (enabled_ == enabled) |
89 return; | 90 return; |
90 if (!enabled) { | 91 if (!enabled) { |
91 EndDrag(); | 92 EndDrag(); |
92 EndFade(); | 93 EndFade(); |
93 } | 94 } |
94 enabled_ = enabled; | 95 enabled_ = enabled; |
95 drawable_->SetEnabled(enabled); | 96 drawable_->SetEnabled(enabled); |
96 } | 97 } |
97 | 98 |
98 void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) { | 99 void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) { |
99 DCHECK(enabled_); | 100 DCHECK(enabled_); |
100 if (is_visible_ == visible) | 101 if (is_visible_ == visible) |
101 return; | 102 return; |
102 | 103 |
103 is_visible_ = visible; | 104 is_visible_ = visible; |
104 | 105 |
105 // Handle repositioning may have been deferred while previously invisible. | 106 // Handle repositioning may have been deferred while previously invisible. |
106 if (visible) | 107 UpdateLayout(); |
107 drawable_->SetFocus(position_); | |
108 | 108 |
109 bool animate = animation_style != ANIMATION_NONE; | 109 bool animate = animation_style != ANIMATION_NONE; |
110 if (is_dragging_) { | 110 if (is_dragging_) { |
111 animate_deferred_fade_ = animate; | 111 animate_deferred_fade_ = animate; |
112 return; | 112 return; |
113 } | 113 } |
114 | 114 |
115 if (animate) | 115 if (animate) |
116 BeginFade(); | 116 BeginFade(); |
117 else | 117 else |
118 EndFade(); | 118 EndFade(); |
119 } | 119 } |
120 | 120 |
121 void TouchHandle::SetPosition(const gfx::PointF& position) { | 121 void TouchHandle::SetFocus(const gfx::PointF& top, const gfx::PointF& bottom) { |
122 DCHECK(enabled_); | 122 if (focus_top_ == top && focus_bottom_ == bottom) |
123 if (position_ == position) | |
124 return; | 123 return; |
125 position_ = position; | 124 |
126 // Suppress repositioning a handle while invisible or fading out to prevent it | 125 focus_top_ = top; |
127 // from "ghosting" outside the visible bounds. The position will be pushed to | 126 focus_bottom_ = bottom; |
128 // the drawable when the handle regains visibility (see |SetVisible()|). | 127 UpdateLayout(); |
jdduke (slow)
2015/05/11 15:40:15
Nice, I think this is a bit easier to follow.
AviD
2015/05/19 16:26:27
Acknowledged.
| |
129 if (is_visible_) | 128 } |
130 drawable_->SetFocus(position_); | 129 |
130 void TouchHandle::SetViewportRect(const gfx::RectF viewport_rect) { | |
131 if (viewport_rect_ == viewport_rect) | |
132 return; | |
133 | |
134 viewport_rect_ = viewport_rect; | |
135 UpdateLayout(); | |
131 } | 136 } |
132 | 137 |
133 void TouchHandle::SetOrientation(TouchHandleOrientation orientation) { | 138 void TouchHandle::SetOrientation(TouchHandleOrientation orientation) { |
134 DCHECK(enabled_); | 139 DCHECK(enabled_); |
135 DCHECK_NE(orientation, TouchHandleOrientation::UNDEFINED); | 140 DCHECK_NE(orientation, TouchHandleOrientation::UNDEFINED); |
136 if (is_dragging_) { | 141 if (is_dragging_) { |
137 deferred_orientation_ = orientation; | 142 deferred_orientation_ = orientation; |
138 return; | 143 return; |
139 } | 144 } |
140 DCHECK_EQ(deferred_orientation_, TouchHandleOrientation::UNDEFINED); | 145 DCHECK_EQ(deferred_orientation_, TouchHandleOrientation::UNDEFINED); |
146 | |
141 if (orientation_ == orientation) | 147 if (orientation_ == orientation) |
142 return; | 148 return; |
143 | 149 |
144 orientation_ = orientation; | 150 orientation_ = orientation; |
145 drawable_->SetOrientation(orientation); | 151 UpdateLayout(); |
146 } | 152 } |
147 | 153 |
148 bool TouchHandle::WillHandleTouchEvent(const MotionEvent& event) { | 154 bool TouchHandle::WillHandleTouchEvent(const MotionEvent& event) { |
149 if (!enabled_) | 155 if (!enabled_) |
150 return false; | 156 return false; |
151 | 157 |
152 if (!is_dragging_ && event.GetAction() != MotionEvent::ACTION_DOWN) | 158 if (!is_dragging_ && event.GetAction() != MotionEvent::ACTION_DOWN) |
153 return false; | 159 return false; |
154 | 160 |
155 switch (event.GetAction()) { | 161 switch (event.GetAction()) { |
156 case MotionEvent::ACTION_DOWN: { | 162 case MotionEvent::ACTION_DOWN: { |
157 if (!is_visible_) | 163 if (!is_visible_) |
158 return false; | 164 return false; |
159 const gfx::PointF touch_point(event.GetX(), event.GetY()); | 165 const gfx::PointF touch_point(event.GetX(), event.GetY()); |
160 const float touch_radius = std::max( | 166 const float touch_radius = std::max( |
161 kMinTouchMajorForHitTesting, | 167 kMinTouchMajorForHitTesting, |
162 std::min(kMaxTouchMajorForHitTesting, event.GetTouchMajor())) * 0.5f; | 168 std::min(kMaxTouchMajorForHitTesting, event.GetTouchMajor())) * 0.5f; |
163 if (!RectIntersectsCircle(drawable_->GetVisibleBounds(), | 169 if (!RectIntersectsCircle(drawable_->GetVisibleBounds(), |
164 touch_point, | 170 touch_point, |
165 touch_radius)) { | 171 touch_radius)) { |
166 EndDrag(); | 172 EndDrag(); |
167 return false; | 173 return false; |
168 } | 174 } |
169 touch_down_position_ = touch_point; | 175 touch_down_position_ = touch_point; |
170 touch_to_focus_offset_ = position_ - touch_down_position_; | 176 touch_to_focus_offset_ = focus_bottom_ - touch_down_position_; |
171 touch_down_time_ = event.GetEventTime(); | 177 touch_down_time_ = event.GetEventTime(); |
172 BeginDrag(); | 178 BeginDrag(); |
173 } break; | 179 } break; |
174 | 180 |
175 case MotionEvent::ACTION_MOVE: { | 181 case MotionEvent::ACTION_MOVE: { |
176 gfx::PointF touch_move_position(event.GetX(), event.GetY()); | 182 gfx::PointF touch_move_position(event.GetX(), event.GetY()); |
177 if (is_drag_within_tap_region_) { | 183 if (is_drag_within_tap_region_) { |
178 const float tap_slop = client_->GetTapSlop(); | 184 const float tap_slop = client_->GetTapSlop(); |
179 is_drag_within_tap_region_ = | 185 is_drag_within_tap_region_ = |
180 (touch_move_position - touch_down_position_).LengthSquared() < | 186 (touch_move_position - touch_down_position_).LengthSquared() < |
(...skipping 27 matching lines...) Expand all Loading... | |
208 } | 214 } |
209 | 215 |
210 bool TouchHandle::Animate(base::TimeTicks frame_time) { | 216 bool TouchHandle::Animate(base::TimeTicks frame_time) { |
211 if (fade_end_time_ == base::TimeTicks()) | 217 if (fade_end_time_ == base::TimeTicks()) |
212 return false; | 218 return false; |
213 | 219 |
214 DCHECK(enabled_); | 220 DCHECK(enabled_); |
215 | 221 |
216 float time_u = | 222 float time_u = |
217 1.f - (fade_end_time_ - frame_time).InMillisecondsF() / kFadeDurationMs; | 223 1.f - (fade_end_time_ - frame_time).InMillisecondsF() / kFadeDurationMs; |
218 float position_u = | 224 float position_u = (focus_bottom_ - fade_start_position_).LengthSquared() / |
219 (position_ - fade_start_position_).LengthSquared() / kFadeDistanceSquared; | 225 kFadeDistanceSquared; |
220 float u = std::max(time_u, position_u); | 226 float u = std::max(time_u, position_u); |
221 SetAlpha(is_visible_ ? u : 1.f - u); | 227 SetAlpha(is_visible_ ? u : 1.f - u); |
222 | 228 |
223 if (u >= 1.f) { | 229 if (u >= 1.f) { |
224 EndFade(); | 230 EndFade(); |
225 return false; | 231 return false; |
226 } | 232 } |
227 | 233 |
228 return true; | 234 return true; |
229 } | 235 } |
230 | 236 |
237 void TouchHandle::UpdateLayout() { | |
238 // Suppress repositioning a handle while invisible or fading out to prevent it | |
239 // from "ghosting" outside the visible bounds. The position will be pushed to | |
240 // the drawable when the handle regains visibility (see |SetVisible()|). | |
241 if (!is_visible_) | |
242 return; | |
243 | |
244 gfx::RectF handle_bounds = drawable_->GetVisibleBounds(); | |
mfomitchev
2015/05/13 22:19:14
move this inside the if
AviD
2015/05/19 16:26:27
Done.
| |
245 | |
246 // Update mirror values only when dragging has stopped to prevent unwanted | |
247 // inversion while dragging of handles | |
248 if (!is_dragging_) { | |
249 mirror_horizontal_ = false; | |
250 mirror_vertical_ = false; | |
251 | |
252 if (focus_bottom_.y() + handle_bounds.height() > viewport_rect_.bottom()) { | |
253 mirror_vertical_ = true; | |
254 } | |
255 | |
256 if (orientation_ == TouchHandleOrientation::LEFT && | |
257 focus_bottom_.x() - handle_bounds.width() < viewport_rect_.x()) { | |
mfomitchev
2015/05/13 22:19:14
This assumes that handle is drawn without any offs
jdduke (slow)
2015/05/14 15:20:10
I believe so, yes. The |handle_bounds| should give
jdduke (slow)
2015/05/14 15:20:10
Good catch, |handle_bounds| should already be in v
mfomitchev
2015/05/14 15:52:39
Yeah, and the coordinates from the previous frame
AviD
2015/05/19 16:26:27
The focal_offset_from_origin is always 1/4th the w
jdduke (slow)
2015/05/19 18:59:26
We've made this assumption until now and it's work
AviD
2015/05/21 09:23:14
I have changed it to (handle_bounds.width() * 0.75
| |
258 mirror_horizontal_ = true; | |
259 } | |
260 | |
261 if (orientation_ == TouchHandleOrientation::RIGHT && | |
mfomitchev
2015/05/13 22:19:14
else if
AviD
2015/05/19 16:26:28
Done.
| |
262 focus_bottom_.x() + handle_bounds.width() > viewport_rect_.right()) { | |
263 mirror_horizontal_ = true; | |
264 } | |
265 } | |
266 | |
267 gfx::PointF position = mirror_vertical_ ? focus_top_ : focus_bottom_; | |
268 | |
269 drawable_->SetLayout(position, orientation_, mirror_vertical_, | |
270 mirror_horizontal_); | |
271 } | |
272 | |
231 void TouchHandle::BeginDrag() { | 273 void TouchHandle::BeginDrag() { |
232 DCHECK(enabled_); | 274 DCHECK(enabled_); |
233 if (is_dragging_) | 275 if (is_dragging_) |
234 return; | 276 return; |
235 EndFade(); | 277 EndFade(); |
236 is_dragging_ = true; | 278 is_dragging_ = true; |
237 is_drag_within_tap_region_ = true; | 279 is_drag_within_tap_region_ = true; |
238 client_->OnHandleDragBegin(*this); | 280 client_->OnHandleDragBegin(*this); |
239 } | 281 } |
240 | 282 |
241 void TouchHandle::EndDrag() { | 283 void TouchHandle::EndDrag() { |
242 DCHECK(enabled_); | 284 DCHECK(enabled_); |
243 if (!is_dragging_) | 285 if (!is_dragging_) |
244 return; | 286 return; |
245 | 287 |
246 is_dragging_ = false; | 288 is_dragging_ = false; |
247 is_drag_within_tap_region_ = false; | 289 is_drag_within_tap_region_ = false; |
248 client_->OnHandleDragEnd(*this); | 290 client_->OnHandleDragEnd(*this); |
249 | 291 |
250 if (deferred_orientation_ != TouchHandleOrientation::UNDEFINED) { | 292 if (deferred_orientation_ != TouchHandleOrientation::UNDEFINED) { |
251 TouchHandleOrientation deferred_orientation = deferred_orientation_; | 293 TouchHandleOrientation deferred_orientation = deferred_orientation_; |
252 deferred_orientation_ = TouchHandleOrientation::UNDEFINED; | 294 deferred_orientation_ = TouchHandleOrientation::UNDEFINED; |
253 SetOrientation(deferred_orientation); | 295 SetOrientation(deferred_orientation); |
296 UpdateLayout(); | |
mfomitchev
2015/05/13 22:19:14
// Handle layout may is deferred while the handle
AviD
2015/05/19 16:26:27
Done.
| |
254 } | 297 } |
255 | 298 |
256 if (animate_deferred_fade_) { | 299 if (animate_deferred_fade_) { |
257 BeginFade(); | 300 BeginFade(); |
258 } else { | 301 } else { |
259 // As drawable visibility assignment is deferred while dragging, push the | 302 // As drawable visibility assignment is deferred while dragging, push the |
260 // change by forcing fade completion. | 303 // change by forcing fade completion. |
261 EndFade(); | 304 EndFade(); |
262 } | 305 } |
263 } | 306 } |
264 | 307 |
265 void TouchHandle::BeginFade() { | 308 void TouchHandle::BeginFade() { |
266 DCHECK(enabled_); | 309 DCHECK(enabled_); |
267 DCHECK(!is_dragging_); | 310 DCHECK(!is_dragging_); |
268 animate_deferred_fade_ = false; | 311 animate_deferred_fade_ = false; |
269 const float target_alpha = is_visible_ ? 1.f : 0.f; | 312 const float target_alpha = is_visible_ ? 1.f : 0.f; |
270 if (target_alpha == alpha_) { | 313 if (target_alpha == alpha_) { |
271 EndFade(); | 314 EndFade(); |
272 return; | 315 return; |
273 } | 316 } |
274 | 317 |
275 fade_end_time_ = base::TimeTicks::Now() + | 318 fade_end_time_ = base::TimeTicks::Now() + |
276 base::TimeDelta::FromMillisecondsD( | 319 base::TimeDelta::FromMillisecondsD( |
277 kFadeDurationMs * std::abs(target_alpha - alpha_)); | 320 kFadeDurationMs * std::abs(target_alpha - alpha_)); |
278 fade_start_position_ = position_; | 321 fade_start_position_ = focus_bottom_; |
279 client_->SetNeedsAnimate(); | 322 client_->SetNeedsAnimate(); |
280 } | 323 } |
281 | 324 |
282 void TouchHandle::EndFade() { | 325 void TouchHandle::EndFade() { |
283 DCHECK(enabled_); | 326 DCHECK(enabled_); |
284 animate_deferred_fade_ = false; | 327 animate_deferred_fade_ = false; |
285 fade_end_time_ = base::TimeTicks(); | 328 fade_end_time_ = base::TimeTicks(); |
286 SetAlpha(is_visible_ ? 1.f : 0.f); | 329 SetAlpha(is_visible_ ? 1.f : 0.f); |
287 } | 330 } |
288 | 331 |
289 void TouchHandle::SetAlpha(float alpha) { | 332 void TouchHandle::SetAlpha(float alpha) { |
290 alpha = std::max(0.f, std::min(1.f, alpha)); | 333 alpha = std::max(0.f, std::min(1.f, alpha)); |
291 if (alpha_ == alpha) | 334 if (alpha_ == alpha) |
292 return; | 335 return; |
293 alpha_ = alpha; | 336 alpha_ = alpha; |
294 drawable_->SetAlpha(alpha); | 337 drawable_->SetAlpha(alpha); |
295 } | 338 } |
296 | 339 |
297 } // namespace ui | 340 } // namespace ui |
OLD | NEW |