MD Downloads: prevent search text from overlapping with the cancel search (X)
[chromium-blink-merge.git] / ui / touch_selection / touch_handle_drawable_aura.cc
bloba353c59a7fccd7f13457d4f73226ea3d4064445d
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"
18 namespace ui {
19 namespace {
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) {
35 int resource_id = 0;
36 switch (orientation) {
37 case TouchHandleOrientation::LEFT:
38 resource_id = IDR_TEXT_SELECTION_HANDLE_LEFT;
39 break;
40 case TouchHandleOrientation::CENTER:
41 resource_id = IDR_TEXT_SELECTION_HANDLE_CENTER;
42 break;
43 case TouchHandleOrientation::RIGHT:
44 resource_id = IDR_TEXT_SELECTION_HANDLE_RIGHT;
45 break;
46 case TouchHandleOrientation::UNDEFINED:
47 NOTREACHED() << "Invalid touch handle bound type.";
48 return nullptr;
50 return &ResourceBundle::GetSharedInstance().GetImageNamed(resource_id);
53 bool IsNearlyZero(float value) {
54 return std::abs(value) < kEpsilon;
57 } // namespace
59 TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent)
60 : window_delegate_(new aura_extra::ImageWindowDelegate),
61 window_(new aura::Window(window_delegate_)),
62 enabled_(false),
63 alpha_(0),
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_)
90 return;
92 enabled_ = enabled;
93 if (IsVisible())
94 window_->Show();
95 else
96 window_->Hide();
99 void TouchHandleDrawableAura::SetOrientation(
100 TouchHandleOrientation orientation) {
101 if (orientation_ == orientation)
102 return;
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.
113 int window_left = 0;
114 switch (orientation) {
115 case TouchHandleOrientation::LEFT:
116 window_left = -image_size.width() - kSelectionHandlePadding;
117 break;
118 case TouchHandleOrientation::RIGHT:
119 window_left = -kSelectionHandlePadding;
120 break;
121 case TouchHandleOrientation::CENTER:
122 window_left = -window_width / 2;
123 break;
124 case TouchHandleOrientation::UNDEFINED:
125 NOTREACHED() << "Undefined handle orientation.";
126 break;
128 relative_bounds_ = gfx::RectF(
129 window_left,
130 kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding,
131 window_width,
132 window_height);
133 UpdateBounds();
136 void TouchHandleDrawableAura::SetAlpha(float alpha) {
137 if (alpha == alpha_)
138 return;
140 alpha_ = alpha;
141 window_->layer()->SetOpacity(alpha_);
142 if (IsVisible())
143 window_->Show();
144 else
145 window_->Hide();
148 void TouchHandleDrawableAura::SetFocus(const gfx::PointF& position) {
149 focal_position_ = position;
150 UpdateBounds();
153 gfx::RectF TouchHandleDrawableAura::GetVisibleBounds() const {
154 gfx::RectF bounds(window_->bounds());
155 bounds.Inset(kSelectionHandlePadding,
156 kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset,
157 kSelectionHandlePadding,
158 kSelectionHandlePadding);
159 return bounds;
162 } // namespace ui