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

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

Issue 1046783002: wip: Aura-specific implementation of unified touch selection: touch_selection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactoring - common client for Aura and Android. Created 5 years, 8 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_impl.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 #include "ui/gfx/geometry/rect.h"
10 11
11 namespace ui { 12 namespace ui {
12 namespace { 13 namespace {
13 14
15 // Delay before showing the quick menu, in milliseconds.
16 const int kQuickMenuDelayInMs = 100;
17
14 gfx::Vector2dF ComputeLineOffsetFromBottom(const SelectionBound& bound) { 18 gfx::Vector2dF ComputeLineOffsetFromBottom(const SelectionBound& bound) {
15 gfx::Vector2dF line_offset = 19 gfx::Vector2dF line_offset =
16 gfx::ScaleVector2d(bound.edge_top() - bound.edge_bottom(), 0.5f); 20 gfx::ScaleVector2d(bound.edge_top() - bound.edge_bottom(), 0.5f);
17 // An offset of 5 DIPs is sufficient for most line sizes. For small lines, 21 // An offset of 5 DIPs is sufficient for most line sizes. For small lines,
18 // using half the line height avoids synthesizing a point on a line above 22 // using half the line height avoids synthesizing a point on a line above
19 // (or below) the intended line. 23 // (or below) the intended line.
20 const gfx::Vector2dF kMaxLineOffset(5.f, 5.f); 24 const gfx::Vector2dF kMaxLineOffset(5.f, 5.f);
21 line_offset.SetToMin(kMaxLineOffset); 25 line_offset.SetToMin(kMaxLineOffset);
22 line_offset.SetToMax(-kMaxLineOffset); 26 line_offset.SetToMax(-kMaxLineOffset);
23 return line_offset; 27 return line_offset;
24 } 28 }
25 29
26 TouchHandleOrientation ToTouchHandleOrientation(SelectionBound::Type type) { 30 TouchHandleOrientation ToTouchHandleOrientation(SelectionBound::Type type) {
27 switch (type) { 31 switch (type) {
28 case SelectionBound::LEFT: 32 case SelectionBound::LEFT:
29 return TouchHandleOrientation::LEFT; 33 return TouchHandleOrientation::LEFT;
30 case SelectionBound::RIGHT: 34 case SelectionBound::RIGHT:
31 return TouchHandleOrientation::RIGHT; 35 return TouchHandleOrientation::RIGHT;
32 case SelectionBound::CENTER: 36 case SelectionBound::CENTER:
33 return TouchHandleOrientation::CENTER; 37 return TouchHandleOrientation::CENTER;
34 case SelectionBound::EMPTY: 38 case SelectionBound::EMPTY:
35 return TouchHandleOrientation::UNDEFINED; 39 return TouchHandleOrientation::UNDEFINED;
36 } 40 }
37 NOTREACHED() << "Invalid selection bound type: " << type; 41 NOTREACHED() << "Invalid selection bound type: " << type;
38 return TouchHandleOrientation::UNDEFINED; 42 return TouchHandleOrientation::UNDEFINED;
39 } 43 }
40 44
45 void ClipPoint(gfx::PointF* point, const gfx::Rect& clip_rect) {
46 point->SetToMax(clip_rect.origin());
47 point->SetToMin(clip_rect.bottom_right());
48 }
49
50 void ClipSelectionBound(SelectionBound* bound, const gfx::Rect& clip_rect) {
51 gfx::PointF edge_top = bound->edge_top();
52 gfx::PointF edge_bottom = bound->edge_bottom();
53 ClipPoint(&edge_top, clip_rect);
54 ClipPoint(&edge_bottom, clip_rect);
55 bound->SetEdge(edge_top, edge_bottom);
56 }
41 } // namespace 57 } // namespace
42 58
43 TouchSelectionController::TouchSelectionController( 59 TouchSelectionControllerImpl::TouchSelectionControllerImpl(
44 TouchSelectionControllerClient* client, 60 TouchSelectionControllerClient* client,
45 base::TimeDelta tap_timeout, 61 base::TimeDelta tap_timeout,
46 float tap_slop, 62 float tap_slop,
47 bool show_on_tap_for_empty_editable) 63 bool show_on_tap_for_empty_editable)
48 : client_(client), 64 : client_(client),
49 tap_timeout_(tap_timeout), 65 tap_timeout_(tap_timeout),
50 tap_slop_(tap_slop), 66 tap_slop_(tap_slop),
51 show_on_tap_for_empty_editable_(show_on_tap_for_empty_editable), 67 show_on_tap_for_empty_editable_(show_on_tap_for_empty_editable),
52 response_pending_input_event_(INPUT_EVENT_TYPE_NONE), 68 response_pending_input_event_(INPUT_EVENT_TYPE_NONE),
53 start_orientation_(TouchHandleOrientation::UNDEFINED), 69 start_orientation_(TouchHandleOrientation::UNDEFINED),
54 end_orientation_(TouchHandleOrientation::UNDEFINED), 70 end_orientation_(TouchHandleOrientation::UNDEFINED),
55 is_insertion_active_(false), 71 is_insertion_active_(false),
56 activate_insertion_automatically_(false), 72 activate_insertion_automatically_(false),
57 is_selection_active_(false), 73 is_selection_active_(false),
58 activate_selection_automatically_(false), 74 activate_selection_automatically_(false),
59 selection_empty_(false), 75 selection_empty_(false),
60 selection_editable_(false), 76 selection_editable_(false),
61 temporarily_hidden_(false), 77 temporarily_hidden_(false),
62 selection_handle_dragged_(false) { 78 quick_menu_timer_(FROM_HERE,
79 base::TimeDelta::FromMilliseconds(kQuickMenuDelayInMs),
80 base::Bind(&TouchSelectionControllerImpl::ShowQuickMenu,
81 base::Unretained(this)),
82 false),
83 scroll_in_progress_(false),
84 overscroll_in_progress_(false),
85 handle_drag_in_progress_(false),
86 selection_handle_was_dragged_(false) {
63 DCHECK(client_); 87 DCHECK(client_);
64 } 88 }
65 89
66 TouchSelectionController::~TouchSelectionController() { 90 TouchSelectionControllerImpl::~TouchSelectionControllerImpl() {
67 } 91 }
68 92
69 void TouchSelectionController::OnSelectionBoundsChanged( 93 bool TouchSelectionControllerImpl::OnSelectionBoundsUpdated(
70 const SelectionBound& start, 94 const SelectionBound& start,
71 const SelectionBound& end) { 95 const SelectionBound& end) {
72 if (start == start_ && end_ == end) 96 if (start == start_ && end_ == end)
73 return; 97 return false;
74 98
75 start_ = start; 99 start_ = start;
76 end_ = end; 100 end_ = end;
77 start_orientation_ = ToTouchHandleOrientation(start_.type()); 101 start_orientation_ = ToTouchHandleOrientation(start_.type());
78 end_orientation_ = ToTouchHandleOrientation(end_.type()); 102 end_orientation_ = ToTouchHandleOrientation(end_.type());
79 103
80 if (!activate_selection_automatically_ && 104 if (!activate_selection_automatically_ &&
81 !activate_insertion_automatically_) { 105 !activate_insertion_automatically_) {
82 DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_); 106 DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_);
83 return; 107 return false;
84 } 108 }
85 109
86 // Ensure that |response_pending_input_event_| is cleared after the method 110 // Ensure that |response_pending_input_event_| is cleared after the method
87 // completes, while also making its current value available for the duration 111 // completes, while also making its current value available for the duration
88 // of the call. 112 // of the call.
89 InputEventType causal_input_event = response_pending_input_event_; 113 InputEventType causal_input_event = response_pending_input_event_;
90 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; 114 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
91 base::AutoReset<InputEventType> auto_reset_response_pending_input_event( 115 base::AutoReset<InputEventType> auto_reset_response_pending_input_event(
92 &response_pending_input_event_, causal_input_event); 116 &response_pending_input_event_, causal_input_event);
93 117
(...skipping 12 matching lines...) Expand all
106 start_orientation_ = start_selection_handle_->orientation(); 130 start_orientation_ = start_selection_handle_->orientation();
107 if (end_orientation_ == TouchHandleOrientation::CENTER) 131 if (end_orientation_ == TouchHandleOrientation::CENTER)
108 end_orientation_ = end_selection_handle_->orientation(); 132 end_orientation_ = end_selection_handle_->orientation();
109 } 133 }
110 134
111 if (GetStartPosition() != GetEndPosition() || 135 if (GetStartPosition() != GetEndPosition() ||
112 (is_selection_dragging && 136 (is_selection_dragging &&
113 start_orientation_ != TouchHandleOrientation::UNDEFINED && 137 start_orientation_ != TouchHandleOrientation::UNDEFINED &&
114 end_orientation_ != TouchHandleOrientation::UNDEFINED)) { 138 end_orientation_ != TouchHandleOrientation::UNDEFINED)) {
115 OnSelectionChanged(); 139 OnSelectionChanged();
116 return; 140 UpdateQuickMenu();
141 return true;
117 } 142 }
118 143
119 if (start_orientation_ == TouchHandleOrientation::CENTER && 144 if (start_orientation_ == TouchHandleOrientation::CENTER &&
120 selection_editable_) { 145 selection_editable_) {
121 OnInsertionChanged(); 146 OnInsertionChanged();
122 return; 147 return true;
123 } 148 }
124 149
125 HideAndDisallowShowingAutomatically(); 150 HideAndDisallowShowingAutomatically();
151 return true;
126 } 152 }
127 153
128 bool TouchSelectionController::WillHandleTouchEvent(const MotionEvent& event) { 154 bool TouchSelectionControllerImpl::WillHandleTouchEvent(
155 const MotionEvent& event) {
129 if (is_insertion_active_) { 156 if (is_insertion_active_) {
130 DCHECK(insertion_handle_); 157 DCHECK(insertion_handle_);
131 return insertion_handle_->WillHandleTouchEvent(event); 158 return insertion_handle_->WillHandleTouchEvent(event);
132 } 159 }
133 160
134 if (is_selection_active_) { 161 if (is_selection_active_) {
135 DCHECK(start_selection_handle_); 162 DCHECK(start_selection_handle_);
136 DCHECK(end_selection_handle_); 163 DCHECK(end_selection_handle_);
137 if (start_selection_handle_->is_dragging()) 164 if (start_selection_handle_->is_dragging())
138 return start_selection_handle_->WillHandleTouchEvent(event); 165 return start_selection_handle_->WillHandleTouchEvent(event);
139 166
140 if (end_selection_handle_->is_dragging()) 167 if (end_selection_handle_->is_dragging())
141 return end_selection_handle_->WillHandleTouchEvent(event); 168 return end_selection_handle_->WillHandleTouchEvent(event);
142 169
143 const gfx::PointF event_pos(event.GetX(), event.GetY()); 170 const gfx::PointF event_pos(event.GetX(), event.GetY());
144 if ((event_pos - GetStartPosition()).LengthSquared() <= 171 if ((event_pos - GetStartPosition()).LengthSquared() <=
145 (event_pos - GetEndPosition()).LengthSquared()) 172 (event_pos - GetEndPosition()).LengthSquared())
146 return start_selection_handle_->WillHandleTouchEvent(event); 173 return start_selection_handle_->WillHandleTouchEvent(event);
147 else 174 else
148 return end_selection_handle_->WillHandleTouchEvent(event); 175 return end_selection_handle_->WillHandleTouchEvent(event);
149 } 176 }
150 177
151 return false; 178 return false;
152 } 179 }
153 180
154 void TouchSelectionController::OnLongPressEvent() { 181 void TouchSelectionControllerImpl::OnLongPressEvent() {
155 response_pending_input_event_ = LONG_PRESS; 182 response_pending_input_event_ = LONG_PRESS;
156 ShowSelectionHandlesAutomatically(); 183 ShowSelectionHandlesAutomatically();
157 ShowInsertionHandleAutomatically(); 184 ShowInsertionHandleAutomatically();
158 ResetCachedValuesIfInactive(); 185 ResetCachedValuesIfInactive();
159 } 186 }
160 187
161 void TouchSelectionController::AllowShowingFromCurrentSelection() { 188 void TouchSelectionControllerImpl::AllowShowingFromCurrentSelection() {
162 if (is_selection_active_ || is_insertion_active_) 189 if (is_selection_active_ || is_insertion_active_)
163 return; 190 return;
164 191
165 activate_selection_automatically_ = true; 192 activate_selection_automatically_ = true;
166 activate_insertion_automatically_ = true; 193 activate_insertion_automatically_ = true;
167 if (GetStartPosition() != GetEndPosition()) 194 if (GetStartPosition() != GetEndPosition())
168 OnSelectionChanged(); 195 OnSelectionChanged();
169 else if (start_orientation_ == TouchHandleOrientation::CENTER && 196 else if (start_orientation_ == TouchHandleOrientation::CENTER &&
170 selection_editable_) 197 selection_editable_)
171 OnInsertionChanged(); 198 OnInsertionChanged();
199 // TODO(mfomitchev): May not be needed
200 UpdateQuickMenu();
172 } 201 }
173 202
174 void TouchSelectionController::OnTapEvent() { 203 void TouchSelectionControllerImpl::OnTapEvent() {
175 response_pending_input_event_ = TAP; 204 response_pending_input_event_ = TAP;
176 ShowInsertionHandleAutomatically(); 205 ShowInsertionHandleAutomatically();
177 if (selection_empty_ && !show_on_tap_for_empty_editable_) 206 if (selection_empty_ && !show_on_tap_for_empty_editable_)
178 DeactivateInsertion(); 207 DeactivateInsertion();
179 ResetCachedValuesIfInactive(); 208 ResetCachedValuesIfInactive();
180 } 209 }
181 210
182 void TouchSelectionController::HideAndDisallowShowingAutomatically() { 211 void TouchSelectionControllerImpl::HideAndDisallowShowingAutomatically() {
183 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; 212 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
184 DeactivateInsertion(); 213 DeactivateInsertion();
185 DeactivateSelection(); 214 DeactivateSelection();
186 activate_insertion_automatically_ = false; 215 activate_insertion_automatically_ = false;
187 activate_selection_automatically_ = false; 216 activate_selection_automatically_ = false;
217 //UpdateQuickMenu(); - DOn't think this is needed
188 } 218 }
189 219
190 void TouchSelectionController::SetTemporarilyHidden(bool hidden) { 220 void TouchSelectionControllerImpl::SetTemporarilyHidden(bool hidden) {
191 if (temporarily_hidden_ == hidden) 221 if (temporarily_hidden_ == hidden)
192 return; 222 return;
193 temporarily_hidden_ = hidden; 223 temporarily_hidden_ = hidden;
194 224
195 TouchHandle::AnimationStyle animation_style = GetAnimationStyle(true); 225 TouchHandle::AnimationStyle animation_style = GetAnimationStyle(true);
196 if (is_selection_active_) { 226 if (is_selection_active_) {
197 start_selection_handle_->SetVisible(GetStartVisible(), animation_style); 227 start_selection_handle_->SetVisible(GetStartVisible(), animation_style);
198 end_selection_handle_->SetVisible(GetEndVisible(), animation_style); 228 end_selection_handle_->SetVisible(GetEndVisible(), animation_style);
199 } 229 }
200 if (is_insertion_active_) 230 if (is_insertion_active_)
201 insertion_handle_->SetVisible(GetStartVisible(), animation_style); 231 insertion_handle_->SetVisible(GetStartVisible(), animation_style);
202 } 232 }
203 233
204 void TouchSelectionController::OnSelectionEditable(bool editable) { 234 void TouchSelectionControllerImpl::OnSelectionEditable(bool editable) {
205 if (selection_editable_ == editable) 235 if (selection_editable_ == editable)
206 return; 236 return;
207 selection_editable_ = editable; 237 selection_editable_ = editable;
208 ResetCachedValuesIfInactive(); 238 ResetCachedValuesIfInactive();
209 if (!selection_editable_) 239 if (!selection_editable_)
210 DeactivateInsertion(); 240 DeactivateInsertion();
241 UpdateQuickMenu();
211 } 242 }
212 243
213 void TouchSelectionController::OnSelectionEmpty(bool empty) { 244 void TouchSelectionControllerImpl::OnSelectionEmpty(bool empty) {
214 if (selection_empty_ == empty) 245 if (selection_empty_ == empty)
215 return; 246 return;
216 selection_empty_ = empty; 247 selection_empty_ = empty;
217 ResetCachedValuesIfInactive(); 248 ResetCachedValuesIfInactive();
249 // TODO: Do we really need this?
250 UpdateQuickMenu();
218 } 251 }
219 252
220 bool TouchSelectionController::Animate(base::TimeTicks frame_time) { 253 bool TouchSelectionControllerImpl::Animate(base::TimeTicks frame_time) {
221 if (is_insertion_active_) 254 if (is_insertion_active_)
222 return insertion_handle_->Animate(frame_time); 255 return insertion_handle_->Animate(frame_time);
223 256
224 if (is_selection_active_) { 257 if (is_selection_active_) {
225 bool needs_animate = start_selection_handle_->Animate(frame_time); 258 bool needs_animate = start_selection_handle_->Animate(frame_time);
226 needs_animate |= end_selection_handle_->Animate(frame_time); 259 needs_animate |= end_selection_handle_->Animate(frame_time);
227 return needs_animate; 260 return needs_animate;
228 } 261 }
229 262
230 return false; 263 return false;
231 } 264 }
232 265
233 void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) { 266 void TouchSelectionControllerImpl::OnNativeViewMoved() {
267 UpdateQuickMenu();
268 }
269
270 void TouchSelectionControllerImpl::OnScrollStarted() {
271 scroll_in_progress_ = true;
272 UpdateQuickMenu();
273 }
274
275 void TouchSelectionControllerImpl::OnScrollCompleted() {
276 scroll_in_progress_ = false;
277 UpdateQuickMenu();
278 }
279
280 void TouchSelectionControllerImpl::OnOverscrollStarted() {
281 overscroll_in_progress_ = true;
282 UpdateQuickMenu();
283 }
284
285 void TouchSelectionControllerImpl::OnOverscrollCompleted() {
286 overscroll_in_progress_ = false;
287 UpdateQuickMenu();
288 }
289
290 void TouchSelectionControllerImpl::OnFlingCompleted() {
291 scroll_in_progress_ = false;
292 UpdateQuickMenu();
293 }
294
295 void TouchSelectionControllerImpl::OnHandleDragBegin(
296 const TouchHandle& handle) {
234 if (&handle == insertion_handle_.get()) { 297 if (&handle == insertion_handle_.get()) {
235 client_->OnSelectionEvent(INSERTION_DRAG_STARTED, handle.position()); 298 client_->OnSelectionEvent(INSERTION_DRAG_STARTED, handle.position());
299 UpdateQuickMenu();
236 return; 300 return;
237 } 301 }
238 302
239 gfx::PointF base, extent; 303 gfx::PointF base, extent;
240 if (&handle == start_selection_handle_.get()) { 304 if (&handle == start_selection_handle_.get()) {
241 base = end_selection_handle_->position() + GetEndLineOffset(); 305 base = end_selection_handle_->position() + GetEndLineOffset();
242 extent = start_selection_handle_->position() + GetStartLineOffset(); 306 extent = start_selection_handle_->position() + GetStartLineOffset();
243 } else { 307 } else {
244 base = start_selection_handle_->position() + GetStartLineOffset(); 308 base = start_selection_handle_->position() + GetStartLineOffset();
245 extent = end_selection_handle_->position() + GetEndLineOffset(); 309 extent = end_selection_handle_->position() + GetEndLineOffset();
246 } 310 }
247 selection_handle_dragged_ = true; 311 selection_handle_was_dragged_ = true;
248 312
249 // When moving the handle we want to move only the extent point. Before doing 313 // When moving the handle we want to move only the extent point. Before doing
250 // so we must make sure that the base point is set correctly. 314 // so we must make sure that the base point is set correctly.
251 client_->SelectBetweenCoordinates(base, extent); 315 client_->SelectBetweenCoordinates(base, extent);
252 316
253 client_->OnSelectionEvent(SELECTION_DRAG_STARTED, handle.position()); 317 client_->OnSelectionEvent(SELECTION_DRAG_STARTED, handle.position());
318 UpdateQuickMenu();
254 } 319 }
255 320
256 void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle, 321 void TouchSelectionControllerImpl::OnHandleDragUpdate(const TouchHandle& handle,
257 const gfx::PointF& position) { 322 const gfx::PointF& position) {
258 // As the position corresponds to the bottom left point of the selection 323 // As the position corresponds to the bottom left point of the selection
259 // bound, offset it by half the corresponding line height. 324 // bound, offset it by half the corresponding line height.
260 gfx::Vector2dF line_offset = &handle == start_selection_handle_.get() 325 gfx::Vector2dF line_offset = &handle == start_selection_handle_.get()
261 ? GetStartLineOffset() 326 ? GetStartLineOffset()
262 : GetEndLineOffset(); 327 : GetEndLineOffset();
263 gfx::PointF line_position = position + line_offset; 328 gfx::PointF line_position = position + line_offset;
264 if (&handle == insertion_handle_.get()) { 329 if (&handle == insertion_handle_.get())
265 client_->MoveCaret(line_position); 330 client_->MoveCaret(line_position);
266 } else { 331 else
267 client_->MoveRangeSelectionExtent(line_position); 332 client_->MoveRangeSelectionExtent(line_position);
268 }
269 } 333 }
270 334
271 void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) { 335 void TouchSelectionControllerImpl::OnHandleDragEnd(const TouchHandle& handle) {
272 if (&handle == insertion_handle_.get()) 336 if (&handle == insertion_handle_.get())
273 client_->OnSelectionEvent(INSERTION_DRAG_STOPPED, handle.position()); 337 client_->OnSelectionEvent(INSERTION_DRAG_STOPPED, handle.position());
274 else 338 else
275 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED, handle.position()); 339 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED, handle.position());
340 UpdateQuickMenu();
276 } 341 }
277 342
278 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) { 343 void TouchSelectionControllerImpl::OnHandleTapped(const TouchHandle& handle) {
279 if (insertion_handle_ && &handle == insertion_handle_.get()) 344 if (insertion_handle_ && &handle == insertion_handle_.get())
280 client_->OnSelectionEvent(INSERTION_TAPPED, handle.position()); 345 client_->OnSelectionEvent(INSERTION_TAPPED, handle.position());
281 } 346 }
282 347
283 void TouchSelectionController::SetNeedsAnimate() { 348 void TouchSelectionControllerImpl::SetNeedsAnimate() {
284 client_->SetNeedsAnimate(); 349 client_->SetNeedsAnimate();
285 } 350 }
286 351
287 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() { 352 scoped_ptr<TouchHandleDrawable> TouchSelectionControllerImpl::CreateDrawable() {
288 return client_->CreateDrawable(); 353 return client_->CreateDrawable();
289 } 354 }
290 355
291 base::TimeDelta TouchSelectionController::GetTapTimeout() const { 356 base::TimeDelta TouchSelectionControllerImpl::GetTapTimeout() const {
292 return tap_timeout_; 357 return tap_timeout_;
293 } 358 }
294 359
295 float TouchSelectionController::GetTapSlop() const { 360 float TouchSelectionControllerImpl::GetTapSlop() const {
296 return tap_slop_; 361 return tap_slop_;
297 } 362 }
298 363
299 void TouchSelectionController::ShowInsertionHandleAutomatically() { 364 void TouchSelectionControllerImpl::ShowInsertionHandleAutomatically() {
300 if (activate_insertion_automatically_) 365 if (activate_insertion_automatically_)
301 return; 366 return;
302 activate_insertion_automatically_ = true; 367 activate_insertion_automatically_ = true;
303 ResetCachedValuesIfInactive(); 368 ResetCachedValuesIfInactive();
304 } 369 }
305 370
306 void TouchSelectionController::ShowSelectionHandlesAutomatically() { 371 void TouchSelectionControllerImpl::ShowSelectionHandlesAutomatically() {
307 if (activate_selection_automatically_) 372 if (activate_selection_automatically_)
308 return; 373 return;
309 activate_selection_automatically_ = true; 374 activate_selection_automatically_ = true;
310 ResetCachedValuesIfInactive(); 375 ResetCachedValuesIfInactive();
311 } 376 }
312 377
313 void TouchSelectionController::OnInsertionChanged() { 378 void TouchSelectionControllerImpl::OnInsertionChanged() {
314 DeactivateSelection(); 379 DeactivateSelection();
315 380
316 if (response_pending_input_event_ == TAP && selection_empty_ && 381 if (response_pending_input_event_ == TAP && selection_empty_ &&
317 !show_on_tap_for_empty_editable_) { 382 !show_on_tap_for_empty_editable_) {
318 HideAndDisallowShowingAutomatically(); 383 HideAndDisallowShowingAutomatically();
319 return; 384 return;
320 } 385 }
321 386
322 if (!activate_insertion_automatically_) 387 if (!activate_insertion_automatically_)
323 return; 388 return;
324 389
325 const bool was_active = is_insertion_active_; 390 const bool was_active = is_insertion_active_;
326 const gfx::PointF position = GetStartPosition(); 391 const gfx::PointF position = GetStartPosition();
327 if (!is_insertion_active_) 392 if (!is_insertion_active_)
328 ActivateInsertion(); 393 ActivateInsertion();
329 else 394 else
330 client_->OnSelectionEvent(INSERTION_MOVED, position); 395 client_->OnSelectionEvent(INSERTION_MOVED, position);
331 396
332 insertion_handle_->SetVisible(GetStartVisible(), 397 insertion_handle_->SetVisible(GetStartVisible(),
333 GetAnimationStyle(was_active)); 398 GetAnimationStyle(was_active));
334 insertion_handle_->SetPosition(position); 399 insertion_handle_->SetPosition(position);
335 } 400 }
336 401
337 void TouchSelectionController::OnSelectionChanged() { 402 void TouchSelectionControllerImpl::OnSelectionChanged() {
338 DeactivateInsertion(); 403 DeactivateInsertion();
339 404
340 if (!activate_selection_automatically_) 405 if (!activate_selection_automatically_)
341 return; 406 return;
342 407
343 const bool was_active = is_selection_active_; 408 const bool was_active = is_selection_active_;
344 ActivateSelection(); 409 ActivateSelection();
345 410
346 const TouchHandle::AnimationStyle animation = GetAnimationStyle(was_active); 411 const TouchHandle::AnimationStyle animation = GetAnimationStyle(was_active);
347 start_selection_handle_->SetVisible(GetStartVisible(), animation); 412 start_selection_handle_->SetVisible(GetStartVisible(), animation);
348 end_selection_handle_->SetVisible(GetEndVisible(), animation); 413 end_selection_handle_->SetVisible(GetEndVisible(), animation);
349 414
350 start_selection_handle_->SetPosition(GetStartPosition()); 415 start_selection_handle_->SetPosition(GetStartPosition());
351 end_selection_handle_->SetPosition(GetEndPosition()); 416 end_selection_handle_->SetPosition(GetEndPosition());
352 } 417 }
353 418
354 void TouchSelectionController::ActivateInsertion() { 419 void TouchSelectionControllerImpl::ActivateInsertion() {
355 DCHECK(!is_selection_active_); 420 DCHECK(!is_selection_active_);
356 421
357 if (!insertion_handle_) 422 if (!insertion_handle_)
358 insertion_handle_.reset( 423 insertion_handle_.reset(
359 new TouchHandle(this, TouchHandleOrientation::CENTER)); 424 new TouchHandle(this, TouchHandleOrientation::CENTER));
360 425
361 if (!is_insertion_active_) { 426 if (!is_insertion_active_) {
362 is_insertion_active_ = true; 427 is_insertion_active_ = true;
363 insertion_handle_->SetEnabled(true); 428 insertion_handle_->SetEnabled(true);
364 client_->OnSelectionEvent(INSERTION_SHOWN, GetStartPosition()); 429 client_->OnSelectionEvent(INSERTION_SHOWN, GetStartPosition());
430 UpdateQuickMenu();
365 } 431 }
366 } 432 }
367 433
368 void TouchSelectionController::DeactivateInsertion() { 434 void TouchSelectionControllerImpl::DeactivateInsertion() {
369 if (!is_insertion_active_) 435 if (!is_insertion_active_)
370 return; 436 return;
371 DCHECK(insertion_handle_); 437 DCHECK(insertion_handle_);
372 is_insertion_active_ = false; 438 is_insertion_active_ = false;
373 insertion_handle_->SetEnabled(false); 439 insertion_handle_->SetEnabled(false);
374 client_->OnSelectionEvent(INSERTION_CLEARED, gfx::PointF()); 440 client_->OnSelectionEvent(INSERTION_CLEARED, gfx::PointF());
441 UpdateQuickMenu();
375 } 442 }
376 443
377 void TouchSelectionController::ActivateSelection() { 444 void TouchSelectionControllerImpl::ActivateSelection() {
378 DCHECK(!is_insertion_active_); 445 DCHECK(!is_insertion_active_);
379 446
380 if (!start_selection_handle_) { 447 if (!start_selection_handle_) {
381 start_selection_handle_.reset(new TouchHandle(this, start_orientation_)); 448 start_selection_handle_.reset(new TouchHandle(this, start_orientation_));
382 } else { 449 } else {
383 start_selection_handle_->SetEnabled(true); 450 start_selection_handle_->SetEnabled(true);
384 start_selection_handle_->SetOrientation(start_orientation_); 451 start_selection_handle_->SetOrientation(start_orientation_);
385 } 452 }
386 453
387 if (!end_selection_handle_) { 454 if (!end_selection_handle_) {
388 end_selection_handle_.reset(new TouchHandle(this, end_orientation_)); 455 end_selection_handle_.reset(new TouchHandle(this, end_orientation_));
389 } else { 456 } else {
390 end_selection_handle_->SetEnabled(true); 457 end_selection_handle_->SetEnabled(true);
391 end_selection_handle_->SetOrientation(end_orientation_); 458 end_selection_handle_->SetOrientation(end_orientation_);
392 } 459 }
393 460
394 // As a long press received while a selection is already active may trigger 461 // As a long press received while a selection is already active may trigger
395 // an entirely new selection, notify the client but avoid sending an 462 // an entirely new selection, notify the client but avoid sending an
396 // intervening SELECTION_CLEARED update to avoid unnecessary state changes. 463 // intervening SELECTION_CLEARED update to avoid unnecessary state changes.
397 if (!is_selection_active_ || response_pending_input_event_ == LONG_PRESS) { 464 if (!is_selection_active_ || response_pending_input_event_ == LONG_PRESS) {
398 if (is_selection_active_) { 465 if (is_selection_active_) {
399 // The active selection session finishes with the start of the new one. 466 // The active selection session finishes with the start of the new one.
400 LogSelectionEnd(); 467 LogSelectionEnd();
401 } 468 }
402 is_selection_active_ = true; 469 is_selection_active_ = true;
403 selection_handle_dragged_ = false; 470 selection_handle_was_dragged_ = false;
404 selection_start_time_ = base::TimeTicks::Now(); 471 selection_start_time_ = base::TimeTicks::Now();
405 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; 472 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
406 client_->OnSelectionEvent(SELECTION_SHOWN, GetStartPosition()); 473 client_->OnSelectionEvent(SELECTION_SHOWN, GetStartPosition());
474 UpdateQuickMenu();
407 } 475 }
408 } 476 }
409 477
410 void TouchSelectionController::DeactivateSelection() { 478 void TouchSelectionControllerImpl::DeactivateSelection() {
411 if (!is_selection_active_) 479 if (!is_selection_active_)
412 return; 480 return;
413 DCHECK(start_selection_handle_); 481 DCHECK(start_selection_handle_);
414 DCHECK(end_selection_handle_); 482 DCHECK(end_selection_handle_);
415 LogSelectionEnd(); 483 LogSelectionEnd();
416 start_selection_handle_->SetEnabled(false); 484 start_selection_handle_->SetEnabled(false);
417 end_selection_handle_->SetEnabled(false); 485 end_selection_handle_->SetEnabled(false);
418 is_selection_active_ = false; 486 is_selection_active_ = false;
419 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF()); 487 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF());
488 UpdateQuickMenu();
420 } 489 }
421 490
422 void TouchSelectionController::ResetCachedValuesIfInactive() { 491 void TouchSelectionControllerImpl::ResetCachedValuesIfInactive() {
423 if (is_selection_active_ || is_insertion_active_) 492 if (is_selection_active_ || is_insertion_active_)
424 return; 493 return;
425 start_ = SelectionBound(); 494 start_ = SelectionBound();
426 end_ = SelectionBound(); 495 end_ = SelectionBound();
427 start_orientation_ = TouchHandleOrientation::UNDEFINED; 496 start_orientation_ = TouchHandleOrientation::UNDEFINED;
428 end_orientation_ = TouchHandleOrientation::UNDEFINED; 497 end_orientation_ = TouchHandleOrientation::UNDEFINED;
429 } 498 }
430 499
431 const gfx::PointF& TouchSelectionController::GetStartPosition() const { 500 const gfx::PointF& TouchSelectionControllerImpl::GetStartPosition() const {
432 return start_.edge_bottom(); 501 return start_.edge_bottom();
433 } 502 }
434 503
435 const gfx::PointF& TouchSelectionController::GetEndPosition() const { 504 const gfx::PointF& TouchSelectionControllerImpl::GetEndPosition() const {
436 return end_.edge_bottom(); 505 return end_.edge_bottom();
437 } 506 }
438 507
439 gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const { 508 gfx::Vector2dF TouchSelectionControllerImpl::GetStartLineOffset() const {
440 return ComputeLineOffsetFromBottom(start_); 509 return ComputeLineOffsetFromBottom(start_);
441 } 510 }
442 511
443 gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const { 512 gfx::Vector2dF TouchSelectionControllerImpl::GetEndLineOffset() const {
444 return ComputeLineOffsetFromBottom(end_); 513 return ComputeLineOffsetFromBottom(end_);
445 } 514 }
446 515
447 bool TouchSelectionController::GetStartVisible() const { 516 bool TouchSelectionControllerImpl::GetStartVisible() const {
448 return start_.visible() && !temporarily_hidden_; 517 return start_.visible() && !temporarily_hidden_;
449 } 518 }
450 519
451 bool TouchSelectionController::GetEndVisible() const { 520 bool TouchSelectionControllerImpl::GetEndVisible() const {
452 return end_.visible() && !temporarily_hidden_; 521 return end_.visible() && !temporarily_hidden_;
453 } 522 }
454 523
455 TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle( 524 TouchHandle::AnimationStyle TouchSelectionControllerImpl::GetAnimationStyle(
456 bool was_active) const { 525 bool was_active) const {
457 return was_active && client_->SupportsAnimation() 526 return was_active && client_->SupportsAnimation()
458 ? TouchHandle::ANIMATION_SMOOTH 527 ? TouchHandle::ANIMATION_SMOOTH
459 : TouchHandle::ANIMATION_NONE; 528 : TouchHandle::ANIMATION_NONE;
460 } 529 }
461 530
462 void TouchSelectionController::LogSelectionEnd() { 531 gfx::Rect TouchSelectionControllerImpl::GetMenuAnchorRect() const {
532 SelectionBound clipped_start = start();
533 SelectionBound clipped_end = end();
534 const gfx::Rect& client_bounds = client_->GetClientBounds();
535 if (clipped_start.visible())
536 ClipSelectionBound(&clipped_start, client_bounds);
537 if (clipped_end.visible())
538 ClipSelectionBound(&clipped_end, client_bounds);
539
540 if (clipped_start.visible() && clipped_end.visible())
541 return RectBetweenSelectionBounds(clipped_start, clipped_end);
542 if (clipped_start.visible()) {
543 return gfx::BoundingRect(clipped_start.edge_top_rounded(),
544 clipped_start.edge_bottom_rounded());
545 }
546 return gfx::BoundingRect(clipped_end.edge_top_rounded(),
547 clipped_end.edge_bottom_rounded());
548 }
549
550 void TouchSelectionControllerImpl::ShowQuickMenu() {
jdduke (slow) 2015/03/30 15:46:22 All of this menu code will have to be a no-op on A
551 DCHECK(is_insertion_active() || is_selection_active());
552
553 if (!start().visible() &&
554 !end().visible())
555 return;
556
557 if (TouchSelectionMenuRunner::GetInstance())
558 client_->ShowQuickMenu(GetMenuAnchorRect());
559 }
560
561 void TouchSelectionControllerImpl::UpdateQuickMenu() {
562 // Hide quick menu if there is any.
563 client_->HideQuickMenu();
564 quick_menu_timer_.Stop();
565
566 // Start timer to show quick menu if necessary.
567 if (!is_insertion_active() && !is_selection_active())
568 return;
569
570 if (!IsQuickMenuAllowed())
571 return;
572
573 // TODO: test API
574 // if (test_api_ && test_api_->immediate_quick_menu())
575 // ShowQuickMenu();
576 // else
577 quick_menu_timer_.Reset();
578 }
579
580 bool TouchSelectionControllerImpl::IsQuickMenuAllowed() const {
581 return !scroll_in_progress_ && !overscroll_in_progress_ &&
582 !handle_drag_in_progress_;
583 }
584
585 void TouchSelectionControllerImpl::LogSelectionEnd() {
463 // TODO(mfomitchev): Once we are able to tell the difference between 586 // TODO(mfomitchev): Once we are able to tell the difference between
464 // 'successful' and 'unsuccessful' selections - log 587 // 'successful' and 'unsuccessful' selections - log
465 // Event.TouchSelection.Duration instead and get rid of 588 // Event.TouchSelection.Duration instead and get rid of
466 // Event.TouchSelectionD.WasDraggeduration. 589 // Event.TouchSelectionD.WasDraggeduration.
467 if (selection_handle_dragged_) { 590 if (selection_handle_was_dragged_) {
468 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; 591 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_;
469 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", 592 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration",
470 duration, 593 duration,
471 base::TimeDelta::FromMilliseconds(500), 594 base::TimeDelta::FromMilliseconds(500),
472 base::TimeDelta::FromSeconds(60), 595 base::TimeDelta::FromSeconds(60),
473 60); 596 60);
474 } 597 }
475 } 598 }
476 599
477 } // namespace ui 600 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698