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/views/touchui/touch_editing_menu.h"
14 #include "ui/views/view.h"
15 #include "ui/views/views_export.h"
20 class WidgetTestInteractive
;
23 // Touch specific implementation of TouchEditingControllerDeprecated.
24 // Responsible for displaying selection handles and menu elements relevant in a
26 class VIEWS_EXPORT TouchSelectionControllerImpl
27 : public ui::TouchEditingControllerDeprecated
,
28 public TouchEditingMenuController
,
29 public aura::WindowObserver
,
30 public WidgetObserver
,
31 public ui::EventHandler
{
33 class EditingHandleView
;
35 // Use TextSelectionController::create().
36 explicit TouchSelectionControllerImpl(
37 ui::TouchEditable
* client_view
);
39 ~TouchSelectionControllerImpl() override
;
41 // TextSelectionController.
42 void SelectionChanged() override
;
43 bool IsHandleDragInProgress() override
;
44 void HideHandles(bool quick
) override
;
47 friend class TouchSelectionControllerImplTest
;
48 friend class test::WidgetTestInteractive
;
50 void SetDraggingHandle(EditingHandleView
* handle
);
52 // Callback to inform the client view that the selection handle has been
53 // dragged, hence selection may need to be updated. |drag_pos| is the new
54 // position for the edge of the selection corresponding to |dragging_handle_|,
55 // specified in handle's coordinates
56 void SelectionHandleDragged(const gfx::Point
& drag_pos
);
58 // Convenience method to convert a point from a selection handle's coordinate
59 // system to that of the client view.
60 void ConvertPointToClientView(EditingHandleView
* source
, gfx::Point
* point
);
62 // Convenience method to set a handle's selection bound and hide it if it is
63 // located out of client view.
64 void SetHandleBound(EditingHandleView
* handle
,
65 const ui::SelectionBound
& bound
,
66 const ui::SelectionBound
& bound_in_screen
);
68 // Checks if handle should be shown for selection bound.
69 // |bound| should be the clipped version of the selection bound.
70 bool ShouldShowHandleFor(const ui::SelectionBound
& bound
) const;
72 // Overridden from TouchEditingMenuController.
73 bool IsCommandIdEnabled(int command_id
) const override
;
74 void ExecuteCommand(int command_id
, int event_flags
) override
;
75 void OpenContextMenu() override
;
76 void OnMenuClosed(TouchEditingMenuView
* menu
) override
;
78 // Overriden from aura::WindowObserver.
79 void OnAncestorWindowTransformed(aura::Window
* source
,
80 aura::Window
* window
) override
;
82 // Overridden from WidgetObserver. We will observe the widget backing the
83 // |client_view_| so that when its moved/resized, we can update the selection
84 // handles appropriately.
85 void OnWidgetClosing(Widget
* widget
) override
;
86 void OnWidgetBoundsChanged(Widget
* widget
,
87 const gfx::Rect
& new_bounds
) override
;
89 // Overriden from ui::EventHandler.
90 void OnKeyEvent(ui::KeyEvent
* event
) override
;
91 void OnMouseEvent(ui::MouseEvent
* event
) override
;
92 void OnScrollEvent(ui::ScrollEvent
* event
) override
;
94 // Time to show context menu.
95 void ContextMenuTimerFired();
97 void StartContextMenuTimer();
99 // Convenience method to update the position/visibility of the context menu.
100 void UpdateContextMenu();
102 // Convenience method for hiding context menu.
103 void HideContextMenu();
105 // Convenience methods for testing.
106 gfx::NativeView
GetCursorHandleNativeView();
107 gfx::Rect
GetSelectionHandle1Bounds();
108 gfx::Rect
GetSelectionHandle2Bounds();
109 gfx::Rect
GetCursorHandleBounds();
110 bool IsSelectionHandle1Visible();
111 bool IsSelectionHandle2Visible();
112 bool IsCursorHandleVisible();
113 gfx::Rect
GetExpectedHandleBounds(const ui::SelectionBound
& bound
);
114 views::WidgetDelegateView
* GetHandle1View();
115 views::WidgetDelegateView
* GetHandle2View();
117 ui::TouchEditable
* client_view_
;
118 Widget
* client_widget_
;
119 scoped_ptr
<EditingHandleView
> selection_handle_1_
;
120 scoped_ptr
<EditingHandleView
> selection_handle_2_
;
121 scoped_ptr
<EditingHandleView
> cursor_handle_
;
122 TouchEditingMenuView
* context_menu_
;
123 bool command_executed_
;
124 base::TimeTicks selection_start_time_
;
126 // Timer to trigger |context_menu| (|context_menu| is not shown if the
127 // selection handles are being updated. It appears only when the handles are
128 // stationary for a certain amount of time).
129 base::OneShotTimer
<TouchSelectionControllerImpl
> context_menu_timer_
;
131 // Pointer to the SelectionHandleView being dragged during a drag session.
132 EditingHandleView
* dragging_handle_
;
134 // In cursor mode, the two selection bounds are the same and correspond to
135 // |cursor_handle_|; otherwise, they correspond to |selection_handle_1_| and
136 // |selection_handle_2_|, respectively. These values should be used when
137 // selection bounds needed rather than position of handles which might be
138 // invalid when handles are hidden.
139 ui::SelectionBound selection_bound_1_
;
140 ui::SelectionBound selection_bound_2_
;
142 // Selection bounds, clipped to client view's boundaries.
143 ui::SelectionBound selection_bound_1_clipped_
;
144 ui::SelectionBound selection_bound_2_clipped_
;
146 DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImpl
);
151 #endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_