summaryrefslogtreecommitdiffstats
path: root/ui/views/touchui/touch_selection_controller_impl.h
blob: deafbd67619618bbf44ea1b91e9eeb13e451dcb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
#define UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_

#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/base/touch/selection_bound.h"
#include "ui/base/touch/touch_editing_controller.h"
#include "ui/gfx/geometry/point.h"
#include "ui/touch_selection/touch_selection_menu_runner.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/widget_observer.h"

namespace views {
class WidgetDelegateView;

namespace test {
class WidgetTestInteractive;
}

// Touch specific implementation of TouchEditingControllerDeprecated.
// Responsible for displaying selection handles and menu elements relevant in a
// touch interface.
class VIEWS_EXPORT TouchSelectionControllerImpl
    : public ui::TouchEditingControllerDeprecated,
      public ui::TouchSelectionMenuClient,
      public aura::WindowObserver,
      public WidgetObserver,
      public ui::EventHandler {
 public:
  class EditingHandleView;

  // Use TextSelectionController::create().
  explicit TouchSelectionControllerImpl(
      ui::TouchEditable* client_view);

  ~TouchSelectionControllerImpl() override;

  // TextSelectionController.
  void SelectionChanged() override;
  bool IsHandleDragInProgress() override;
  void HideHandles(bool quick) override;

 private:
  friend class TouchSelectionControllerImplTest;
  friend class test::WidgetTestInteractive;

  void SetDraggingHandle(EditingHandleView* handle);

  // Callback to inform the client view that the selection handle has been
  // dragged, hence selection may need to be updated. |drag_pos| is the new
  // position for the edge of the selection corresponding to |dragging_handle_|,
  // specified in handle's coordinates
  void SelectionHandleDragged(const gfx::Point& drag_pos);

  // Convenience method to convert a point from a selection handle's coordinate
  // system to that of the client view.
  void ConvertPointToClientView(EditingHandleView* source, gfx::Point* point);

  // Convenience method to set a handle's selection bound and hide it if it is
  // located out of client view.
  void SetHandleBound(EditingHandleView* handle,
                      const ui::SelectionBound& bound,
                      const ui::SelectionBound& bound_in_screen);

  // Checks if handle should be shown for selection bound.
  // |bound| should be the clipped version of the selection bound.
  bool ShouldShowHandleFor(const ui::SelectionBound& bound) const;

  // Overridden from ui::TouchSelectionMenuClient.
  bool IsCommandIdEnabled(int command_id) const override;
  void ExecuteCommand(int command_id, int event_flags) override;
  void RunContextMenu() override;

  // Overriden from aura::WindowObserver.
  void OnAncestorWindowTransformed(aura::Window* source,
                                   aura::Window* window) override;

  // Overridden from WidgetObserver. We will observe the widget backing the
  // |client_view_| so that when its moved/resized, we can update the selection
  // handles appropriately.
  void OnWidgetClosing(Widget* widget) override;
  void OnWidgetBoundsChanged(Widget* widget,
                             const gfx::Rect& new_bounds) override;

  // Overriden from ui::EventHandler.
  void OnKeyEvent(ui::KeyEvent* event) override;
  void OnMouseEvent(ui::MouseEvent* event) override;
  void OnScrollEvent(ui::ScrollEvent* event) override;

  // Time to show quick menu.
  void QuickMenuTimerFired();

  void StartQuickMenuTimer();

  // Convenience method to update the position/visibility of the quick menu.
  void UpdateQuickMenu();

  // Convenience method for hiding quick menu.
  void HideQuickMenu();

  // Convenience method to calculate anchor rect for quick menu, in screen
  // coordinates.
  gfx::Rect GetQuickMenuAnchorRect() const;

  // Convenience methods for testing.
  gfx::NativeView GetCursorHandleNativeView();
  gfx::Rect GetSelectionHandle1Bounds();
  gfx::Rect GetSelectionHandle2Bounds();
  gfx::Rect GetCursorHandleBounds();
  bool IsSelectionHandle1Visible();
  bool IsSelectionHandle2Visible();
  bool IsCursorHandleVisible();
  gfx::Rect GetExpectedHandleBounds(const ui::SelectionBound& bound);
  views::WidgetDelegateView* GetHandle1View();
  views::WidgetDelegateView* GetHandle2View();

  ui::TouchEditable* client_view_;
  Widget* client_widget_;
  scoped_ptr<EditingHandleView> selection_handle_1_;
  scoped_ptr<EditingHandleView> selection_handle_2_;
  scoped_ptr<EditingHandleView> cursor_handle_;
  bool command_executed_;
  base::TimeTicks selection_start_time_;

  // Timer to trigger quick menu (Quick menu is not shown if the selection
  // handles are being updated. It appears only when the handles are stationary
  // for a certain amount of time).
  base::OneShotTimer<TouchSelectionControllerImpl> quick_menu_timer_;

  // Pointer to the SelectionHandleView being dragged during a drag session.
  EditingHandleView* dragging_handle_;

  // In cursor mode, the two selection bounds are the same and correspond to
  // |cursor_handle_|; otherwise, they correspond to |selection_handle_1_| and
  // |selection_handle_2_|, respectively. These values should be used when
  // selection bounds needed rather than position of handles which might be
  // invalid when handles are hidden.
  ui::SelectionBound selection_bound_1_;
  ui::SelectionBound selection_bound_2_;

  // Selection bounds, clipped to client view's boundaries.
  ui::SelectionBound selection_bound_1_clipped_;
  ui::SelectionBound selection_bound_2_clipped_;

  DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImpl);
};

}  // namespace views

#endif  // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_