| 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..512a0bf57b1f68ffce624246eb47070fe0a5c3e0 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 |
|
| @@ -82,43 +87,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 +242,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);
|
| @@ -169,11 +265,13 @@ class TouchSelectionControllerImpl::EditingHandleView
|
| 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 +282,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 +338,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 +360,34 @@ 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;
|
| + // Cursor handle should always have the bound type CENTER
|
| + DCHECK(!is_cursor_handle_ || bound.type == ui::SelectionBound::CENTER);
|
| +
|
| + 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 +397,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_;
|
| +
|
| + // 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 +432,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 +468,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 +503,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 +520,30 @@ 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 &&
|
| + screen_bound_anchor.edge_bottom == screen_bound_focus.edge_bottom) {
|
| 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 +578,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 +599,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 +637,7 @@ void TouchSelectionControllerImpl::OpenContextMenu() {
|
|
|
| void TouchSelectionControllerImpl::OnMenuClosed(TouchEditingMenuView* menu) {
|
| if (menu == context_menu_)
|
| - context_menu_ = NULL;
|
| + context_menu_ = nullptr;
|
| }
|
|
|
| void TouchSelectionControllerImpl::OnAncestorWindowTransformed(
|
| @@ -512,7 +648,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 +675,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 +721,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 +729,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 +753,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
|
|
|