Chromium Code Reviews| 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_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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 | 223 |
| 224 if (is_selection_active_) { | 224 if (is_selection_active_) { |
| 225 bool needs_animate = start_selection_handle_->Animate(frame_time); | 225 bool needs_animate = start_selection_handle_->Animate(frame_time); |
| 226 needs_animate |= end_selection_handle_->Animate(frame_time); | 226 needs_animate |= end_selection_handle_->Animate(frame_time); |
| 227 return needs_animate; | 227 return needs_animate; |
| 228 } | 228 } |
| 229 | 229 |
| 230 return false; | 230 return false; |
| 231 } | 231 } |
| 232 | 232 |
| 233 gfx::RectF TouchSelectionController::GetRectBetweenBounds() const { | |
| 234 // Short-circuit for efficiency. | |
| 235 if (!is_insertion_active_ && !is_selection_active_) | |
| 236 return gfx::RectF(); | |
| 237 | |
| 238 if (start_.visible() && !end_.visible()) | |
| 239 return gfx::BoundingRect(start_.edge_top(), start_.edge_bottom()); | |
| 240 | |
| 241 if (end_.visible() && !start_.visible()) | |
| 242 return gfx::BoundingRect(end_.edge_top(), end_.edge_bottom()); | |
| 243 | |
| 244 // If both handles are visible, or both are invisible, use the entire rect. | |
| 245 return RectFBetweenSelectionBounds(start_, end_); | |
|
mfomitchev
2015/04/14 15:02:33
Can't we also have a case when non are visible (bu
jdduke (slow)
2015/04/14 15:19:30
For sure, but I think the controller should be som
| |
| 246 } | |
| 247 | |
| 248 gfx::RectF TouchSelectionController::GetRectBetweenBoundsIncludingHandles() | |
|
mfomitchev
2015/04/14 15:02:33
Having a method returning MaxHandleImageSize/MaxHa
jdduke (slow)
2015/04/14 15:19:30
Well, we may simply have to differ between platfor
| |
| 249 const { | |
| 250 gfx::RectF rect = GetRectBetweenBounds(); | |
| 251 if (rect.IsEmpty()) | |
| 252 return rect; | |
| 253 | |
| 254 if (is_insertion_active_) { | |
| 255 rect.Union(insertion_handle_->GetVisibleBounds()); | |
| 256 } else if (is_selection_active_) { | |
| 257 rect.Union(start_selection_handle_->GetVisibleBounds()); | |
| 258 rect.Union(end_selection_handle_->GetVisibleBounds()); | |
| 259 } | |
| 260 | |
| 261 return rect; | |
| 262 } | |
| 263 | |
| 264 const gfx::PointF& TouchSelectionController::GetStartPosition() const { | |
| 265 return start_.edge_bottom(); | |
| 266 } | |
| 267 | |
| 268 const gfx::PointF& TouchSelectionController::GetEndPosition() const { | |
| 269 return end_.edge_bottom(); | |
| 270 } | |
| 271 | |
| 233 void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) { | 272 void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) { |
| 234 if (&handle == insertion_handle_.get()) { | 273 if (&handle == insertion_handle_.get()) { |
| 235 client_->OnSelectionEvent(INSERTION_DRAG_STARTED, handle.position()); | 274 client_->OnSelectionEvent(INSERTION_DRAG_STARTED); |
| 236 return; | 275 return; |
| 237 } | 276 } |
| 238 | 277 |
| 239 gfx::PointF base, extent; | 278 gfx::PointF base, extent; |
| 240 if (&handle == start_selection_handle_.get()) { | 279 if (&handle == start_selection_handle_.get()) { |
| 241 base = end_selection_handle_->position() + GetEndLineOffset(); | 280 base = end_selection_handle_->position() + GetEndLineOffset(); |
| 242 extent = start_selection_handle_->position() + GetStartLineOffset(); | 281 extent = start_selection_handle_->position() + GetStartLineOffset(); |
| 243 } else { | 282 } else { |
| 244 base = start_selection_handle_->position() + GetStartLineOffset(); | 283 base = start_selection_handle_->position() + GetStartLineOffset(); |
| 245 extent = end_selection_handle_->position() + GetEndLineOffset(); | 284 extent = end_selection_handle_->position() + GetEndLineOffset(); |
| 246 } | 285 } |
| 247 selection_handle_dragged_ = true; | 286 selection_handle_dragged_ = true; |
| 248 | 287 |
| 249 // When moving the handle we want to move only the extent point. Before doing | 288 // 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. | 289 // so we must make sure that the base point is set correctly. |
| 251 client_->SelectBetweenCoordinates(base, extent); | 290 client_->SelectBetweenCoordinates(base, extent); |
| 252 | 291 client_->OnSelectionEvent(SELECTION_DRAG_STARTED); |
| 253 client_->OnSelectionEvent(SELECTION_DRAG_STARTED, handle.position()); | |
| 254 } | 292 } |
| 255 | 293 |
| 256 void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle, | 294 void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle, |
| 257 const gfx::PointF& position) { | 295 const gfx::PointF& position) { |
| 258 // As the position corresponds to the bottom left point of the selection | 296 // As the position corresponds to the bottom left point of the selection |
| 259 // bound, offset it by half the corresponding line height. | 297 // bound, offset it by half the corresponding line height. |
| 260 gfx::Vector2dF line_offset = &handle == start_selection_handle_.get() | 298 gfx::Vector2dF line_offset = &handle == start_selection_handle_.get() |
| 261 ? GetStartLineOffset() | 299 ? GetStartLineOffset() |
| 262 : GetEndLineOffset(); | 300 : GetEndLineOffset(); |
| 263 gfx::PointF line_position = position + line_offset; | 301 gfx::PointF line_position = position + line_offset; |
| 264 if (&handle == insertion_handle_.get()) { | 302 if (&handle == insertion_handle_.get()) { |
| 265 client_->MoveCaret(line_position); | 303 client_->MoveCaret(line_position); |
| 266 } else { | 304 } else { |
| 267 client_->MoveRangeSelectionExtent(line_position); | 305 client_->MoveRangeSelectionExtent(line_position); |
| 268 } | 306 } |
| 269 } | 307 } |
| 270 | 308 |
| 271 void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) { | 309 void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) { |
| 272 if (&handle == insertion_handle_.get()) | 310 if (&handle == insertion_handle_.get()) |
| 273 client_->OnSelectionEvent(INSERTION_DRAG_STOPPED, handle.position()); | 311 client_->OnSelectionEvent(INSERTION_DRAG_STOPPED); |
| 274 else | 312 else |
| 275 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED, handle.position()); | 313 client_->OnSelectionEvent(SELECTION_DRAG_STOPPED); |
| 276 } | 314 } |
| 277 | 315 |
| 278 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) { | 316 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) { |
| 279 if (insertion_handle_ && &handle == insertion_handle_.get()) | 317 if (insertion_handle_ && &handle == insertion_handle_.get()) |
| 280 client_->OnSelectionEvent(INSERTION_TAPPED, handle.position()); | 318 client_->OnSelectionEvent(INSERTION_TAPPED); |
| 281 } | 319 } |
| 282 | 320 |
| 283 void TouchSelectionController::SetNeedsAnimate() { | 321 void TouchSelectionController::SetNeedsAnimate() { |
| 284 client_->SetNeedsAnimate(); | 322 client_->SetNeedsAnimate(); |
| 285 } | 323 } |
| 286 | 324 |
| 287 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() { | 325 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() { |
| 288 return client_->CreateDrawable(); | 326 return client_->CreateDrawable(); |
| 289 } | 327 } |
| 290 | 328 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 320 } | 358 } |
| 321 | 359 |
| 322 if (!activate_insertion_automatically_) | 360 if (!activate_insertion_automatically_) |
| 323 return; | 361 return; |
| 324 | 362 |
| 325 const bool was_active = is_insertion_active_; | 363 const bool was_active = is_insertion_active_; |
| 326 const gfx::PointF position = GetStartPosition(); | 364 const gfx::PointF position = GetStartPosition(); |
| 327 if (!is_insertion_active_) | 365 if (!is_insertion_active_) |
| 328 ActivateInsertion(); | 366 ActivateInsertion(); |
| 329 else | 367 else |
| 330 client_->OnSelectionEvent(INSERTION_MOVED, position); | 368 client_->OnSelectionEvent(INSERTION_MOVED); |
| 331 | 369 |
| 332 insertion_handle_->SetVisible(GetStartVisible(), | 370 insertion_handle_->SetVisible(GetStartVisible(), |
| 333 GetAnimationStyle(was_active)); | 371 GetAnimationStyle(was_active)); |
| 334 insertion_handle_->SetPosition(position); | 372 insertion_handle_->SetPosition(position); |
| 335 } | 373 } |
| 336 | 374 |
| 337 void TouchSelectionController::OnSelectionChanged() { | 375 void TouchSelectionController::OnSelectionChanged() { |
| 338 DeactivateInsertion(); | 376 DeactivateInsertion(); |
| 339 | 377 |
| 340 if (!activate_selection_automatically_) | 378 if (!activate_selection_automatically_) |
| 341 return; | 379 return; |
| 342 | 380 |
| 343 const bool was_active = is_selection_active_; | 381 const bool was_active = is_selection_active_; |
| 344 ActivateSelection(); | 382 if (!is_selection_active_ || response_pending_input_event_ == LONG_PRESS) |
| 383 ActivateSelection(); | |
| 384 else | |
| 385 client_->OnSelectionEvent(SELECTION_MOVED); | |
| 345 | 386 |
| 346 const TouchHandle::AnimationStyle animation = GetAnimationStyle(was_active); | 387 const TouchHandle::AnimationStyle animation = GetAnimationStyle(was_active); |
| 347 start_selection_handle_->SetVisible(GetStartVisible(), animation); | 388 start_selection_handle_->SetVisible(GetStartVisible(), animation); |
| 348 end_selection_handle_->SetVisible(GetEndVisible(), animation); | 389 end_selection_handle_->SetVisible(GetEndVisible(), animation); |
| 349 | 390 |
| 350 start_selection_handle_->SetPosition(GetStartPosition()); | 391 start_selection_handle_->SetPosition(GetStartPosition()); |
| 351 end_selection_handle_->SetPosition(GetEndPosition()); | 392 end_selection_handle_->SetPosition(GetEndPosition()); |
| 352 } | 393 } |
| 353 | 394 |
| 354 void TouchSelectionController::ActivateInsertion() { | 395 void TouchSelectionController::ActivateInsertion() { |
| 355 DCHECK(!is_selection_active_); | 396 DCHECK(!is_selection_active_); |
| 356 | 397 |
| 357 if (!insertion_handle_) | 398 if (!insertion_handle_) |
| 358 insertion_handle_.reset( | 399 insertion_handle_.reset( |
| 359 new TouchHandle(this, TouchHandleOrientation::CENTER)); | 400 new TouchHandle(this, TouchHandleOrientation::CENTER)); |
| 360 | 401 |
| 361 if (!is_insertion_active_) { | 402 if (!is_insertion_active_) { |
| 362 is_insertion_active_ = true; | 403 is_insertion_active_ = true; |
| 363 insertion_handle_->SetEnabled(true); | 404 insertion_handle_->SetEnabled(true); |
| 364 client_->OnSelectionEvent(INSERTION_SHOWN, GetStartPosition()); | 405 client_->OnSelectionEvent(INSERTION_SHOWN); |
| 365 } | 406 } |
| 366 } | 407 } |
| 367 | 408 |
| 368 void TouchSelectionController::DeactivateInsertion() { | 409 void TouchSelectionController::DeactivateInsertion() { |
| 369 if (!is_insertion_active_) | 410 if (!is_insertion_active_) |
| 370 return; | 411 return; |
| 371 DCHECK(insertion_handle_); | 412 DCHECK(insertion_handle_); |
| 372 is_insertion_active_ = false; | 413 is_insertion_active_ = false; |
| 373 insertion_handle_->SetEnabled(false); | 414 insertion_handle_->SetEnabled(false); |
| 374 client_->OnSelectionEvent(INSERTION_CLEARED, gfx::PointF()); | 415 client_->OnSelectionEvent(INSERTION_CLEARED); |
| 375 } | 416 } |
| 376 | 417 |
| 377 void TouchSelectionController::ActivateSelection() { | 418 void TouchSelectionController::ActivateSelection() { |
| 378 DCHECK(!is_insertion_active_); | 419 DCHECK(!is_insertion_active_); |
| 379 | 420 |
| 380 if (!start_selection_handle_) { | 421 if (!start_selection_handle_) { |
| 381 start_selection_handle_.reset(new TouchHandle(this, start_orientation_)); | 422 start_selection_handle_.reset(new TouchHandle(this, start_orientation_)); |
| 382 } else { | 423 } else { |
| 383 start_selection_handle_->SetEnabled(true); | 424 start_selection_handle_->SetEnabled(true); |
| 384 start_selection_handle_->SetOrientation(start_orientation_); | 425 start_selection_handle_->SetOrientation(start_orientation_); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 396 // intervening SELECTION_CLEARED update to avoid unnecessary state changes. | 437 // intervening SELECTION_CLEARED update to avoid unnecessary state changes. |
| 397 if (!is_selection_active_ || response_pending_input_event_ == LONG_PRESS) { | 438 if (!is_selection_active_ || response_pending_input_event_ == LONG_PRESS) { |
| 398 if (is_selection_active_) { | 439 if (is_selection_active_) { |
| 399 // The active selection session finishes with the start of the new one. | 440 // The active selection session finishes with the start of the new one. |
| 400 LogSelectionEnd(); | 441 LogSelectionEnd(); |
| 401 } | 442 } |
| 402 is_selection_active_ = true; | 443 is_selection_active_ = true; |
| 403 selection_handle_dragged_ = false; | 444 selection_handle_dragged_ = false; |
| 404 selection_start_time_ = base::TimeTicks::Now(); | 445 selection_start_time_ = base::TimeTicks::Now(); |
| 405 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; | 446 response_pending_input_event_ = INPUT_EVENT_TYPE_NONE; |
| 406 client_->OnSelectionEvent(SELECTION_SHOWN, GetStartPosition()); | 447 client_->OnSelectionEvent(SELECTION_SHOWN); |
| 407 } | 448 } |
| 408 } | 449 } |
| 409 | 450 |
| 410 void TouchSelectionController::DeactivateSelection() { | 451 void TouchSelectionController::DeactivateSelection() { |
| 411 if (!is_selection_active_) | 452 if (!is_selection_active_) |
| 412 return; | 453 return; |
| 413 DCHECK(start_selection_handle_); | 454 DCHECK(start_selection_handle_); |
| 414 DCHECK(end_selection_handle_); | 455 DCHECK(end_selection_handle_); |
| 415 LogSelectionEnd(); | 456 LogSelectionEnd(); |
| 416 start_selection_handle_->SetEnabled(false); | 457 start_selection_handle_->SetEnabled(false); |
| 417 end_selection_handle_->SetEnabled(false); | 458 end_selection_handle_->SetEnabled(false); |
| 418 is_selection_active_ = false; | 459 is_selection_active_ = false; |
| 419 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF()); | 460 client_->OnSelectionEvent(SELECTION_CLEARED); |
| 420 } | 461 } |
| 421 | 462 |
| 422 void TouchSelectionController::ResetCachedValuesIfInactive() { | 463 void TouchSelectionController::ResetCachedValuesIfInactive() { |
| 423 if (is_selection_active_ || is_insertion_active_) | 464 if (is_selection_active_ || is_insertion_active_) |
| 424 return; | 465 return; |
| 425 start_ = SelectionBound(); | 466 start_ = SelectionBound(); |
| 426 end_ = SelectionBound(); | 467 end_ = SelectionBound(); |
| 427 start_orientation_ = TouchHandleOrientation::UNDEFINED; | 468 start_orientation_ = TouchHandleOrientation::UNDEFINED; |
| 428 end_orientation_ = TouchHandleOrientation::UNDEFINED; | 469 end_orientation_ = TouchHandleOrientation::UNDEFINED; |
| 429 } | 470 } |
| 430 | 471 |
| 431 const gfx::PointF& TouchSelectionController::GetStartPosition() const { | |
| 432 return start_.edge_bottom(); | |
| 433 } | |
| 434 | |
| 435 const gfx::PointF& TouchSelectionController::GetEndPosition() const { | |
| 436 return end_.edge_bottom(); | |
| 437 } | |
| 438 | |
| 439 gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const { | 472 gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const { |
| 440 return ComputeLineOffsetFromBottom(start_); | 473 return ComputeLineOffsetFromBottom(start_); |
| 441 } | 474 } |
| 442 | 475 |
| 443 gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const { | 476 gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const { |
| 444 return ComputeLineOffsetFromBottom(end_); | 477 return ComputeLineOffsetFromBottom(end_); |
| 445 } | 478 } |
| 446 | 479 |
| 447 bool TouchSelectionController::GetStartVisible() const { | 480 bool TouchSelectionController::GetStartVisible() const { |
| 448 return start_.visible() && !temporarily_hidden_; | 481 return start_.visible() && !temporarily_hidden_; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 468 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; | 501 base::TimeDelta duration = base::TimeTicks::Now() - selection_start_time_; |
| 469 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", | 502 UMA_HISTOGRAM_CUSTOM_TIMES("Event.TouchSelection.WasDraggedDuration", |
| 470 duration, | 503 duration, |
| 471 base::TimeDelta::FromMilliseconds(500), | 504 base::TimeDelta::FromMilliseconds(500), |
| 472 base::TimeDelta::FromSeconds(60), | 505 base::TimeDelta::FromSeconds(60), |
| 473 60); | 506 60); |
| 474 } | 507 } |
| 475 } | 508 } |
| 476 | 509 |
| 477 } // namespace ui | 510 } // namespace ui |
| OLD | NEW |