Chromium Code Reviews| Index: ui/touch_selection/touch_handle.cc |
| diff --git a/ui/touch_selection/touch_handle.cc b/ui/touch_selection/touch_handle.cc |
| index cea93885f51582696204a4f49a0071f65fbe4bdb..ba4482a17041ec8f792d2f7f9ff6e9977b3205bc 100644 |
| --- a/ui/touch_selection/touch_handle.cc |
| +++ b/ui/touch_selection/touch_handle.cc |
| @@ -63,9 +63,11 @@ static std::ostream& operator<<(std::ostream& os, |
| // Responsible for rendering a selection or insertion handle for text editing. |
| TouchHandle::TouchHandle(TouchHandleClient* client, |
| - TouchHandleOrientation orientation) |
| + TouchHandleOrientation orientation, |
| + const gfx::RectF viewport_rect) |
| : drawable_(client->CreateDrawable()), |
| client_(client), |
| + viewport_rect_(viewport_rect), |
| orientation_(orientation), |
| deferred_orientation_(TouchHandleOrientation::UNDEFINED), |
| alpha_(0.f), |
| @@ -73,12 +75,13 @@ TouchHandle::TouchHandle(TouchHandleClient* client, |
| enabled_(true), |
| is_visible_(false), |
| is_dragging_(false), |
| - is_drag_within_tap_region_(false) { |
| + is_drag_within_tap_region_(false), |
| + mirror_vertical_(false), |
| + mirror_horizontal_(false) { |
| DCHECK_NE(orientation, TouchHandleOrientation::UNDEFINED); |
| drawable_->SetEnabled(enabled_); |
| - drawable_->SetOrientation(orientation_); |
| + drawable_->SetLayout(focus_bottom_, orientation_, false, false, false); |
| drawable_->SetAlpha(alpha_); |
| - drawable_->SetFocus(position_); |
| } |
| TouchHandle::~TouchHandle() { |
| @@ -103,8 +106,7 @@ void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) { |
| is_visible_ = visible; |
| // Handle repositioning may have been deferred while previously invisible. |
| - if (visible) |
| - drawable_->SetFocus(position_); |
| + UpdateLayout(); |
| bool animate = animation_style != ANIMATION_NONE; |
| if (is_dragging_) { |
| @@ -118,16 +120,21 @@ void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) { |
| EndFade(); |
| } |
| -void TouchHandle::SetPosition(const gfx::PointF& position) { |
| - DCHECK(enabled_); |
| - if (position_ == position) |
| +void TouchHandle::SetFocus(const gfx::PointF& top, const gfx::PointF& bottom) { |
| + if (focus_top_ == top && focus_bottom_ == bottom) |
| return; |
| - position_ = position; |
| - // Suppress repositioning a handle while invisible or fading out to prevent it |
| - // from "ghosting" outside the visible bounds. The position will be pushed to |
| - // the drawable when the handle regains visibility (see |SetVisible()|). |
| - if (is_visible_) |
| - drawable_->SetFocus(position_); |
| + |
| + focus_top_ = top; |
| + focus_bottom_ = bottom; |
| + UpdateLayout(); |
| +} |
| + |
| +void TouchHandle::SetViewportRect(const gfx::RectF viewport_rect) { |
| + if ((viewport_rect_ == viewport_rect)) |
|
jdduke (slow)
2015/06/08 15:24:46
Nit: No need for double parentheses.
AviD
2015/06/16 14:09:14
Done.
|
| + return; |
| + |
| + viewport_rect_ = viewport_rect; |
| + UpdateLayout(); |
| } |
| void TouchHandle::SetOrientation(TouchHandleOrientation orientation) { |
| @@ -142,7 +149,7 @@ void TouchHandle::SetOrientation(TouchHandleOrientation orientation) { |
| return; |
| orientation_ = orientation; |
| - drawable_->SetOrientation(orientation); |
| + UpdateLayout(); |
| } |
| bool TouchHandle::WillHandleTouchEvent(const MotionEvent& event) { |
| @@ -167,7 +174,7 @@ bool TouchHandle::WillHandleTouchEvent(const MotionEvent& event) { |
| return false; |
| } |
| touch_down_position_ = touch_point; |
| - touch_to_focus_offset_ = position_ - touch_down_position_; |
| + touch_to_focus_offset_ = focus_bottom_ - touch_down_position_; |
| touch_down_time_ = event.GetEventTime(); |
| BeginDrag(); |
| } break; |
| @@ -215,8 +222,8 @@ bool TouchHandle::Animate(base::TimeTicks frame_time) { |
| float time_u = |
| 1.f - (fade_end_time_ - frame_time).InMillisecondsF() / kFadeDurationMs; |
| - float position_u = |
| - (position_ - fade_start_position_).LengthSquared() / kFadeDistanceSquared; |
| + float position_u = (focus_bottom_ - fade_start_position_).LengthSquared() / |
| + kFadeDistanceSquared; |
| float u = std::max(time_u, position_u); |
| SetAlpha(is_visible_ ? u : 1.f - u); |
| @@ -235,6 +242,55 @@ gfx::RectF TouchHandle::GetVisibleBounds() const { |
| return drawable_->GetVisibleBounds(); |
| } |
| +void TouchHandle::UpdateLayout() { |
| + // Suppress repositioning a handle while invisible or fading out to prevent it |
| + // from "ghosting" outside the visible bounds. The position will be pushed to |
| + // the drawable when the handle regains visibility (see |SetVisible()|). |
| + if (!is_visible_) |
| + return; |
| + |
| + // Update mirror values only when dragging has stopped to prevent unwanted |
| + // inversion while dragging of handles |
| + bool mirror_changed = false; |
| + |
| + if (!is_dragging_) { |
| + gfx::RectF handle_bounds = drawable_->GetVisibleBounds(); |
| + bool mirror_horizontal = false; |
| + bool mirror_vertical = false; |
| + |
| + const float bottom_y_unmirrored = |
| + focus_bottom_.y() + handle_bounds.height() + viewport_rect_.y(); |
| + const float top_y_mirrored = |
| + focus_top_.y() - handle_bounds.height() + viewport_rect_.y(); |
| + |
| + // In case the viewport height is small, like webview, avoid inversion. |
| + if (bottom_y_unmirrored > viewport_rect_.bottom() && |
| + top_y_mirrored > viewport_rect_.y()) { |
| + mirror_vertical = true; |
|
mfomitchev
2015/06/08 18:06:09
Don't we also have vertical padding to account for
AviD
2015/06/16 14:09:14
Added a common API to get both vertical and horizo
|
| + } |
| + |
| + if (orientation_ == TouchHandleOrientation::LEFT && |
| + focus_bottom_.x() - (handle_bounds.width() * 0.75f) < |
|
mfomitchev
2015/06/08 18:06:09
This code will be used by Aura (desktop Chrome UI)
AviD
2015/06/16 14:09:14
I have added GetDrawablePadding() returning gfx::S
|
| + viewport_rect_.x()) { |
| + mirror_horizontal = true; |
| + } else if (orientation_ == TouchHandleOrientation::RIGHT && |
| + focus_bottom_.x() + (handle_bounds.width() * 0.75f) > |
| + viewport_rect_.right()) { |
| + mirror_horizontal = true; |
| + } |
| + |
| + mirror_changed = mirror_horizontal != mirror_horizontal_ || |
| + mirror_vertical != mirror_vertical_; |
| + mirror_horizontal_ = mirror_horizontal; |
| + mirror_vertical_ = mirror_vertical; |
| + } |
| + |
| + gfx::PointF position = mirror_vertical_ ? focus_top_ : focus_bottom_; |
| + |
| + drawable_->SetLayout(position, orientation_, mirror_vertical_, |
| + mirror_horizontal_, mirror_changed); |
| +} |
| + |
| void TouchHandle::BeginDrag() { |
| DCHECK(enabled_); |
| if (is_dragging_) |
| @@ -258,6 +314,8 @@ void TouchHandle::EndDrag() { |
| TouchHandleOrientation deferred_orientation = deferred_orientation_; |
| deferred_orientation_ = TouchHandleOrientation::UNDEFINED; |
| SetOrientation(deferred_orientation); |
| + // Handle layout may is deferred while the handle is dragged. |
| + UpdateLayout(); |
| } |
| if (animate_deferred_fade_) { |
| @@ -282,7 +340,7 @@ void TouchHandle::BeginFade() { |
| fade_end_time_ = base::TimeTicks::Now() + |
| base::TimeDelta::FromMillisecondsD( |
| kFadeDurationMs * std::abs(target_alpha - alpha_)); |
| - fade_start_position_ = position_; |
| + fade_start_position_ = focus_bottom_; |
| client_->SetNeedsAnimate(); |
| } |