OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 #include "content/browser/renderer_host/input/touch_selection_controller.h" | |
6 | |
7 #include "base/logging.h" | |
8 | |
9 namespace content { | |
10 | |
11 TouchSelectionController::TouchSelectionController( | |
12 TouchSelectionControllerClient* client) | |
13 : client_(client), | |
14 anchor_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | |
15 anchor_visible_(false), | |
16 focus_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED), | |
17 focus_visible_(false), | |
18 is_insertion_active_(false), | |
19 allow_automatic_insertion_activation_(false), | |
20 is_selection_active_(false), | |
21 allow_automatic_selection_activation_(false), | |
22 selection_editable_(false), | |
23 selection_editable_for_last_update_(false) { | |
24 DCHECK(client_); | |
25 HideAndDisallowAutomaticShowing(); | |
26 } | |
27 | |
28 TouchSelectionController::~TouchSelectionController() { | |
29 } | |
30 | |
31 void TouchSelectionController::OnSelectionBoundsChanged( | |
32 const gfx::RectF& anchor_rect, | |
33 TouchHandleOrientation anchor_orientation, | |
34 bool anchor_visible, | |
35 const gfx::RectF& focus_rect, | |
36 TouchHandleOrientation focus_orientation, | |
37 bool focus_visible) { | |
38 if (!allow_automatic_selection_activation_ && | |
39 !allow_automatic_insertion_activation_) | |
40 return; | |
41 | |
42 if (anchor_rect_ == anchor_rect && focus_rect_ == focus_rect && | |
43 anchor_orientation_ == anchor_orientation && | |
44 focus_orientation_ == focus_orientation && | |
45 anchor_visible_ == anchor_visible && focus_visible_ == focus_visible && | |
46 selection_editable_ == selection_editable_for_last_update_) | |
47 return; | |
48 | |
49 anchor_rect_ = anchor_rect; | |
50 anchor_orientation_ = anchor_orientation; | |
51 anchor_visible_ = anchor_visible; | |
52 focus_rect_ = focus_rect; | |
53 focus_orientation_ = focus_orientation; | |
54 focus_visible_ = focus_visible; | |
55 selection_editable_for_last_update_ = selection_editable_; | |
56 | |
57 const gfx::PointF anchor = GetAnchorPosition(); | |
58 const gfx::PointF focus = GetFocusPosition(); | |
59 if (anchor.x() != focus.x() || anchor.y() != focus.y() || | |
cjhopman
2014/07/07 22:13:41
anchor != focus
jdduke (slow)
2014/07/08 00:54:44
Done.
| |
60 (start_selection_handle_ && start_selection_handle_->is_dragging()) || | |
cjhopman
2014/07/07 22:13:41
Can this just use is_selection_active_ rather than
jdduke (slow)
2014/07/08 00:54:44
Done.
| |
61 (end_selection_handle_ && end_selection_handle_->is_dragging())) { | |
62 // It's possible that the bounds temporarily overlap while a handle is | |
63 // being dragged, incorrectly reporting a CENTER orientation. | |
64 if (anchor_orientation_ == TOUCH_HANDLE_CENTER && start_selection_handle_) | |
cjhopman
2014/07/07 22:13:41
AIUI, if anchor_orientation_ == TOUCH_HANDLE_CENTE
jdduke (slow)
2014/07/08 00:54:44
It's definitely better, good call.
| |
65 anchor_orientation_ = start_selection_handle_->orientation(); | |
66 if (focus_orientation_ == TOUCH_HANDLE_CENTER && end_selection_handle_) | |
67 focus_orientation_ = end_selection_handle_->orientation(); | |
68 | |
69 OnSelectionChanged(); | |
70 return; | |
71 } | |
72 | |
73 if (anchor_orientation_ == TOUCH_HANDLE_CENTER) { | |
74 OnInsertionChanged(); | |
75 return; | |
76 } | |
77 | |
78 HideAndDisallowAutomaticShowing(); | |
79 } | |
80 | |
81 bool TouchSelectionController::WillHandleTouchEvent( | |
82 const ui::MotionEvent& event) { | |
83 if (is_insertion_active_) { | |
84 DCHECK(insertion_handle_); | |
85 return insertion_handle_->WillHandleTouchEvent(event); | |
86 } | |
87 | |
88 if (is_selection_active_) { | |
89 DCHECK(start_selection_handle_); | |
90 DCHECK(end_selection_handle_); | |
91 return start_selection_handle_->WillHandleTouchEvent(event) || | |
92 end_selection_handle_->WillHandleTouchEvent(event); | |
93 } | |
94 | |
95 return false; | |
96 } | |
97 | |
98 void TouchSelectionController::AllowAutomaticInsertionShowing() { | |
99 if (allow_automatic_insertion_activation_) | |
100 return; | |
101 allow_automatic_insertion_activation_ = true; | |
102 if (!is_insertion_active_ && !is_selection_active_) | |
103 ResetCachedValues(); | |
104 } | |
105 | |
106 void TouchSelectionController::AllowAutomaticSelectionShowing() { | |
107 if (allow_automatic_selection_activation_) | |
108 return; | |
109 allow_automatic_selection_activation_ = true; | |
110 if (!is_insertion_active_ && !is_selection_active_) | |
111 ResetCachedValues(); | |
112 } | |
113 | |
114 void TouchSelectionController::HideAndDisallowAutomaticShowing() { | |
115 DeactivateInsertion(); | |
116 DeactivateSelection(); | |
117 allow_automatic_insertion_activation_ = false; | |
118 allow_automatic_selection_activation_ = false; | |
119 } | |
120 | |
121 void TouchSelectionController::OnSelectionEditable(bool editable) { | |
122 if (selection_editable_ == editable) | |
123 return; | |
124 selection_editable_ = editable; | |
125 if (!selection_editable_) | |
126 DeactivateInsertion(); | |
127 } | |
128 | |
129 bool TouchSelectionController::Animate(base::TimeTicks frame_time) { | |
130 if (is_insertion_active_) | |
131 return insertion_handle_->Animate(frame_time); | |
132 | |
133 if (is_selection_active_) { | |
134 bool needs_animate = start_selection_handle_->Animate(frame_time); | |
135 needs_animate |= end_selection_handle_->Animate(frame_time); | |
136 return needs_animate; | |
137 } | |
138 | |
139 return false; | |
140 } | |
141 | |
142 void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) { | |
143 if (&handle == insertion_handle_.get()) | |
144 return; | |
145 | |
146 if (&handle == start_selection_handle_.get()) { | |
147 fixed_handle_position_ = end_selection_handle_->position() - | |
148 gfx::Vector2dF(0, GetFocusLineHeight() / 2.f); | |
149 } else { | |
150 fixed_handle_position_ = start_selection_handle_->position() - | |
151 gfx::Vector2dF(0, GetAnchorLineHeight() / 2.f); | |
152 } | |
153 } | |
154 | |
155 void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle, | |
156 const gfx::PointF& position) { | |
157 // As the position corresponds to the bottom left point of the selection | |
158 // bound, offset it by half the corresponding line height. | |
159 float half_line_height = &handle == end_selection_handle_.get() | |
160 ? GetFocusLineHeight() / 2.f | |
161 : GetAnchorLineHeight() / 2.f; | |
162 gfx::PointF line_position = position - gfx::Vector2dF(0, half_line_height); | |
163 if (&handle == insertion_handle_.get()) { | |
164 client_->MoveCaret(line_position); | |
165 } else { | |
166 client_->SelectBetweenCoordinates(fixed_handle_position_, line_position); | |
167 } | |
168 } | |
169 | |
170 void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) { | |
171 } | |
172 | |
173 void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) { | |
174 if (insertion_handle_ && &handle == insertion_handle_.get()) | |
175 client_->OnSelectionEvent(INSERTION_TAPPED, GetAnchorPosition()); | |
176 } | |
177 | |
178 void TouchSelectionController::SetNeedsAnimate() { | |
179 client_->SetNeedsAnimate(); | |
180 } | |
181 | |
182 scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() { | |
183 return client_->CreateDrawable(); | |
184 } | |
185 | |
186 void TouchSelectionController::OnInsertionChanged() { | |
187 DeactivateSelection(); | |
188 | |
189 if (!allow_automatic_insertion_activation_ || !selection_editable_) | |
190 return; | |
191 | |
192 bool was_active = is_insertion_active_; | |
193 gfx::PointF position = GetAnchorPosition(); | |
194 if (!was_active) | |
195 ActivateInsertion(); | |
196 else | |
197 client_->OnSelectionEvent(INSERTION_MOVED, position); | |
198 | |
199 if (was_active) | |
200 insertion_handle_->SetVisibleAnimated(anchor_visible_); | |
201 else | |
202 insertion_handle_->SetVisible(anchor_visible_); | |
203 | |
204 insertion_handle_->SetPosition(position); | |
205 } | |
206 | |
207 void TouchSelectionController::OnSelectionChanged() { | |
208 DeactivateInsertion(); | |
209 | |
210 if (!allow_automatic_selection_activation_) | |
211 return; | |
212 | |
213 const bool was_active = is_selection_active_; | |
214 ActivateSelection(); | |
215 if (was_active) { | |
216 start_selection_handle_->SetVisibleAnimated(anchor_visible_); | |
217 end_selection_handle_->SetVisibleAnimated(focus_visible_); | |
218 } else { | |
219 start_selection_handle_->SetVisible(anchor_visible_); | |
220 end_selection_handle_->SetVisible(focus_visible_); | |
221 } | |
222 start_selection_handle_->SetPosition(GetAnchorPosition()); | |
223 end_selection_handle_->SetPosition(GetFocusPosition()); | |
224 } | |
225 | |
226 void TouchSelectionController::ActivateInsertion() { | |
227 DCHECK(!is_selection_active_); | |
228 | |
229 if (!insertion_handle_) | |
230 insertion_handle_.reset(new TouchHandle(this, TOUCH_HANDLE_CENTER)); | |
231 | |
232 if (!is_insertion_active_) { | |
233 is_insertion_active_ = true; | |
234 client_->OnSelectionEvent(INSERTION_SHOWN, GetAnchorPosition()); | |
235 } | |
236 } | |
237 | |
238 void TouchSelectionController::DeactivateInsertion() { | |
239 if (!is_insertion_active_) | |
240 return; | |
241 DCHECK(insertion_handle_); | |
242 insertion_handle_->Hide(); | |
243 is_insertion_active_ = false; | |
244 client_->OnSelectionEvent(INSERTION_CLEARED, gfx::PointF()); | |
245 } | |
246 | |
247 void TouchSelectionController::ActivateSelection() { | |
248 DCHECK(!is_insertion_active_); | |
249 | |
250 if (!start_selection_handle_) | |
251 start_selection_handle_.reset(new TouchHandle(this, anchor_orientation_)); | |
252 else | |
253 start_selection_handle_->SetOrientation(anchor_orientation_); | |
254 | |
255 if (!end_selection_handle_) | |
256 end_selection_handle_.reset(new TouchHandle(this, focus_orientation_)); | |
257 else | |
258 end_selection_handle_->SetOrientation(focus_orientation_); | |
259 | |
260 if (!is_selection_active_) { | |
261 is_selection_active_ = true; | |
262 client_->OnSelectionEvent(SELECTION_SHOWN, GetAnchorPosition()); | |
263 } | |
264 } | |
265 | |
266 void TouchSelectionController::DeactivateSelection() { | |
267 if (!is_selection_active_) | |
268 return; | |
269 DCHECK(start_selection_handle_); | |
270 DCHECK(end_selection_handle_); | |
271 start_selection_handle_->Hide(); | |
272 end_selection_handle_->Hide(); | |
273 is_selection_active_ = false; | |
274 client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF()); | |
275 } | |
276 | |
277 void TouchSelectionController::ResetCachedValues() { | |
278 anchor_rect_ = gfx::RectF(); | |
279 focus_rect_ = gfx::RectF(); | |
280 anchor_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; | |
281 focus_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED; | |
282 anchor_visible_ = false; | |
283 focus_visible_ = false; | |
284 selection_editable_for_last_update_ = false; | |
285 } | |
286 | |
287 gfx::PointF TouchSelectionController::GetAnchorPosition() const { | |
288 return anchor_rect_.bottom_left(); | |
289 } | |
290 | |
291 gfx::PointF TouchSelectionController::GetFocusPosition() const { | |
292 return focus_rect_.bottom_left(); | |
293 } | |
294 | |
295 float TouchSelectionController::GetAnchorLineHeight() const { | |
296 return anchor_rect_.height(); | |
297 } | |
298 | |
299 float TouchSelectionController::GetFocusLineHeight() const { | |
300 return focus_rect_.height(); | |
301 } | |
302 | |
303 } // namespace content | |
OLD | NEW |