Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(510)

Side by Side Diff: ui/touch_selection/touch_handle.cc

Issue 481683003: Support for Adaptive Handle Orientation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cleanup Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698