1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
6 #define UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
8 #include "base/timer/timer.h"
9 #include "ui/aura/window_observer.h"
10 #include "ui/base/touch/selection_bound.h"
11 #include "ui/base/touch/touch_editing_controller.h"
12 #include "ui/gfx/geometry/point.h"
13 #include "ui/touch_selection/touch_selection_menu_runner.h"
14 #include "ui/views/view.h"
15 #include "ui/views/views_export.h"
16 #include "ui/views/widget/widget_observer.h"
19 class WidgetDelegateView
;
22 class WidgetTestInteractive
;
25 // Touch specific implementation of TouchEditingControllerDeprecated.
26 // Responsible for displaying selection handles and menu elements relevant in a
28 class VIEWS_EXPORT TouchSelectionControllerImpl
29 : public ui::TouchEditingControllerDeprecated
,
30 public ui::TouchSelectionMenuClient
,
31 public aura::WindowObserver
,
32 public WidgetObserver
,
33 public ui::EventHandler
{
35 class EditingHandleView
;
37 // Use TextSelectionController::create().
38 explicit TouchSelectionControllerImpl(
39 ui::TouchEditable
* client_view
);
41 ~TouchSelectionControllerImpl() override
;
43 // TextSelectionController.
44 void SelectionChanged() override
;
45 bool IsHandleDragInProgress() override
;
46 void HideHandles(bool quick
) override
;
49 friend class TouchSelectionControllerImplTest
;
50 friend class test::WidgetTestInteractive
;
52 void SetDraggingHandle(EditingHandleView
* handle
);
54 // Callback to inform the client view that the selection handle has been
55 // dragged, hence selection may need to be updated. |drag_pos| is the new
56 // position for the edge of the selection corresponding to |dragging_handle_|,
57 // specified in handle's coordinates
58 void SelectionHandleDragged(const gfx::Point
& drag_pos
);
60 // Convenience method to convert a point from a selection handle's coordinate
61 // system to that of the client view.
62 void ConvertPointToClientView(EditingHandleView
* source
, gfx::Point
* point
);
64 // Convenience method to set a handle's selection bound and hide it if it is
65 // located out of client view.
66 void SetHandleBound(EditingHandleView
* handle
,
67 const ui::SelectionBound
& bound
,
68 const ui::SelectionBound
& bound_in_screen
);
70 // Checks if handle should be shown for selection bound.
71 // |bound| should be the clipped version of the selection bound.
72 bool ShouldShowHandleFor(const ui::SelectionBound
& bound
) const;
74 // Overridden from ui::TouchSelectionMenuClient.
75 bool IsCommandIdEnabled(int command_id
) const override
;
76 void ExecuteCommand(int command_id
, int event_flags
) override
;
77 void RunContextMenu() override
;
79 // Overriden from aura::WindowObserver.
80 void OnAncestorWindowTransformed(aura::Window
* source
,
81 aura::Window
* window
) override
;
83 // Overridden from WidgetObserver. We will observe the widget backing the
84 // |client_view_| so that when its moved/resized, we can update the selection
85 // handles appropriately.
86 void OnWidgetClosing(Widget
* widget
) override
;
87 void OnWidgetBoundsChanged(Widget
* widget
,
88 const gfx::Rect
& new_bounds
) override
;
90 // Overriden from ui::EventHandler.
91 void OnKeyEvent(ui::KeyEvent
* event
) override
;
92 void OnMouseEvent(ui::MouseEvent
* event
) override
;
93 void OnScrollEvent(ui::ScrollEvent
* event
) override
;
95 // Time to show quick menu.
96 void QuickMenuTimerFired();
98 void StartQuickMenuTimer();
100 // Convenience method to update the position/visibility of the quick menu.
101 void UpdateQuickMenu();
103 // Convenience method for hiding quick menu.
104 void HideQuickMenu();
106 // Convenience method to calculate anchor rect for quick menu, in screen
108 gfx::Rect
GetQuickMenuAnchorRect() const;
110 // Convenience methods for testing.
111 gfx::NativeView
GetCursorHandleNativeView();
112 gfx::Rect
GetSelectionHandle1Bounds();
113 gfx::Rect
GetSelectionHandle2Bounds();
114 gfx::Rect
GetCursorHandleBounds();
115 bool IsSelectionHandle1Visible();
116 bool IsSelectionHandle2Visible();
117 bool IsCursorHandleVisible();
118 gfx::Rect
GetExpectedHandleBounds(const ui::SelectionBound
& bound
);
119 views::WidgetDelegateView
* GetHandle1View();
120 views::WidgetDelegateView
* GetHandle2View();
122 ui::TouchEditable
* client_view_
;
123 Widget
* client_widget_
;
124 scoped_ptr
<EditingHandleView
> selection_handle_1_
;
125 scoped_ptr
<EditingHandleView
> selection_handle_2_
;
126 scoped_ptr
<EditingHandleView
> cursor_handle_
;
127 bool command_executed_
;
128 base::TimeTicks selection_start_time_
;
130 // Timer to trigger quick menu (Quick menu is not shown if the selection
131 // handles are being updated. It appears only when the handles are stationary
132 // for a certain amount of time).
133 base::OneShotTimer
<TouchSelectionControllerImpl
> quick_menu_timer_
;
135 // Pointer to the SelectionHandleView being dragged during a drag session.
136 EditingHandleView
* dragging_handle_
;
138 // In cursor mode, the two selection bounds are the same and correspond to
139 // |cursor_handle_|; otherwise, they correspond to |selection_handle_1_| and
140 // |selection_handle_2_|, respectively. These values should be used when
141 // selection bounds needed rather than position of handles which might be
142 // invalid when handles are hidden.
143 ui::SelectionBound selection_bound_1_
;
144 ui::SelectionBound selection_bound_2_
;
146 // Selection bounds, clipped to client view's boundaries.
147 ui::SelectionBound selection_bound_1_clipped_
;
148 ui::SelectionBound selection_bound_2_clipped_
;
150 DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImpl
);
155 #endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_