Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(923)

Side by Side Diff: ui/views/touchui/touch_selection_controller_impl.cc

Issue 769393002: Minor visual improvements to text selection UI (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/touchui/touch_selection_controller_impl.h" 5 #include "ui/views/touchui/touch_selection_controller_impl.h"
6 6
7 #include "base/time/time.h" 7 #include "base/time/time.h"
8 #include "ui/aura/client/cursor_client.h" 8 #include "ui/aura/client/cursor_client.h"
9 #include "ui/aura/env.h" 9 #include "ui/aura/env.h"
10 #include "ui/aura/window.h" 10 #include "ui/aura/window.h"
11 #include "ui/base/resource/resource_bundle.h" 11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/gfx/canvas.h" 12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/image/image.h" 13 #include "ui/gfx/image/image.h"
14 #include "ui/gfx/path.h" 14 #include "ui/gfx/path.h"
15 #include "ui/gfx/rect.h" 15 #include "ui/gfx/rect.h"
16 #include "ui/gfx/screen.h" 16 #include "ui/gfx/screen.h"
17 #include "ui/gfx/size.h" 17 #include "ui/gfx/size.h"
18 #include "ui/resources/grit/ui_resources.h" 18 #include "ui/resources/grit/ui_resources.h"
19 #include "ui/strings/grit/ui_strings.h" 19 #include "ui/strings/grit/ui_strings.h"
20 #include "ui/views/widget/widget.h" 20 #include "ui/views/widget/widget.h"
21 #include "ui/wm/core/coordinate_conversion.h" 21 #include "ui/wm/core/coordinate_conversion.h"
22 #include "ui/wm/core/masked_window_targeter.h" 22 #include "ui/wm/core/masked_window_targeter.h"
23 23
24 namespace { 24 namespace {
25 25
26 // Constants defining the visual attributes of selection handles 26 // Constants defining the visual attributes of selection handles
27 27
28 // Controls the width of the cursor line associated with the selection handle. 28 // The distance by which a handle image is offset from the bottom of the
29 const int kSelectionHandleLineWidth = 2; 29 // selection/text baseline.
30 30 const int kSelectionHandleVerticalVisualOffset = 2;
31 const SkColor kSelectionHandleLineColor =
32 SkColorSetRGB(0x42, 0x81, 0xf4);
33 31
34 // When a handle is dragged, the drag position reported to the client view is 32 // When a handle is dragged, the drag position reported to the client view is
35 // offset vertically to represent the cursor position. This constant specifies 33 // offset vertically to represent the cursor position. This constant specifies
36 // the offset in pixels above the "O" (see pic below). This is required because 34 // the offset in pixels above the bottom of the selection (see pic below). This
mohsen 2014/12/02 22:34:57 nit: Please also remove the extra space in "in pi
mfomitchev 2014/12/03 23:57:19 Done.
37 // say if this is zero, that means the drag position we report is the point 35 // is required because say if this is zero, that means the drag position we
38 // right above the "O" or the bottom most point of the cursor "|". In that case, 36 // report is right on the text baseline. In that case, a vertical movement of
39 // a vertical movement of even one pixel will make the handle jump to the line 37 // even one pixel will make the handle jump to the line below it. So when the
40 // below it. So when the user just starts dragging, the handle will jump to the 38 // user just starts dragging, the handle will jump to the next line if the user
41 // next line if the user makes any vertical movement. It is correct but 39 // makes any vertical movement. So we have this non-zero offset to prevent this
42 // looks/feels weird. So we have this non-zero offset to prevent this jumping. 40 // jumping.
43 // 41 //
44 // Editing handle widget showing the padding and difference between the position 42 // Editing handle widget showing the padding and difference between the position
45 // of the ET_GESTURE_SCROLL_UPDATE event and the drag position reported to the 43 // of the ET_GESTURE_SCROLL_UPDATE event and the drag position reported to the
46 // client: 44 // client:
47 // _____ 45 // ___________
mohsen 2014/12/02 22:34:56 nit: Apparently, this line has trailing spaces. Ca
mfomitchev 2014/12/03 23:57:20 I don't see any. There's a bunch of underscores.
mohsen 2014/12/04 00:34:56 Yep, you're right.
48 // | |<-|---- Drag position reported to client 46 // Selection Highlight --->_____|__|<-|---- Drag position reported to client
49 // _ | O | 47 // _ | O |
50 // Vertical Padding __| | <-|---- ET_GESTURE_SCROLL_UPDATE position 48 // Vertical Padding __| | <-|---- ET_GESTURE_SCROLL_UPDATE position
51 // |_ |_____|<--- Editing handle widget 49 // |_ |_____|<--- Editing handle widget
52 // 50 //
53 // | | 51 // | |
54 // T 52 // T
55 // Horizontal Padding 53 // Horizontal Padding
56 // 54 //
57 const int kSelectionHandleVerticalDragOffset = 5; 55 const int kSelectionHandleVerticalDragOffset = 5;
58 56
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 case ui::SelectionBound::CENTER: 120 case ui::SelectionBound::CENTER:
123 return GetCenterHandleImage(); 121 return GetCenterHandleImage();
124 case ui::SelectionBound::RIGHT: 122 case ui::SelectionBound::RIGHT:
125 return GetRightHandleImage(); 123 return GetRightHandleImage();
126 default: 124 default:
127 NOTREACHED() << "Invalid touch handle bound type."; 125 NOTREACHED() << "Invalid touch handle bound type.";
128 return nullptr; 126 return nullptr;
129 }; 127 };
130 } 128 }
131 129
132 enum Alignment {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
133
134 // Determine the cursor line alignment to the handle image based on the bound
135 // type. Depends on the visual shapes of the handle image assets.
136 Alignment GetCursorAlignment(ui::SelectionBound::Type bound_type) {
137 switch (bound_type) {
138 case ui::SelectionBound::LEFT:
139 return ALIGN_RIGHT;
140 case ui::SelectionBound::RIGHT:
141 return ALIGN_LEFT;
142 case ui::SelectionBound::CENTER:
143 return ALIGN_CENTER;
144 default:
145 NOTREACHED() << "Undefined bound type for cursor alignment.";
146 return ALIGN_LEFT;
147 };
148 }
149
150 // Calculates the bounds of the widget containing the selection handle based 130 // Calculates the bounds of the widget containing the selection handle based
151 // on the SelectionBound's type and location 131 // on the SelectionBound's type and location
152 gfx::Rect GetSelectionWidgetBounds(const ui::SelectionBound& bound) { 132 gfx::Rect GetSelectionWidgetBounds(const ui::SelectionBound& bound) {
153 Alignment cursor_alignment = GetCursorAlignment(bound.type);
154 gfx::Size image_size = GetHandleImage(bound.type)->Size(); 133 gfx::Size image_size = GetHandleImage(bound.type)->Size();
155 int widget_width = image_size.width() + 2 * kSelectionHandleHorizPadding; 134 int widget_width = image_size.width() + 2 * kSelectionHandleHorizPadding;
156 int widget_height = bound.GetHeight() + image_size.height() + 135 int widget_height = bound.GetHeight() + image_size.height() +
157 kSelectionHandleVertPadding; 136 kSelectionHandleVerticalVisualOffset + kSelectionHandleVertPadding;
137 // Due to the shape of the handle images, the widget is aligned differently to
138 // the selection bound depending on the type of the bound.
158 int widget_left = 0; 139 int widget_left = 0;
159 switch (cursor_alignment) { 140 switch (bound.type) {
160 case ALIGN_LEFT: 141 case ui::SelectionBound::LEFT:
161 widget_left = bound.edge_top.x() - kSelectionHandleHorizPadding;
162 break;
163 case ALIGN_RIGHT:
164 widget_left = bound.edge_top.x() - image_size.width() - 142 widget_left = bound.edge_top.x() - image_size.width() -
165 kSelectionHandleHorizPadding; 143 kSelectionHandleHorizPadding;
166 break; 144 break;
167 case ALIGN_CENTER: 145 case ui::SelectionBound::RIGHT:
146 widget_left = bound.edge_top.x() - kSelectionHandleHorizPadding;
147 break;
148 case ui::SelectionBound::CENTER:
168 widget_left = bound.edge_top.x() - widget_width / 2; 149 widget_left = bound.edge_top.x() - widget_width / 2;
169 break; 150 break;
151 default:
152 NOTREACHED() << "Undefined bound type.";
153 break;
170 }; 154 };
171 return gfx::Rect( 155 return gfx::Rect(
172 widget_left, bound.edge_top.y(), widget_width, widget_height); 156 widget_left, bound.edge_top.y(), widget_width, widget_height);
173 } 157 }
174 158
175 gfx::Size GetMaxHandleImageSize() { 159 gfx::Size GetMaxHandleImageSize() {
176 gfx::Rect center_rect = gfx::Rect(GetCenterHandleImage()->Size()); 160 gfx::Rect center_rect = gfx::Rect(GetCenterHandleImage()->Size());
177 gfx::Rect left_rect = gfx::Rect(GetLeftHandleImage()->Size()); 161 gfx::Rect left_rect = gfx::Rect(GetLeftHandleImage()->Size());
178 gfx::Rect right_rect = gfx::Rect(GetRightHandleImage()->Size()); 162 gfx::Rect right_rect = gfx::Rect(GetRightHandleImage()->Size());
179 gfx::Rect union_rect = center_rect; 163 gfx::Rect union_rect = center_rect;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 245
262 ~EditingHandleView() override { SetWidgetVisible(false, false); } 246 ~EditingHandleView() override { SetWidgetVisible(false, false); }
263 247
264 // Overridden from views::WidgetDelegateView: 248 // Overridden from views::WidgetDelegateView:
265 bool WidgetHasHitTestMask() const override { return true; } 249 bool WidgetHasHitTestMask() const override { return true; }
266 250
267 void GetWidgetHitTestMask(gfx::Path* mask) const override { 251 void GetWidgetHitTestMask(gfx::Path* mask) const override {
268 gfx::Size image_size = image_->Size(); 252 gfx::Size image_size = image_->Size();
269 mask->addRect( 253 mask->addRect(
270 SkIntToScalar(0), 254 SkIntToScalar(0),
271 SkIntToScalar(selection_bound_.GetHeight()), 255 SkIntToScalar(selection_bound_.GetHeight() +
256 kSelectionHandleVerticalVisualOffset),
272 SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding, 257 SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding,
273 SkIntToScalar(selection_bound_.GetHeight() + image_size.height() + 258 SkIntToScalar(selection_bound_.GetHeight() +
274 kSelectionHandleVertPadding)); 259 kSelectionHandleVerticalVisualOffset +
260 image_size.height() + kSelectionHandleVertPadding));
275 } 261 }
276 262
277 void DeleteDelegate() override { 263 void DeleteDelegate() override {
278 // We are owned and deleted by TouchSelectionController. 264 // We are owned and deleted by TouchSelectionController.
279 } 265 }
280 266
281 // Overridden from views::View: 267 // Overridden from views::View:
282 void OnPaint(gfx::Canvas* canvas) override { 268 void OnPaint(gfx::Canvas* canvas) override {
283 if (draw_invisible_) 269 if (draw_invisible_)
284 return; 270 return;
285 271
286 Alignment cursor_alignment = GetCursorAlignment(selection_bound_.type);
287 int cursor_x = 0;
288 switch (cursor_alignment) {
289 case ALIGN_RIGHT:
290 cursor_x =
291 selection_bound_.edge_top.x() - kSelectionHandleLineWidth + 1;
292 break;
293 case ALIGN_LEFT:
294 cursor_x = selection_bound_.edge_top.x() - 1;
295 break;
296 case ALIGN_CENTER:
297 cursor_x =
298 selection_bound_.edge_top.x() - kSelectionHandleLineWidth / 2;
299 break;
300 };
301 // Draw the cursor line.
302 canvas->FillRect(gfx::Rect(cursor_x,
303 0,
304 kSelectionHandleLineWidth,
305 selection_bound_.GetHeight()),
306 kSelectionHandleLineColor);
307 // Draw the handle image. 272 // Draw the handle image.
308 canvas->DrawImageInt(*image_->ToImageSkia(), 273 canvas->DrawImageInt(
309 kSelectionHandleHorizPadding, selection_bound_.GetHeight()); 274 *image_->ToImageSkia(),
275 kSelectionHandleHorizPadding,
276 selection_bound_.GetHeight() + kSelectionHandleVerticalVisualOffset);
310 } 277 }
311 278
312 void OnGestureEvent(ui::GestureEvent* event) override { 279 void OnGestureEvent(ui::GestureEvent* event) override {
313 event->SetHandled(); 280 event->SetHandled();
314 switch (event->type()) { 281 switch (event->type()) {
315 case ui::ET_GESTURE_SCROLL_BEGIN: { 282 case ui::ET_GESTURE_SCROLL_BEGIN: {
316 widget_->SetCapture(this); 283 widget_->SetCapture(this);
317 controller_->SetDraggingHandle(this); 284 controller_->SetDraggingHandle(this);
318 // Distance from the point which is |kSelectionHandleVerticalDragOffset| 285 // Distance from the point which is |kSelectionHandleVerticalDragOffset|
319 // pixels above the bottom of the handle's cursor line to the event 286 // pixels above the bottom of the selection bound edge to the event
320 // location (aka the touch-drag point). 287 // location (aka the touch-drag point).
321 drag_offset_ = selection_bound_.edge_bottom - 288 drag_offset_ = selection_bound_.edge_bottom -
322 gfx::Vector2d(0, kSelectionHandleVerticalDragOffset) - 289 gfx::Vector2d(0, kSelectionHandleVerticalDragOffset) -
323 event->location(); 290 event->location();
324 break; 291 break;
325 } 292 }
326 case ui::ET_GESTURE_SCROLL_UPDATE: { 293 case ui::ET_GESTURE_SCROLL_UPDATE: {
327 controller_->SelectionHandleDragged(event->location() + drag_offset_); 294 controller_->SelectionHandleDragged(event->location() + drag_offset_);
328 break; 295 break;
329 } 296 }
330 case ui::ET_GESTURE_SCROLL_END: 297 case ui::ET_GESTURE_SCROLL_END:
331 case ui::ET_SCROLL_FLING_START: 298 case ui::ET_SCROLL_FLING_START:
332 widget_->ReleaseCapture(); 299 widget_->ReleaseCapture();
333 controller_->SetDraggingHandle(nullptr); 300 controller_->SetDraggingHandle(nullptr);
334 break; 301 break;
335 default: 302 default:
336 break; 303 break;
337 } 304 }
338 } 305 }
339 306
340 gfx::Size GetPreferredSize() const override { 307 gfx::Size GetPreferredSize() const override {
341 gfx::Size image_size = image_->Size(); 308 return GetSelectionWidgetBounds(selection_bound_).size();
mohsen 2014/12/02 22:34:56 What about adding a helper function that calculate
mfomitchev 2014/12/03 23:57:20 This would be worthwhile if this was called a bunc
mohsen 2014/12/04 00:34:56 I see. OK.
342 return gfx::Size(image_size.width() + 2 * kSelectionHandleHorizPadding,
343 image_size.height() + selection_bound_.GetHeight() +
344 kSelectionHandleVertPadding);
345 } 309 }
346 310
347 bool IsWidgetVisible() const { 311 bool IsWidgetVisible() const {
348 return widget_->IsVisible(); 312 return widget_->IsVisible();
349 } 313 }
350 314
351 void SetWidgetVisible(bool visible, bool quick) { 315 void SetWidgetVisible(bool visible, bool quick) {
352 if (widget_->IsVisible() == visible) 316 if (widget_->IsVisible() == visible)
353 return; 317 return;
354 widget_->SetVisibilityAnimationDuration( 318 widget_->SetVisibilityAnimationDuration(
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 724
761 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() { 725 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() {
762 return selection_handle_1_.get(); 726 return selection_handle_1_.get();
763 } 727 }
764 728
765 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() { 729 views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() {
766 return selection_handle_2_.get(); 730 return selection_handle_2_.get();
767 } 731 }
768 732
769 } // namespace views 733 } // namespace views
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698