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

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

Issue 1087893003: Support longpress drag selection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 6 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_selection_controller.h" 5 #include "ui/touch_selection/touch_selection_controller.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 10
(...skipping 22 matching lines...) Expand all
33 return TouchHandleOrientation::CENTER; 33 return TouchHandleOrientation::CENTER;
34 case SelectionBound::EMPTY: 34 case SelectionBound::EMPTY:
35 return TouchHandleOrientation::UNDEFINED; 35 return TouchHandleOrientation::UNDEFINED;
36 } 36 }
37 NOTREACHED() << "Invalid selection bound type: " << type; 37 NOTREACHED() << "Invalid selection bound type: " << type;
38 return TouchHandleOrientation::UNDEFINED; 38 return TouchHandleOrientation::UNDEFINED;
39 } 39 }
40 40
41 } // namespace 41 } // namespace
42 42
43 TouchSelectionController::Config::Config()
44 : tap_timeout(base::TimeDelta::FromMilliseconds(100)),
45 tap_slop(8),
46 enable_longpress_drag_selection(false),
47 show_on_tap_for_empty_editable(false) {
48 }
49
50 TouchSelectionController::Config::~Config() {
51 }
52
43 TouchSelectionController::TouchSelectionController( 53 TouchSelectionController::TouchSelectionController(
44 TouchSelectionControllerClient* client, 54 TouchSelectionControllerClient* client,
45 base::TimeDelta tap_timeout, 55 const Config& config)
46 float tap_slop,
47 bool show_on_tap_for_empty_editable)
48 : client_(client), 56 : client_(client),
49 tap_timeout_(tap_timeout), 57 config_(config),
50 tap_slop_(tap_slop),
51 force_next_update_(false), 58 force_next_update_(false),
52 show_on_tap_for_empty_editable_(show_on_tap_for_empty_editable),
53 response_pending_input_event_(INPUT_EVENT_TYPE_NONE), 59 response_pending_input_event_(INPUT_EVENT_TYPE_NONE),
54 start_orientation_(TouchHandleOrientation::UNDEFINED), 60 start_orientation_(TouchHandleOrientation::UNDEFINED),
55 end_orientation_(TouchHandleOrientation::UNDEFINED), 61 end_orientation_(TouchHandleOrientation::UNDEFINED),
56 active_status_(INACTIVE), 62 active_status_(INACTIVE),
57 activate_insertion_automatically_(false), 63 activate_insertion_automatically_(false),
58 activate_selection_automatically_(false), 64 activate_selection_automatically_(false),
59 selection_empty_(false), 65 selection_empty_(false),
60 selection_editable_(false), 66 selection_editable_(false),
61 temporarily_hidden_(false), 67 temporarily_hidden_(false),
68 anchor_drag_to_selection_start_(false),
69 longpress_drag_selector_(this),
62 selection_handle_dragged_(false) { 70 selection_handle_dragged_(false) {
63 DCHECK(client_); 71 DCHECK(client_);
64 } 72 }
65 73
66 TouchSelectionController::~TouchSelectionController() { 74 TouchSelectionController::~TouchSelectionController() {
67 } 75 }
68 76
69 void TouchSelectionController::OnSelectionBoundsChanged( 77 void TouchSelectionController::OnSelectionBoundsChanged(
70 const SelectionBound& start, 78 const SelectionBound& start,
71 const SelectionBound& end) { 79 const SelectionBound& end) {
(...skipping 15 matching lines...) Expand all
87 95
88 // Ensure that |response_pending_input_event_| is cleared after the method 96 // Ensure that |response_pending_input_event_| is cleared after the method
89 // completes, while also making its current value available for the duration 97 // completes, while also making its current value available for the duration
90 // of the call. 98 // of the call.
91 InputEventType causal_input_event = response_pending_input_event_; 99 InputEventType causal_input_event = response_pending_input_event_;
92 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; 100 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
93 base::AutoReset<InputEventType> auto_reset_response_pending_input_event( 101 base::AutoReset<InputEventType> auto_reset_response_pending_input_event(
94 &response_pending_input_event_, causal_input_event); 102 &response_pending_input_event_, causal_input_event);
95 103
96 const bool is_selection_dragging = active_status_ == SELECTION_ACTIVE && 104 const bool is_selection_dragging = active_status_ == SELECTION_ACTIVE &&
97 (start_selection_handle_->is_dragging() || 105 (start_selection_handle_->IsActive() ||
98 end_selection_handle_->is_dragging()); 106 end_selection_handle_->IsActive());
99 107
100 // It's possible that the bounds temporarily overlap while a selection handle 108 // It's possible that the bounds temporarily overlap while a selection handle
101 // is being dragged, incorrectly reporting a CENTER orientation. 109 // is being dragged, incorrectly reporting a CENTER orientation.
102 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response 110 // TODO(jdduke): This safeguard is racy, as it's possible the delayed response
103 // from handle positioning occurs *after* the handle dragging has ceased. 111 // from handle positioning occurs *after* the handle dragging has ceased.
104 // Instead, prevent selection -> insertion transitions without an intervening 112 // Instead, prevent selection -> insertion transitions without an intervening
105 // action or selection clearing of some sort, crbug.com/392696. 113 // action or selection clearing of some sort, crbug.com/392696.
106 if (is_selection_dragging) { 114 if (is_selection_dragging) {
107 if (start_orientation_ == TouchHandleOrientation::CENTER) 115 if (start_orientation_ == TouchHandleOrientation::CENTER)
108 start_orientation_ = start_selection_handle_->orientation(); 116 start_orientation_ = start_selection_handle_->orientation();
(...skipping 12 matching lines...) Expand all
121 if (start_orientation_ == TouchHandleOrientation::CENTER && 129 if (start_orientation_ == TouchHandleOrientation::CENTER &&
122 selection_editable_) { 130 selection_editable_) {
123 OnInsertionChanged(); 131 OnInsertionChanged();
124 return; 132 return;
125 } 133 }
126 134
127 HideAndDisallowShowingAutomatically(); 135 HideAndDisallowShowingAutomatically();
128 } 136 }
129 137
130 bool TouchSelectionController::WillHandleTouchEvent(const MotionEvent& event) { 138 bool TouchSelectionController::WillHandleTouchEvent(const MotionEvent& event) {
139 if (config_.enable_longpress_drag_selection &&
140 longpress_drag_selector_.WillHandleTouchEvent(event)) {
141 return true;
142 }
143
131 if (active_status_ == INSERTION_ACTIVE) { 144 if (active_status_ == INSERTION_ACTIVE) {
132 DCHECK(insertion_handle_); 145 DCHECK(insertion_handle_);
133 return insertion_handle_->WillHandleTouchEvent(event); 146 return insertion_handle_->WillHandleTouchEvent(event);
134 } 147 }
135 148
136 if (active_status_ == SELECTION_ACTIVE) { 149 if (active_status_ == SELECTION_ACTIVE) {
137 DCHECK(start_selection_handle_); 150 DCHECK(start_selection_handle_);
138 DCHECK(end_selection_handle_); 151 DCHECK(end_selection_handle_);
139 if (start_selection_handle_->is_dragging()) 152 if (start_selection_handle_->IsActive())
140 return start_selection_handle_->WillHandleTouchEvent(event); 153 return start_selection_handle_->WillHandleTouchEvent(event);
141 154
142 if (end_selection_handle_->is_dragging()) 155 if (end_selection_handle_->IsActive())
143 return end_selection_handle_->WillHandleTouchEvent(event); 156 return end_selection_handle_->WillHandleTouchEvent(event);
144 157
145 const gfx::PointF event_pos(event.GetX(), event.GetY()); 158 const gfx::PointF event_pos(event.GetX(), event.GetY());
146 if ((event_pos - GetStartPosition()).LengthSquared() <= 159 if ((event_pos - GetStartPosition()).LengthSquared() <=
147 (event_pos - GetEndPosition()).LengthSquared()) { 160 (event_pos - GetEndPosition()).LengthSquared()) {
148 return start_selection_handle_->WillHandleTouchEvent(event); 161 return start_selection_handle_->WillHandleTouchEvent(event);
149 } 162 }
150 return end_selection_handle_->WillHandleTouchEvent(event); 163 return end_selection_handle_->WillHandleTouchEvent(event);
151 } 164 }
152 165
153 return false; 166 return false;
154 } 167 }
155 168
156 bool TouchSelectionController::WillHandleTapEvent(const gfx::PointF& location) { 169 bool TouchSelectionController::WillHandleTapEvent(const gfx::PointF& location) {
157 if (WillHandleTapOrLongPress(location)) 170 if (WillHandleTapOrLongPress(location))
158 return true; 171 return true;
159 172
160 response_pending_input_event_ = TAP; 173 response_pending_input_event_ = TAP;
161 if (active_status_ != SELECTION_ACTIVE) 174 if (active_status_ != SELECTION_ACTIVE)
162 activate_selection_automatically_ = false; 175 activate_selection_automatically_ = false;
163 ShowInsertionHandleAutomatically(); 176 ShowInsertionHandleAutomatically();
164 if (selection_empty_ && !show_on_tap_for_empty_editable_) 177 if (selection_empty_ && !config_.show_on_tap_for_empty_editable)
165 DeactivateInsertion(); 178 DeactivateInsertion();
166 ForceNextUpdateIfInactive(); 179 ForceNextUpdateIfInactive();
167 return false; 180 return false;
168 } 181 }
169 182
170 bool TouchSelectionController::WillHandleLongPressEvent( 183 bool TouchSelectionController::WillHandleLongPressEvent(
184 base::TimeTicks event_time,
171 const gfx::PointF& location) { 185 const gfx::PointF& location) {
172 if (WillHandleTapOrLongPress(location)) 186 if (WillHandleTapOrLongPress(location))
173 return true; 187 return true;
174 188
189 longpress_drag_selector_.OnLongPressEvent(event_time, location);
175 response_pending_input_event_ = LONG_PRESS; 190 response_pending_input_event_ = LONG_PRESS;
176 ShowSelectionHandlesAutomatically(); 191 ShowSelectionHandlesAutomatically();
177 ShowInsertionHandleAutomatically(); 192 ShowInsertionHandleAutomatically();
178 ForceNextUpdateIfInactive(); 193 ForceNextUpdateIfInactive();
179 return false; 194 return false;
180 } 195 }
181 196
182 void TouchSelectionController::AllowShowingFromCurrentSelection() { 197 void TouchSelectionController::AllowShowingFromCurrentSelection() {
183 if (active_status_ != INACTIVE) 198 if (active_status_ != INACTIVE)
184 return; 199 return;
(...skipping 13 matching lines...) Expand all
198 DeactivateInsertion(); 213 DeactivateInsertion();
199 DeactivateSelection(); 214 DeactivateSelection();
200 activate_insertion_automatically_ = false; 215 activate_insertion_automatically_ = false;
201 activate_selection_automatically_ = false; 216 activate_selection_automatically_ = false;
202 } 217 }
203 218
204 void TouchSelectionController::SetTemporarilyHidden(bool hidden) { 219 void TouchSelectionController::SetTemporarilyHidden(bool hidden) {
205 if (temporarily_hidden_ == hidden) 220 if (temporarily_hidden_ == hidden)
206 return; 221 return;
207 temporarily_hidden_ = hidden; 222 temporarily_hidden_ = hidden;
208 223 RefreshHandleVisibility();
209 TouchHandle::AnimationStyle animation_style = GetAnimationStyle(true);
210 if (active_status_ == SELECTION_ACTIVE) {
211 start_selection_handle_->SetVisible(GetStartVisible(), animation_style);
212 end_selection_handle_->SetVisible(GetEndVisible(), animation_style);
213 } else if (active_status_ == INSERTION_ACTIVE) {
214 insertion_handle_->SetVisible(GetStartVisible(), animation_style);
215 }
216 } 224 }
217 225
218 void TouchSelectionController::OnSelectionEditable(bool editable) { 226 void TouchSelectionController::OnSelectionEditable(bool editable) {
219 if (selection_editable_ == editable) 227 if (selection_editable_ == editable)
220 return; 228 return;
221 selection_editable_ = editable; 229 selection_editable_ = editable;
222 ForceNextUpdateIfInactive(); 230 ForceNextUpdateIfInactive();
223 if (!selection_editable_) 231 if (!selection_editable_)
224 DeactivateInsertion(); 232 DeactivateInsertion();
225 } 233 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 } 284 }
277 285
278 const gfx::PointF& TouchSelectionController::GetStartPosition() const { 286 const gfx::PointF& TouchSelectionController::GetStartPosition() const {
279 return start_.edge_bottom(); 287 return start_.edge_bottom();
280 } 288 }
281 289
282 const gfx::PointF& TouchSelectionController::GetEndPosition() const { 290 const gfx::PointF& TouchSelectionController::GetEndPosition() const {
283 return end_.edge_bottom(); 291 return end_.edge_bottom();
284 } 292 }
285 293
286 void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) { 294 void TouchSelectionController::OnDragBegin(
287 if (&handle == insertion_handle_.get()) { 295 const TouchSelectionDraggable& draggable,
296 const gfx::PointF& drag_position) {
297 if (&draggable == insertion_handle_.get()) {
298 DCHECK_EQ(active_status_, INSERTION_ACTIVE);
288 client_->OnSelectionEvent(INSERTION_DRAG_STARTED); 299 client_->OnSelectionEvent(INSERTION_DRAG_STARTED);
300 anchor_drag_to_selection_start_ = true;
289 return; 301 return;
290 } 302 }
291 303
292 gfx::PointF base, extent; 304 DCHECK_EQ(active_status_, SELECTION_ACTIVE);
293 if (&handle == start_selection_handle_.get()) { 305
294 base = end_selection_handle_->position() + GetEndLineOffset(); 306 if (&draggable == start_selection_handle_.get()) {
295 extent = start_selection_handle_->position() + GetStartLineOffset(); 307 anchor_drag_to_selection_start_ = true;
308 } else if (&draggable == end_selection_handle_.get()) {
309 anchor_drag_to_selection_start_ = false;
296 } else { 310 } else {
297 base = start_selection_handle_->position() + GetStartLineOffset(); 311 DCHECK_EQ(&draggable, &longpress_drag_selector_);
298 extent = end_selection_handle_->position() + GetEndLineOffset(); 312 anchor_drag_to_selection_start_ =
313 (drag_position - GetStartPosition()).LengthSquared() <
314 (drag_position - GetEndPosition()).LengthSquared();
299 } 315 }
316
317 gfx::PointF base = GetStartPosition() + GetStartLineOffset();
318 gfx::PointF extent = GetEndPosition() + GetEndLineOffset();
319 if (anchor_drag_to_selection_start_)
320 std::swap(base, extent);
321
300 selection_handle_dragged_ = true; 322 selection_handle_dragged_ = true;
301 323
302 // When moving the handle we want to move only the extent point. Before doing 324 // When moving the handle we want to move only the extent point. Before doing
303 // so we must make sure that the base point is set correctly. 325 // so we must make sure that the base point is set correctly.
304 client_->SelectBetweenCoordinates(base, extent); 326 client_->SelectBetweenCoordinates(base, extent);
305 client_->OnSelectionEvent(SELECTION_DRAG_STARTED); 327 client_->OnSelectionEvent(SELECTION_DRAG_STARTED);
306 } 328 }
307 329
308 void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle, 330 void TouchSelectionController::OnDragUpdate(
309 const gfx::PointF& position) { 331 const TouchSelectionDraggable& draggable,
332 const gfx::PointF& drag_position) {
310 // As the position corresponds to the bottom left point of the selection 333 // As the position corresponds to the bottom left point of the selection
311 // bound, offset it by half the corresponding line height. 334 // bound, offset it to some reasonable point on the current line of text.
312 gfx::Vector2dF line_offset = &handle == start_selection_handle_.get() 335 gfx::Vector2dF line_offset = anchor_drag_to_selection_start_
313 ? GetStartLineOffset() 336 ? GetStartLineOffset()
314 : GetEndLineOffset(); 337 : GetEndLineOffset();
315 gfx::PointF line_position = position + line_offset; 338 gfx::PointF line_position = drag_position + line_offset;
316 if (&handle == insertion_handle_.get()) 339 if (&draggable == insertion_handle_.get())
317 client_->MoveCaret(line_position); 340 client_->MoveCaret(line_position);
318 else 341 else
319 client_->MoveRangeSelectionExtent(line_position); 342 client_->MoveRangeSelectionExtent(line_position);
320 } 343 }
321 344
322 void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) { 345 void TouchSelectionController::OnDragEnd(
323 if (&handle == insertion_handle_.get()) 346 const TouchSelectionDraggable& draggable) {
347 if (&draggable == insertion_handle_.get())
324 client_->OnSelectionEvent(INSERTION_DRAG_STOPPED); 348 client_->OnSelectionEvent(INSERTION_DRAG_STOPPED);
325 else 349 else
326 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED); 350 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED);
327 } 351 }
328 352
353 bool TouchSelectionController::IsWithinTapSlop(
354 const gfx::Vector2dF& delta) const {
355 return delta.LengthSquared() <
356 (static_cast<double>(config_.tap_slop) * config_.tap_slop);
357 }
358
329 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) { 359 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) {
330 if (insertion_handle_ && &handle == insertion_handle_.get()) 360 if (insertion_handle_ && &handle == insertion_handle_.get())
331 client_->OnSelectionEvent(INSERTION_TAPPED); 361 client_->OnSelectionEvent(INSERTION_TAPPED);
332 } 362 }
333 363
334 void TouchSelectionController::SetNeedsAnimate() { 364 void TouchSelectionController::SetNeedsAnimate() {
335 client_->SetNeedsAnimate(); 365 client_->SetNeedsAnimate();
336 } 366 }
337 367
338 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() { 368 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() {
339 return client_->CreateDrawable(); 369 return client_->CreateDrawable();
340 } 370 }
341 371
342 base::TimeDelta TouchSelectionController::GetTapTimeout() const { 372 base::TimeDelta TouchSelectionController::GetTapTimeout() const {
343 return tap_timeout_; 373 return config_.tap_timeout;
344 } 374 }
345 375
346 float TouchSelectionController::GetTapSlop() const { 376 void TouchSelectionController::OnLongPressDragActiveStateChanged() {
347 return tap_slop_; 377 // The handles should remain hidden for the duration of a longpress drag,
378 // including the time between a longpress and the start of drag motion.
379 RefreshHandleVisibility();
380 }
381
382 gfx::PointF TouchSelectionController::GetSelectionStart() const {
383 return GetStartPosition();
384 }
385
386 gfx::PointF TouchSelectionController::GetSelectionEnd() const {
387 return GetEndPosition();
348 } 388 }
349 389
350 void TouchSelectionController::ShowInsertionHandleAutomatically() { 390 void TouchSelectionController::ShowInsertionHandleAutomatically() {
351 if (activate_insertion_automatically_) 391 if (activate_insertion_automatically_)
352 return; 392 return;
353 activate_insertion_automatically_ = true; 393 activate_insertion_automatically_ = true;
354 ForceNextUpdateIfInactive(); 394 ForceNextUpdateIfInactive();
355 } 395 }
356 396
357 void TouchSelectionController::ShowSelectionHandlesAutomatically() { 397 void TouchSelectionController::ShowSelectionHandlesAutomatically() {
(...skipping 16 matching lines...) Expand all
374 AllowShowingFromCurrentSelection(); 414 AllowShowingFromCurrentSelection();
375 return true; 415 return true;
376 } 416 }
377 return false; 417 return false;
378 } 418 }
379 419
380 void TouchSelectionController::OnInsertionChanged() { 420 void TouchSelectionController::OnInsertionChanged() {
381 DeactivateSelection(); 421 DeactivateSelection();
382 422
383 if (response_pending_input_event_ == TAP && selection_empty_ && 423 if (response_pending_input_event_ == TAP && selection_empty_ &&
384 !show_on_tap_for_empty_editable_) { 424 !config_.show_on_tap_for_empty_editable) {
385 HideAndDisallowShowingAutomatically(); 425 HideAndDisallowShowingAutomatically();
386 return; 426 return;
387 } 427 }
388 428
389 if (!activate_insertion_automatically_) 429 if (!activate_insertion_automatically_)
390 return; 430 return;
391 431
392 const bool activated = ActivateInsertionIfNecessary(); 432 const bool activated = ActivateInsertionIfNecessary();
393 433
394 const TouchHandle::AnimationStyle animation = GetAnimationStyle(!activated); 434 const TouchHandle::AnimationStyle animation = GetAnimationStyle(!activated);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 if (active_status_ == INACTIVE || 503 if (active_status_ == INACTIVE ||
464 response_pending_input_event_ == LONG_PRESS) { 504 response_pending_input_event_ == LONG_PRESS) {
465 if (active_status_ == SELECTION_ACTIVE) { 505 if (active_status_ == SELECTION_ACTIVE) {
466 // The active selection session finishes with the start of the new one. 506 // The active selection session finishes with the start of the new one.
467 LogSelectionEnd(); 507 LogSelectionEnd();
468 } 508 }
469 active_status_ = SELECTION_ACTIVE; 509 active_status_ = SELECTION_ACTIVE;
470 selection_handle_dragged_ = false; 510 selection_handle_dragged_ = false;
471 selection_start_time_ = base::TimeTicks::Now(); 511 selection_start_time_ = base::TimeTicks::Now();
472 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; 512 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
513 longpress_drag_selector_.OnSelectionActivated();
473 return true; 514 return true;
474 } 515 }
475 return false; 516 return false;
476 } 517 }
477 518
478 void TouchSelectionController::DeactivateSelection() { 519 void TouchSelectionController::DeactivateSelection() {
479 if (active_status_ != SELECTION_ACTIVE) 520 if (active_status_ != SELECTION_ACTIVE)
480 return; 521 return;
481 DCHECK(start_selection_handle_); 522 DCHECK(start_selection_handle_);
482 DCHECK(end_selection_handle_); 523 DCHECK(end_selection_handle_);
483 LogSelectionEnd(); 524 LogSelectionEnd();
525 longpress_drag_selector_.OnSelectionDeactivated();
484 start_selection_handle_->SetEnabled(false); 526 start_selection_handle_->SetEnabled(false);
485 end_selection_handle_->SetEnabled(false); 527 end_selection_handle_->SetEnabled(false);
486 active_status_ = INACTIVE; 528 active_status_ = INACTIVE;
487 client_->OnSelectionEvent(SELECTION_CLEARED); 529 client_->OnSelectionEvent(SELECTION_CLEARED);
488 } 530 }
489 531
490 void TouchSelectionController::ForceNextUpdateIfInactive() { 532 void TouchSelectionController::ForceNextUpdateIfInactive() {
491 // Only force the update if the reported selection is non-empty but still 533 // Only force the update if the reported selection is non-empty but still
492 // considered "inactive", i.e., it wasn't preceded by a user gesture or 534 // considered "inactive", i.e., it wasn't preceded by a user gesture or
493 // the handles have since been explicitly hidden. 535 // the handles have since been explicitly hidden.
494 if (active_status_ == INACTIVE && 536 if (active_status_ == INACTIVE &&
495 start_.type() != SelectionBound::EMPTY && 537 start_.type() != SelectionBound::EMPTY &&
496 end_.type() != SelectionBound::EMPTY) { 538 end_.type() != SelectionBound::EMPTY) {
497 force_next_update_ = true; 539 force_next_update_ = true;
498 } 540 }
499 } 541 }
500 542
543 void TouchSelectionController::RefreshHandleVisibility() {
544 TouchHandle::AnimationStyle animation_style = GetAnimationStyle(true);
545 if (active_status_ == SELECTION_ACTIVE) {
546 start_selection_handle_->SetVisible(GetStartVisible(), animation_style);
547 end_selection_handle_->SetVisible(GetEndVisible(), animation_style);
548 }
549 if (active_status_ == INSERTION_ACTIVE)
550 insertion_handle_->SetVisible(GetStartVisible(), animation_style);
551 }
552
501 gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const { 553 gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const {
502 return ComputeLineOffsetFromBottom(start_); 554 return ComputeLineOffsetFromBottom(start_);
503 } 555 }
504 556
505 gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const { 557 gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const {
506 return ComputeLineOffsetFromBottom(end_); 558 return ComputeLineOffsetFromBottom(end_);
507 } 559 }
508 560
509 bool TouchSelectionController::GetStartVisible() const { 561 bool TouchSelectionController::GetStartVisible() const {
510 return start_.visible() && !temporarily_hidden_; 562 if (!start_.visible())
563 return false;
564
565 return !temporarily_hidden_ && !longpress_drag_selector_.IsActive();
511 } 566 }
512 567
513 bool TouchSelectionController::GetEndVisible() const { 568 bool TouchSelectionController::GetEndVisible() const {
514 return end_.visible() && !temporarily_hidden_; 569 if (!end_.visible())
570 return false;
571
572 return !temporarily_hidden_ && !longpress_drag_selector_.IsActive();
515 } 573 }
516 574
517 TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle( 575 TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle(
518 bool was_active) const { 576 bool was_active) const {
519 return was_active && client_->SupportsAnimation() 577 return was_active && client_->SupportsAnimation()
520 ? TouchHandle::ANIMATION_SMOOTH 578 ? TouchHandle::ANIMATION_SMOOTH
521 : TouchHandle::ANIMATION_NONE; 579 : TouchHandle::ANIMATION_NONE;
522 } 580 }
523 581
524 void TouchSelectionController::LogSelectionEnd() { 582 void TouchSelectionController::LogSelectionEnd() {
525 // TODO(mfomitchev): Once we are able to tell the difference between 583 // TODO(mfomitchev): Once we are able to tell the difference between
526 // 'successful' and 'unsuccessful' selections - log 584 // 'successful' and 'unsuccessful' selections - log
527 // Event.TouchSelection.Duration instead and get rid of 585 // Event.TouchSelection.Duration instead and get rid of
528 // Event.TouchSelectionD.WasDraggeduration. 586 // Event.TouchSelectionD.WasDraggeduration.
529 if (selection_handle_dragged_) { 587 if (selection_handle_dragged_) {
530 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; 588 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_;
531 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", 589 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration",
532 duration, 590 duration,
533 base::TimeDelta::FromMilliseconds(500), 591 base::TimeDelta::FromMilliseconds(500),
534 base::TimeDelta::FromSeconds(60), 592 base::TimeDelta::FromSeconds(60),
535 60); 593 60);
536 } 594 }
537 } 595 }
538 596
539 } // namespace ui 597 } // namespace ui
OLDNEW
« no previous file with comments | « ui/touch_selection/touch_selection_controller.h ('k') | ui/touch_selection/touch_selection_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698