1 // Copyright 2015 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.
5 #include "ui/touch_selection/touch_handle_drawable_aura.h"
7 #include "ui/aura/window.h"
8 #include "ui/aura/window_targeter.h"
9 #include "ui/aura_extra/image_window_delegate.h"
10 #include "ui/base/cursor/cursor.h"
11 #include "ui/base/hit_test.h"
12 #include "ui/base/resource/resource_bundle.h"
13 #include "ui/events/event.h"
14 #include "ui/gfx/canvas.h"
15 #include "ui/gfx/geometry/rect_conversions.h"
16 #include "ui/resources/grit/ui_resources.h"
21 // The distance by which a handle image is offset from the focal point (i.e.
22 // text baseline) downwards.
23 const int kSelectionHandleVerticalVisualOffset
= 2;
25 // The padding around the selection handle image can be used to extend the
26 // handle window so that touch events near the selection handle image are
27 // targeted to the selection handle window.
28 const int kSelectionHandlePadding
= 0;
30 // Epsilon value used to compare float values to zero.
31 const float kEpsilon
= 1e-8f
;
33 // Returns the appropriate handle image based on the handle orientation.
34 gfx::Image
* GetHandleImage(TouchHandleOrientation orientation
) {
36 switch (orientation
) {
37 case TouchHandleOrientation::LEFT
:
38 resource_id
= IDR_TEXT_SELECTION_HANDLE_LEFT
;
40 case TouchHandleOrientation::CENTER
:
41 resource_id
= IDR_TEXT_SELECTION_HANDLE_CENTER
;
43 case TouchHandleOrientation::RIGHT
:
44 resource_id
= IDR_TEXT_SELECTION_HANDLE_RIGHT
;
46 case TouchHandleOrientation::UNDEFINED
:
47 NOTREACHED() << "Invalid touch handle bound type.";
50 return &ResourceBundle::GetSharedInstance().GetImageNamed(resource_id
);
53 bool IsNearlyZero(float value
) {
54 return std::abs(value
) < kEpsilon
;
59 TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window
* parent
)
60 : window_delegate_(new aura_extra::ImageWindowDelegate
),
61 window_(new aura::Window(window_delegate_
)),
64 orientation_(TouchHandleOrientation::UNDEFINED
) {
65 window_delegate_
->set_image_offset(gfx::Vector2d(kSelectionHandlePadding
,
66 kSelectionHandlePadding
));
67 window_delegate_
->set_background_color(SK_ColorTRANSPARENT
);
68 window_
->SetTransparent(true);
69 window_
->Init(LAYER_TEXTURED
);
70 window_
->set_owned_by_parent(false);
71 window_
->set_ignore_events(true);
72 parent
->AddChild(window_
.get());
75 TouchHandleDrawableAura::~TouchHandleDrawableAura() {
78 void TouchHandleDrawableAura::UpdateBounds() {
79 gfx::RectF new_bounds
= relative_bounds_
;
80 new_bounds
.Offset(focal_position_
.x(), focal_position_
.y());
81 window_
->SetBounds(gfx::ToEnclosingRect(new_bounds
));
84 bool TouchHandleDrawableAura::IsVisible() const {
85 return enabled_
&& !IsNearlyZero(alpha_
);
88 void TouchHandleDrawableAura::SetEnabled(bool enabled
) {
89 if (enabled
== enabled_
)
99 void TouchHandleDrawableAura::SetOrientation(
100 TouchHandleOrientation orientation
) {
101 if (orientation_
== orientation
)
103 orientation_
= orientation
;
104 gfx::Image
* image
= GetHandleImage(orientation
);
105 window_delegate_
->SetImage(*image
);
107 // Calculate the relative bounds.
108 gfx::Size image_size
= image
->Size();
109 int window_width
= image_size
.width() + 2 * kSelectionHandlePadding
;
110 int window_height
= image_size
.height() + 2 * kSelectionHandlePadding
;
111 // Due to the shape of the handle images, the window is aligned differently to
112 // the selection bound depending on the orientation.
114 switch (orientation
) {
115 case TouchHandleOrientation::LEFT
:
116 window_left
= -image_size
.width() - kSelectionHandlePadding
;
118 case TouchHandleOrientation::RIGHT
:
119 window_left
= -kSelectionHandlePadding
;
121 case TouchHandleOrientation::CENTER
:
122 window_left
= -window_width
/ 2;
124 case TouchHandleOrientation::UNDEFINED
:
125 NOTREACHED() << "Undefined handle orientation.";
128 relative_bounds_
= gfx::RectF(
130 kSelectionHandleVerticalVisualOffset
- kSelectionHandlePadding
,
136 void TouchHandleDrawableAura::SetAlpha(float alpha
) {
141 window_
->layer()->SetOpacity(alpha_
);
148 void TouchHandleDrawableAura::SetFocus(const gfx::PointF
& position
) {
149 focal_position_
= position
;
153 gfx::RectF
TouchHandleDrawableAura::GetVisibleBounds() const {
154 gfx::RectF
bounds(window_
->bounds());
155 bounds
.Inset(kSelectionHandlePadding
,
156 kSelectionHandlePadding
+ kSelectionHandleVerticalVisualOffset
,
157 kSelectionHandlePadding
,
158 kSelectionHandlePadding
);