Index: ui/views/touchui/touch_selection_controller_impl.cc |
diff --git a/ui/views/touchui/touch_selection_controller_impl.cc b/ui/views/touchui/touch_selection_controller_impl.cc |
index 978592c349683bf24580de4ff16b37a05015a033..416947f1cc11e860f64702a3866c5e768c017f48 100644 |
--- a/ui/views/touchui/touch_selection_controller_impl.cc |
+++ b/ui/views/touchui/touch_selection_controller_impl.cc |
@@ -18,12 +18,16 @@ |
#include "ui/resources/grit/ui_resources.h" |
#include "ui/strings/grit/ui_strings.h" |
#include "ui/views/widget/widget.h" |
+#include "ui/wm/core/coordinate_conversion.h" |
#include "ui/wm/core/masked_window_targeter.h" |
namespace { |
// Constants defining the visual attributes of selection handles |
-const int kSelectionHandleLineWidth = 1; |
+ |
+// Controls the width of the cursor line associated with the selection handle. |
+const int kSelectionHandleLineWidth = 2; |
+ |
const SkColor kSelectionHandleLineColor = |
SkColorSetRGB(0x42, 0x81, 0xf4); |
@@ -37,8 +41,9 @@ const SkColor kSelectionHandleLineColor = |
// next line if the user makes any vertical movement. It is correct but |
// looks/feels weird. So we have this non-zero offset to prevent this jumping. |
// |
-// Editing handle widget showing the difference between the position of the |
-// ET_GESTURE_SCROLL_UPDATE event and the drag position reported to the client: |
+// Editing handle widget showing the padding and difference between the position |
+// of the ET_GESTURE_SCROLL_UPDATE event and the drag position reported to the |
+// client: |
// _____ |
// | |<-|---- Drag position reported to client |
// _ | O | |
@@ -52,10 +57,13 @@ const SkColor kSelectionHandleLineColor = |
const int kSelectionHandleVerticalDragOffset = 5; |
// Padding around the selection handle defining the area that will be included |
-// in the touch target to make dragging the handle easier (see pic above). |
+// in the touch target to make dragging the handle easier (see pic below). |
mohsen
2014/11/10 22:25:59
below -> above
mfomitchev
2014/11/10 23:07:30
Acknowledged.
mfomitchev
2014/11/12 18:32:49
Done.
|
const int kSelectionHandleHorizPadding = 10; |
const int kSelectionHandleVertPadding = 20; |
+ |
+ |
+ |
mohsen
2014/11/10 22:25:59
nit: Style guide suggests minimizing use of vertic
mfomitchev
2014/11/10 23:07:30
Acknowledged.
mfomitchev
2014/11/12 18:32:49
Done.
|
const int kContextMenuTimoutMs = 200; |
const int kSelectionHandleQuickFadeDurationMs = 50; |
@@ -82,43 +90,132 @@ views::Widget* CreateTouchSelectionPopupWidget( |
return widget; |
} |
-gfx::Image* GetHandleImage() { |
- static gfx::Image* handle_image = NULL; |
+gfx::Image* GetCenterHandleImage() { |
+ static gfx::Image* handle_image = nullptr; |
if (!handle_image) { |
handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
- IDR_TEXT_SELECTION_HANDLE); |
+ IDR_TEXT_SELECTION_HANDLE_CENTER); |
} |
return handle_image; |
} |
-gfx::Size GetHandleImageSize() { |
- return GetHandleImage()->Size(); |
+gfx::Image* GetLeftHandleImage() { |
+ static gfx::Image* handle_image = nullptr; |
+ if (!handle_image) { |
+ handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
+ IDR_TEXT_SELECTION_HANDLE_LEFT); |
+ } |
+ return handle_image; |
} |
-// Cannot use gfx::UnionRect since it does not work for empty rects. |
-gfx::Rect Union(const gfx::Rect& r1, const gfx::Rect& r2) { |
- int rx = std::min(r1.x(), r2.x()); |
- int ry = std::min(r1.y(), r2.y()); |
- int rr = std::max(r1.right(), r2.right()); |
- int rb = std::max(r1.bottom(), r2.bottom()); |
- |
- return gfx::Rect(rx, ry, rr - rx, rb - ry); |
+gfx::Image* GetRightHandleImage() { |
+ static gfx::Image* handle_image = nullptr; |
+ if (!handle_image) { |
+ handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
+ IDR_TEXT_SELECTION_HANDLE_RIGHT); |
+ } |
+ return handle_image; |
} |
-// Convenience methods to convert a |rect| from screen to the |client|'s |
+// Return the appropriate handle image based on the bound's type |
+gfx::Image* GetHandleImage(ui::SelectionBound::Type bound_type) { |
+ switch(bound_type) { |
+ case ui::SelectionBound::LEFT: |
+ return GetLeftHandleImage(); |
+ case ui::SelectionBound::CENTER: |
+ return GetCenterHandleImage(); |
+ case ui::SelectionBound::RIGHT: |
+ return GetRightHandleImage(); |
+ default: |
+ NOTREACHED() << "Invalid touch handle bound type."; |
+ return nullptr; |
+ }; |
+} |
+ |
+enum Alignment {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT}; |
+ |
+// Determine the cursor line alignment to the handle image based on the bound |
+// type. Depends on the visual shapes of the handle image assets. |
+Alignment GetCursorAlignment(ui::SelectionBound::Type bound_type) { |
+ switch (bound_type) { |
+ case ui::SelectionBound::LEFT: |
+ return ALIGN_RIGHT; |
+ case ui::SelectionBound::RIGHT: |
+ return ALIGN_LEFT; |
+ case ui::SelectionBound::CENTER: |
+ return ALIGN_CENTER; |
+ default: |
+ NOTREACHED() << "Undefined bound type for cursor alignment."; |
+ return ALIGN_LEFT; |
+ }; |
+} |
+ |
+// Calculates the bounds of the widget containing the selection handle based |
+// on the SelectionBound's type and location |
+gfx::Rect GetSelectionWidgetBounds(const ui::SelectionBound& bound) { |
+ Alignment cursor_alignment = GetCursorAlignment(bound.type); |
+ gfx::Size image_size = GetHandleImage(bound.type)->Size(); |
+ int widget_width = image_size.width() + 2 * kSelectionHandleHorizPadding; |
+ int widget_height = bound.GetHeight() + image_size.height() + |
+ kSelectionHandleVertPadding; |
+ int widget_left = 0; |
+ switch (cursor_alignment) { |
+ case ALIGN_LEFT: |
+ widget_left = bound.edge_top.x() - kSelectionHandleHorizPadding; |
+ break; |
+ case ALIGN_RIGHT: |
+ widget_left = bound.edge_top.x() - image_size.width() - |
+ kSelectionHandleHorizPadding; |
+ break; |
+ case ALIGN_CENTER: |
+ widget_left = bound.edge_top.x() - widget_width / 2; |
+ break; |
+ }; |
+ return gfx::Rect( |
+ widget_left, bound.edge_top.y(), widget_width, widget_height); |
+} |
+ |
+gfx::Size GetMaxHandleImageSize() { |
+ gfx::Rect center_rect = gfx::Rect(GetCenterHandleImage()->Size()); |
+ gfx::Rect left_rect = gfx::Rect(GetLeftHandleImage()->Size()); |
+ gfx::Rect right_rect = gfx::Rect(GetRightHandleImage()->Size()); |
+ gfx::Rect union_rect = center_rect; |
+ union_rect.Union(left_rect); |
+ union_rect.Union(right_rect); |
+ return union_rect.size(); |
+} |
+ |
+// Convenience methods to convert a |bound| from screen to the |client|'s |
// coordinate system and vice versa. |
// Note that this is not quite correct because it does not take into account |
// transforms such as rotation and scaling. This should be in TouchEditable. |
// TODO(varunjain): Fix this. |
-gfx::Rect ConvertFromScreen(ui::TouchEditable* client, const gfx::Rect& rect) { |
- gfx::Point origin = rect.origin(); |
- client->ConvertPointFromScreen(&origin); |
- return gfx::Rect(origin, rect.size()); |
-} |
-gfx::Rect ConvertToScreen(ui::TouchEditable* client, const gfx::Rect& rect) { |
- gfx::Point origin = rect.origin(); |
- client->ConvertPointToScreen(&origin); |
- return gfx::Rect(origin, rect.size()); |
+ui::SelectionBound ConvertFromScreen(ui::TouchEditable* client, |
+ const ui::SelectionBound& bound) { |
+ ui::SelectionBound result = bound; |
+ gfx::Point edge_bottom = bound.edge_bottom; |
+ gfx::Point edge_top = bound.edge_top; |
+ client->ConvertPointFromScreen(&edge_bottom); |
+ client->ConvertPointFromScreen(&edge_top); |
+ result.edge_bottom = edge_bottom; |
+ result.edge_top = edge_top; |
+ return result; |
+} |
+ |
+ui::SelectionBound ConvertToScreen(ui::TouchEditable* client, |
+ const ui::SelectionBound& bound) { |
+ ui::SelectionBound result = bound; |
+ gfx::Point edge_bottom = bound.edge_bottom; |
+ gfx::Point edge_top = bound.edge_top; |
+ client->ConvertPointToScreen(&edge_bottom); |
+ client->ConvertPointToScreen(&edge_top); |
+ result.edge_bottom = edge_bottom; |
+ result.edge_top = edge_top; |
+ return result; |
+} |
+ |
+gfx::Rect BoundToRect(const ui::SelectionBound& bound) { |
+ return gfx::BoundingRect(bound.edge_top, bound.edge_bottom); |
} |
} // namespace |
@@ -148,9 +245,11 @@ class TouchSelectionControllerImpl::EditingHandleView |
: public views::WidgetDelegateView { |
public: |
EditingHandleView(TouchSelectionControllerImpl* controller, |
- gfx::NativeView context) |
+ gfx::NativeView context, |
+ bool is_cursor_handle) |
: controller_(controller), |
- drag_offset_(0), |
+ image_(GetCenterHandleImage()), |
+ is_cursor_handle_(is_cursor_handle), |
draw_invisible_(false) { |
widget_.reset(CreateTouchSelectionPopupWidget(context, this)); |
widget_->SetContentsView(this); |
@@ -165,15 +264,19 @@ class TouchSelectionControllerImpl::EditingHandleView |
~EditingHandleView() override { SetWidgetVisible(false, false); } |
+ const gfx::Image* image() const { return image_; } |
+ |
// Overridden from views::WidgetDelegateView: |
bool WidgetHasHitTestMask() const override { return true; } |
void GetWidgetHitTestMask(gfx::Path* mask) const override { |
- gfx::Size image_size = GetHandleImageSize(); |
- mask->addRect(SkIntToScalar(0), SkIntToScalar(selection_rect_.height()), |
+ gfx::Size image_size = image_->Size(); |
+ mask->addRect( |
+ SkIntToScalar(0), |
+ SkIntToScalar(selection_bound_.GetHeight()), |
SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding, |
- SkIntToScalar(selection_rect_.height() + image_size.height() + |
- kSelectionHandleVertPadding)); |
+ SkIntToScalar(selection_bound_.GetHeight() + image_size.height() + |
+ kSelectionHandleVertPadding)); |
} |
void DeleteDelegate() override { |
@@ -184,40 +287,55 @@ class TouchSelectionControllerImpl::EditingHandleView |
void OnPaint(gfx::Canvas* canvas) override { |
if (draw_invisible_) |
return; |
- gfx::Size image_size = GetHandleImageSize(); |
- int cursor_pos_x = image_size.width() / 2 - kSelectionHandleLineWidth + |
- kSelectionHandleHorizPadding; |
+ Alignment cursor_alignment = GetCursorAlignment(selection_bound_.type); |
+ int cursor_x = 0; |
+ switch (cursor_alignment) { |
+ case ALIGN_RIGHT: |
+ cursor_x = |
+ selection_bound_.edge_top.x() - kSelectionHandleLineWidth + 1; |
+ break; |
+ case ALIGN_LEFT: |
+ cursor_x = selection_bound_.edge_top.x() - 1; |
+ break; |
+ case ALIGN_CENTER: |
+ cursor_x = |
+ selection_bound_.edge_top.x() - kSelectionHandleLineWidth / 2; |
+ break; |
+ }; |
// Draw the cursor line. |
- canvas->FillRect( |
- gfx::Rect(cursor_pos_x, 0, |
- 2 * kSelectionHandleLineWidth + 1, selection_rect_.height()), |
- kSelectionHandleLineColor); |
- |
+ canvas->FillRect(gfx::Rect(cursor_x, |
+ 0, |
+ kSelectionHandleLineWidth, |
+ selection_bound_.GetHeight()), |
+ kSelectionHandleLineColor); |
// Draw the handle image. |
- canvas->DrawImageInt(*GetHandleImage()->ToImageSkia(), |
- kSelectionHandleHorizPadding, selection_rect_.height()); |
+ canvas->DrawImageInt(*image_->ToImageSkia(), |
+ kSelectionHandleHorizPadding, selection_bound_.GetHeight()); |
} |
void OnGestureEvent(ui::GestureEvent* event) override { |
event->SetHandled(); |
switch (event->type()) { |
- case ui::ET_GESTURE_SCROLL_BEGIN: |
+ case ui::ET_GESTURE_SCROLL_BEGIN: { |
widget_->SetCapture(this); |
controller_->SetDraggingHandle(this); |
- drag_offset_ = event->y() - selection_rect_.height() + |
- kSelectionHandleVerticalDragOffset; |
+ // Distance from the point which is |kSelectionHandleVerticalDragOffset| |
+ // pixels above the bottom of the handle's cursor line to the event |
+ // location (aka the touch-drag point). |
+ drag_offset_ = selection_bound_.edge_bottom - |
+ gfx::Vector2d(0, kSelectionHandleVerticalDragOffset) - |
+ event->location(); |
break; |
+ } |
case ui::ET_GESTURE_SCROLL_UPDATE: { |
- gfx::Point drag_pos(event->location().x(), |
- event->location().y() - drag_offset_); |
- controller_->SelectionHandleDragged(drag_pos); |
+ controller_->SelectionHandleDragged(event->location() + drag_offset_); |
break; |
} |
case ui::ET_GESTURE_SCROLL_END: |
case ui::ET_SCROLL_FLING_START: |
widget_->ReleaseCapture(); |
- controller_->SetDraggingHandle(NULL); |
+ controller_->SetDraggingHandle(nullptr); |
break; |
default: |
break; |
@@ -225,9 +343,9 @@ class TouchSelectionControllerImpl::EditingHandleView |
} |
gfx::Size GetPreferredSize() const override { |
- gfx::Size image_size = GetHandleImageSize(); |
+ gfx::Size image_size = image_->Size(); |
return gfx::Size(image_size.width() + 2 * kSelectionHandleHorizPadding, |
- image_size.height() + selection_rect_.height() + |
+ image_size.height() + selection_bound_.GetHeight() + |
kSelectionHandleVertPadding); |
} |
@@ -247,19 +365,31 @@ class TouchSelectionControllerImpl::EditingHandleView |
widget_->Hide(); |
} |
- void SetSelectionRectInScreen(const gfx::Rect& rect) { |
- gfx::Size image_size = GetHandleImageSize(); |
- selection_rect_ = rect; |
- gfx::Rect widget_bounds( |
- rect.x() - image_size.width() / 2 - kSelectionHandleHorizPadding, |
- rect.y(), |
- image_size.width() + 2 * kSelectionHandleHorizPadding, |
- rect.height() + image_size.height() + kSelectionHandleVertPadding); |
- widget_->SetBounds(widget_bounds); |
- } |
+ void SetBoundInScreen(const ui::SelectionBound& bound) { |
+ bool update_bound_type = false; |
+ if (bound.type != selection_bound_.type) { |
+ // Unless this is a cursor handle, do not set the type to CENTER - |
+ // selection handles corresponding to a selection should always use left |
+ // or right handle image. If selection handles are dragged to be located |
+ // at the same spot, the |bound|'s type here will be CENTER for both of |
+ // them. In this case do not update the type of the |selection_bound_|. |
+ if (bound.type != ui::SelectionBound::CENTER || is_cursor_handle_) |
+ update_bound_type = true; |
+ } |
+ if (update_bound_type) { |
+ selection_bound_ = bound; |
+ image_ = GetHandleImage(bound.type); |
+ SchedulePaint(); |
+ } else { |
+ selection_bound_.edge_top = bound.edge_top; |
+ selection_bound_.edge_bottom = bound.edge_bottom; |
+ } |
+ |
+ widget_->SetBounds(GetSelectionWidgetBounds(selection_bound_)); |
- gfx::Point GetScreenPosition() { |
- return widget_->GetClientAreaBoundsInScreen().origin(); |
+ aura::Window* window = widget_->GetNativeView(); |
+ wm::ConvertPointFromScreen(window, &selection_bound_.edge_top); |
+ wm::ConvertPointFromScreen(window, &selection_bound_.edge_bottom); |
} |
void SetDrawInvisible(bool draw_invisible) { |
@@ -269,17 +399,22 @@ class TouchSelectionControllerImpl::EditingHandleView |
SchedulePaint(); |
} |
- const gfx::Rect& selection_rect() const { return selection_rect_; } |
- |
private: |
scoped_ptr<Widget> widget_; |
TouchSelectionControllerImpl* controller_; |
- gfx::Rect selection_rect_; |
- // Vertical offset between the scroll event position and the drag position |
- // reported to the client view (see the ASCII figure at the top of the file |
- // and its description for more details). |
- int drag_offset_; |
+ // In local coordinates |
+ ui::SelectionBound selection_bound_; |
+ gfx::Image* image_; |
+ |
+ // If true, this is a handle corresponding to the single cursor, otherwise it |
+ // is a handle corresponding to one of the two selection bounds. |
+ bool is_cursor_handle_; |
mohsen
2014/11/10 22:25:59
Can we just use current type of handle to prevent
mfomitchev
2014/11/10 23:07:29
I guess we could do this.. We'd still need to pass
mohsen
2014/11/11 01:24:39
What if we allow an EMPTY handle become anything e
mfomitchev
2014/11/12 18:32:49
Added a DCHECK as per our discussion
|
+ |
+ // Offset applied to the scroll events location when calling |
+ // TouchSelectionControllerImpl::SelectionHandleDragged while dragging the |
+ // handle. |
+ gfx::Vector2d drag_offset_; |
// If set to true, the handle will not draw anything, hence providing an empty |
// widget. We need this because we may want to stop showing the handle while |
@@ -299,27 +434,25 @@ TouchHandleWindowTargeter::TouchHandleWindowTargeter( |
bool TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window, |
gfx::Path* mask) const { |
- const gfx::Rect& selection_rect = handle_view_->selection_rect(); |
- gfx::Size image_size = GetHandleImageSize(); |
- mask->addRect(SkIntToScalar(0), SkIntToScalar(selection_rect.height()), |
- SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding, |
- SkIntToScalar(selection_rect.height() + image_size.height() + |
- kSelectionHandleVertPadding)); |
+ handle_view_->GetWidgetHitTestMask(mask); |
return true; |
} |
TouchSelectionControllerImpl::TouchSelectionControllerImpl( |
ui::TouchEditable* client_view) |
: client_view_(client_view), |
- client_widget_(NULL), |
+ client_widget_(nullptr), |
selection_handle_1_(new EditingHandleView(this, |
- client_view->GetNativeView())), |
+ client_view->GetNativeView(), |
+ false)), |
selection_handle_2_(new EditingHandleView(this, |
- client_view->GetNativeView())), |
+ client_view->GetNativeView(), |
+ false)), |
cursor_handle_(new EditingHandleView(this, |
- client_view->GetNativeView())), |
- context_menu_(NULL), |
- dragging_handle_(NULL) { |
+ client_view->GetNativeView(), |
+ true)), |
+ context_menu_(nullptr), |
+ dragging_handle_(nullptr) { |
aura::Window* client_window = client_view_->GetNativeView(); |
client_window->AddObserver(this); |
client_widget_ = Widget::GetTopLevelWidgetForNativeView(client_window); |
@@ -337,30 +470,34 @@ TouchSelectionControllerImpl::~TouchSelectionControllerImpl() { |
} |
void TouchSelectionControllerImpl::SelectionChanged() { |
- gfx::Rect r1, r2; |
- client_view_->GetSelectionEndPoints(&r1, &r2); |
- gfx::Rect screen_rect_1 = ConvertToScreen(client_view_, r1); |
- gfx::Rect screen_rect_2 = ConvertToScreen(client_view_, r2); |
+ ui::SelectionBound anchor, focus; |
+ client_view_->GetSelectionEndPoints(&anchor, &focus); |
+ ui::SelectionBound screen_bound_anchor = |
+ ConvertToScreen(client_view_, anchor); |
+ ui::SelectionBound screen_bound_focus = ConvertToScreen(client_view_, focus); |
gfx::Rect client_bounds = client_view_->GetBounds(); |
- if (r1.y() < client_bounds.y()) |
- r1.Inset(0, client_bounds.y() - r1.y(), 0, 0); |
- if (r2.y() < client_bounds.y()) |
- r2.Inset(0, client_bounds.y() - r2.y(), 0, 0); |
- gfx::Rect screen_rect_1_clipped = ConvertToScreen(client_view_, r1); |
- gfx::Rect screen_rect_2_clipped = ConvertToScreen(client_view_, r2); |
- if (screen_rect_1_clipped == selection_end_point_1_clipped_ && |
- screen_rect_2_clipped == selection_end_point_2_clipped_) |
+ if (anchor.edge_top.y() < client_bounds.y()) |
+ anchor.edge_top.set_y(client_bounds.y()); |
+ if (focus.edge_top.y() < client_bounds.y()) |
+ focus.edge_top.set_y(client_bounds.y()); |
+ ui::SelectionBound screen_bound_anchor_clipped = |
+ ConvertToScreen(client_view_, anchor); |
+ ui::SelectionBound screen_bound_focus_clipped = |
+ ConvertToScreen(client_view_, focus); |
+ if (screen_bound_anchor_clipped == selection_bound_1_clipped_ && |
+ screen_bound_focus_clipped == selection_bound_2_clipped_) |
return; |
- selection_end_point_1_ = screen_rect_1; |
- selection_end_point_2_ = screen_rect_2; |
- selection_end_point_1_clipped_ = screen_rect_1_clipped; |
- selection_end_point_2_clipped_ = screen_rect_2_clipped; |
+ selection_bound_1_ = screen_bound_anchor; |
+ selection_bound_2_ = screen_bound_focus; |
+ selection_bound_1_clipped_ = screen_bound_anchor_clipped; |
+ selection_bound_2_clipped_ = screen_bound_focus_clipped; |
if (client_view_->DrawsHandles()) { |
UpdateContextMenu(); |
return; |
} |
+ |
if (dragging_handle_) { |
// We need to reposition only the selection handle that is being dragged. |
// The other handle stays the same. Also, the selection handle being dragged |
@@ -368,15 +505,15 @@ void TouchSelectionControllerImpl::SelectionChanged() { |
// the start. |
// If the new location of this handle is out of client view, its widget |
// should not get hidden, since it should still receive touch events. |
- // Hence, we are not using |SetHandleSelectionRect()| method here. |
- dragging_handle_->SetSelectionRectInScreen(screen_rect_2_clipped); |
+ // Hence, we are not using |SetHandleBound()| method here. |
+ dragging_handle_->SetBoundInScreen(screen_bound_focus_clipped); |
// Temporary fix for selection handle going outside a window. On a webpage, |
// the page should scroll if the selection handle is dragged outside the |
// window. That does not happen currently. So we just hide the handle for |
// now. |
// TODO(varunjain): Fix this: crbug.com/269003 |
- dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(r2)); |
+ dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(focus)); |
if (dragging_handle_ != cursor_handle_.get()) { |
// The non-dragging-handle might have recently become visible. |
@@ -385,29 +522,29 @@ void TouchSelectionControllerImpl::SelectionChanged() { |
non_dragging_handle = selection_handle_2_.get(); |
// if handle 1 is being dragged, it is corresponding to the end of |
// selection and the other handle to the start of selection. |
- selection_end_point_1_ = screen_rect_2; |
- selection_end_point_2_ = screen_rect_1; |
- selection_end_point_1_clipped_ = screen_rect_2_clipped; |
- selection_end_point_2_clipped_ = screen_rect_1_clipped; |
+ selection_bound_1_ = screen_bound_focus; |
+ selection_bound_2_ = screen_bound_anchor; |
+ selection_bound_1_clipped_ = screen_bound_focus_clipped; |
+ selection_bound_2_clipped_ = screen_bound_anchor_clipped; |
} |
- SetHandleSelectionRect(non_dragging_handle, r1, screen_rect_1_clipped); |
+ SetHandleBound(non_dragging_handle, anchor, screen_bound_anchor_clipped); |
} |
} else { |
UpdateContextMenu(); |
// Check if there is any selection at all. |
- if (screen_rect_1.origin() == screen_rect_2.origin()) { |
+ if (screen_bound_anchor.edge_top == screen_bound_focus.edge_top) { |
selection_handle_1_->SetWidgetVisible(false, false); |
selection_handle_2_->SetWidgetVisible(false, false); |
- SetHandleSelectionRect(cursor_handle_.get(), r1, screen_rect_1_clipped); |
+ SetHandleBound(cursor_handle_.get(), anchor, screen_bound_anchor_clipped); |
return; |
} |
cursor_handle_->SetWidgetVisible(false, false); |
- SetHandleSelectionRect(selection_handle_1_.get(), r1, |
- screen_rect_1_clipped); |
- SetHandleSelectionRect(selection_handle_2_.get(), r2, |
- screen_rect_2_clipped); |
+ SetHandleBound( |
+ selection_handle_1_.get(), anchor, screen_bound_anchor_clipped); |
+ SetHandleBound( |
+ selection_handle_2_.get(), focus, screen_bound_focus_clipped); |
} |
} |
@@ -442,13 +579,13 @@ void TouchSelectionControllerImpl::SelectionHandleDragged( |
} |
// Find the stationary selection handle. |
- gfx::Rect fixed_handle_rect = selection_end_point_1_; |
- if (selection_handle_1_ == dragging_handle_) |
- fixed_handle_rect = selection_end_point_2_; |
+ ui::SelectionBound anchor_bound = |
+ selection_handle_1_ == dragging_handle_ ? selection_bound_2_ |
+ : selection_bound_1_; |
// Find selection end points in client_view's coordinate system. |
- gfx::Point p2 = fixed_handle_rect.origin(); |
- p2.Offset(0, fixed_handle_rect.height() / 2); |
+ gfx::Point p2 = anchor_bound.edge_top; |
+ p2.Offset(0, anchor_bound.GetHeight() / 2); |
client_view_->ConvertPointFromScreen(&p2); |
// Instruct client_view to select the region between p1 and p2. The position |
@@ -463,22 +600,22 @@ void TouchSelectionControllerImpl::ConvertPointToClientView( |
client_view_->ConvertPointFromScreen(point); |
} |
-void TouchSelectionControllerImpl::SetHandleSelectionRect( |
+void TouchSelectionControllerImpl::SetHandleBound( |
EditingHandleView* handle, |
- const gfx::Rect& rect, |
- const gfx::Rect& rect_in_screen) { |
- handle->SetWidgetVisible(ShouldShowHandleFor(rect), false); |
+ const ui::SelectionBound& bound, |
+ const ui::SelectionBound& bound_in_screen) { |
+ handle->SetWidgetVisible(ShouldShowHandleFor(bound), false); |
if (handle->IsWidgetVisible()) |
- handle->SetSelectionRectInScreen(rect_in_screen); |
+ handle->SetBoundInScreen(bound_in_screen); |
} |
bool TouchSelectionControllerImpl::ShouldShowHandleFor( |
- const gfx::Rect& rect) const { |
- if (rect.height() < kSelectionHandleBarMinHeight) |
+ const ui::SelectionBound& bound) const { |
+ if (bound.GetHeight() < kSelectionHandleBarMinHeight) |
return false; |
- gfx::Rect bounds = client_view_->GetBounds(); |
- bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance); |
- return bounds.Contains(rect); |
+ gfx::Rect client_bounds = client_view_->GetBounds(); |
+ client_bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance); |
+ return client_bounds.Contains(BoundToRect(bound)); |
} |
bool TouchSelectionControllerImpl::IsCommandIdEnabled(int command_id) const { |
@@ -501,7 +638,7 @@ void TouchSelectionControllerImpl::OpenContextMenu() { |
void TouchSelectionControllerImpl::OnMenuClosed(TouchEditingMenuView* menu) { |
if (menu == context_menu_) |
- context_menu_ = NULL; |
+ context_menu_ = nullptr; |
} |
void TouchSelectionControllerImpl::OnAncestorWindowTransformed( |
@@ -512,7 +649,7 @@ void TouchSelectionControllerImpl::OnAncestorWindowTransformed( |
void TouchSelectionControllerImpl::OnWidgetClosing(Widget* widget) { |
DCHECK_EQ(client_widget_, widget); |
- client_widget_ = NULL; |
+ client_widget_ = nullptr; |
} |
void TouchSelectionControllerImpl::OnWidgetBoundsChanged( |
@@ -539,37 +676,30 @@ void TouchSelectionControllerImpl::OnScrollEvent(ui::ScrollEvent* event) { |
void TouchSelectionControllerImpl::ContextMenuTimerFired() { |
// Get selection end points in client_view's space. |
- gfx::Rect end_rect_1_in_screen; |
- gfx::Rect end_rect_2_in_screen; |
- if (cursor_handle_->IsWidgetVisible()) { |
- end_rect_1_in_screen = selection_end_point_1_clipped_; |
- end_rect_2_in_screen = end_rect_1_in_screen; |
- } else { |
- end_rect_1_in_screen = selection_end_point_1_clipped_; |
- end_rect_2_in_screen = selection_end_point_2_clipped_; |
- } |
- |
+ ui::SelectionBound b1_in_screen = selection_bound_1_clipped_; |
+ ui::SelectionBound b2_in_screen = |
+ cursor_handle_->IsWidgetVisible() ? b1_in_screen |
+ : selection_bound_2_clipped_; |
// Convert from screen to client. |
- gfx::Rect end_rect_1(ConvertFromScreen(client_view_, end_rect_1_in_screen)); |
- gfx::Rect end_rect_2(ConvertFromScreen(client_view_, end_rect_2_in_screen)); |
+ ui::SelectionBound b1 = ConvertFromScreen(client_view_, b1_in_screen); |
+ ui::SelectionBound b2 = ConvertFromScreen(client_view_, b2_in_screen); |
// if selection is completely inside the view, we display the context menu |
// in the middle of the end points on the top. Else, we show it above the |
// visible handle. If no handle is visible, we do not show the menu. |
gfx::Rect menu_anchor; |
- if (ShouldShowHandleFor(end_rect_1) && |
- ShouldShowHandleFor(end_rect_2)) |
- menu_anchor = Union(end_rect_1_in_screen,end_rect_2_in_screen); |
- else if (ShouldShowHandleFor(end_rect_1)) |
- menu_anchor = end_rect_1_in_screen; |
- else if (ShouldShowHandleFor(end_rect_2)) |
- menu_anchor = end_rect_2_in_screen; |
+ if (ShouldShowHandleFor(b1) && ShouldShowHandleFor(b2)) |
+ menu_anchor = ui::RectBetweenSelectionBounds(b1_in_screen, b2_in_screen); |
+ else if (ShouldShowHandleFor(b1)) |
+ menu_anchor = BoundToRect(b1_in_screen); |
+ else if (ShouldShowHandleFor(b2)) |
+ menu_anchor = BoundToRect(b2_in_screen); |
else |
return; |
DCHECK(!context_menu_); |
context_menu_ = TouchEditingMenuView::Create(this, menu_anchor, |
- GetHandleImageSize(), |
+ GetMaxHandleImageSize(), |
client_view_->GetNativeView()); |
} |
@@ -592,7 +722,7 @@ void TouchSelectionControllerImpl::UpdateContextMenu() { |
void TouchSelectionControllerImpl::HideContextMenu() { |
if (context_menu_) |
context_menu_->Close(); |
- context_menu_ = NULL; |
+ context_menu_ = nullptr; |
context_menu_timer_.Stop(); |
} |
@@ -600,16 +730,16 @@ gfx::NativeView TouchSelectionControllerImpl::GetCursorHandleNativeView() { |
return cursor_handle_->GetWidget()->GetNativeView(); |
} |
-gfx::Point TouchSelectionControllerImpl::GetSelectionHandle1Position() { |
- return selection_handle_1_->GetScreenPosition(); |
+gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle1Bounds() { |
+ return selection_handle_1_->GetBoundsInScreen(); |
} |
-gfx::Point TouchSelectionControllerImpl::GetSelectionHandle2Position() { |
- return selection_handle_2_->GetScreenPosition(); |
+gfx::Rect TouchSelectionControllerImpl::GetSelectionHandle2Bounds() { |
+ return selection_handle_2_->GetBoundsInScreen(); |
} |
-gfx::Point TouchSelectionControllerImpl::GetCursorHandlePosition() { |
- return cursor_handle_->GetScreenPosition(); |
+gfx::Rect TouchSelectionControllerImpl::GetCursorHandleBounds() { |
+ return cursor_handle_->GetBoundsInScreen(); |
} |
bool TouchSelectionControllerImpl::IsSelectionHandle1Visible() { |
@@ -624,4 +754,17 @@ bool TouchSelectionControllerImpl::IsCursorHandleVisible() { |
return cursor_handle_->IsWidgetVisible(); |
} |
+gfx::Rect TouchSelectionControllerImpl::GetExpectedHandleBounds( |
+ const ui::SelectionBound& bound) { |
+ return GetSelectionWidgetBounds(bound); |
+} |
+ |
+views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() { |
+ return selection_handle_1_.get(); |
+} |
+ |
+views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() { |
+ return selection_handle_2_.get(); |
+} |
+ |
} // namespace views |