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