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. 4 5 #ifndef UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_ 6 #define UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_ 7 8 #include "base/timer/timer.h" 9 #include "ui/aura/window_observer.h" 10 #include "ui/base/touch/touch_editing_controller.h" 11 #include "ui/gfx/point.h" 12 #include "ui/views/touchui/touch_editing_menu.h" 13 #include "ui/views/view.h" 14 #include "ui/views/views_export.h" 15 16 namespace views { 17 18 namespace test { 19 class WidgetTestInteractive; 20 } 21 22 // Touch specific implementation of TouchSelectionController. Responsible for 23 // displaying selection handles and menu elements relevant in a touch interface. 24 class VIEWS_EXPORT TouchSelectionControllerImpl 25 : public ui::TouchSelectionController, 26 public TouchEditingMenuController, 27 public aura::WindowObserver, 28 public WidgetObserver, 29 public ui::EventHandler { 30 public: 31 class EditingHandleView; 32 33 // Use TextSelectionController::create(). 34 explicit TouchSelectionControllerImpl( 35 ui::TouchEditable* client_view); 36 37 virtual ~TouchSelectionControllerImpl(); 38 39 // TextSelectionController. 40 virtual void SelectionChanged() OVERRIDE; 41 virtual bool IsHandleDragInProgress() OVERRIDE; 42 virtual void HideHandles(bool quick) OVERRIDE; 43 44 private: 45 friend class TouchSelectionControllerImplTest; 46 friend class test::WidgetTestInteractive; 47 48 void SetDraggingHandle(EditingHandleView* handle); 49 50 // Callback to inform the client view that the selection handle has been 51 // dragged, hence selection may need to be updated. 52 void SelectionHandleDragged(const gfx::Point& drag_pos); 53 54 // Convenience method to convert a point from a selection handle's coordinate 55 // system to that of the client view. 56 void ConvertPointToClientView(EditingHandleView* source, gfx::Point* point); 57 58 // Convenience method to set a handle's selection rect and hide it if it is 59 // located out of client view. 60 void SetHandleSelectionRect(EditingHandleView* handle, const gfx::Rect& rect, 61 const gfx::Rect& rect_in_screen); 62 63 // Checks if handle should be shown for a selection end-point at |rect|. 64 // |rect| should be the clipped version of the selection end-point. 65 bool ShouldShowHandleFor(const gfx::Rect& rect) const; 66 67 // Overridden from TouchEditingMenuController. 68 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; 69 virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE; 70 virtual void OpenContextMenu() OVERRIDE; 71 virtual void OnMenuClosed(TouchEditingMenuView* menu) OVERRIDE; 72 73 // Overriden from aura::WindowObserver. 74 virtual void OnAncestorWindowTransformed(aura::Window* source, 75 aura::Window* window) OVERRIDE; 76 77 // Overridden from WidgetObserver. We will observe the widget backing the 78 // |client_view_| so that when its moved/resized, we can update the selection 79 // handles appropriately. 80 virtual void OnWidgetClosing(Widget* widget) OVERRIDE; 81 virtual void OnWidgetBoundsChanged(Widget* widget, 82 const gfx::Rect& new_bounds) OVERRIDE; 83 84 // Overriden from ui::EventHandler. 85 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; 86 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; 87 virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; 88 89 // Time to show context menu. 90 void ContextMenuTimerFired(); 91 92 void StartContextMenuTimer(); 93 94 // Convenience method to update the position/visibility of the context menu. 95 void UpdateContextMenu(); 96 97 // Convenience method for hiding context menu. 98 void HideContextMenu(); 99 100 // Convenience methods for testing. 101 gfx::NativeView GetCursorHandleNativeView(); 102 gfx::Point GetSelectionHandle1Position(); 103 gfx::Point GetSelectionHandle2Position(); 104 gfx::Point GetCursorHandlePosition(); 105 bool IsSelectionHandle1Visible(); 106 bool IsSelectionHandle2Visible(); 107 bool IsCursorHandleVisible(); 108 109 ui::TouchEditable* client_view_; 110 Widget* client_widget_; 111 scoped_ptr<EditingHandleView> selection_handle_1_; 112 scoped_ptr<EditingHandleView> selection_handle_2_; 113 scoped_ptr<EditingHandleView> cursor_handle_; 114 TouchEditingMenuView* context_menu_; 115 116 // Timer to trigger |context_menu| (|context_menu| is not shown if the 117 // selection handles are being updated. It appears only when the handles are 118 // stationary for a certain amount of time). 119 base::OneShotTimer<TouchSelectionControllerImpl> context_menu_timer_; 120 121 // Pointer to the SelectionHandleView being dragged during a drag session. 122 EditingHandleView* dragging_handle_; 123 124 // Selection end points. In cursor mode, the two end points are the same and 125 // correspond to |cursor_handle_|; otherwise, they correspond to 126 // |selection_handle_1_| and |selection_handle_2_|, respectively. These 127 // values should be used when selection end points are needed rather than 128 // position of handles which might be invalid when handles are hidden. 129 gfx::Rect selection_end_point_1_; 130 gfx::Rect selection_end_point_2_; 131 // Selection end points, clipped to client view's boundaries. 132 gfx::Rect selection_end_point_1_clipped_; 133 gfx::Rect selection_end_point_2_clipped_; 134 135 DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImpl); 136 }; 137 138 } // namespace views 139 140 #endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_ 141