Index: ui/touch_selection/touch_handle_drawable_aura.cc |
diff --git a/ui/touch_selection/touch_handle_drawable_aura.cc b/ui/touch_selection/touch_handle_drawable_aura.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3fadeede44cfaf7ca906ab36cde20ca909d2e815 |
--- /dev/null |
+++ b/ui/touch_selection/touch_handle_drawable_aura.cc |
@@ -0,0 +1,160 @@ |
+// Copyright 2015 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. |
+ |
+#include "ui/touch_selection/touch_handle_drawable_aura.h" |
+ |
+#include "ui/aura/window.h" |
+#include "ui/aura/window_targeter.h" |
+#include "ui/aura_extra/image_window_delegate.h" |
+#include "ui/base/cursor/cursor.h" |
+#include "ui/base/hit_test.h" |
+#include "ui/base/resource/resource_bundle.h" |
+#include "ui/events/event.h" |
+#include "ui/gfx/canvas.h" |
+#include "ui/gfx/geometry/rect_conversions.h" |
+#include "ui/resources/grit/ui_resources.h" |
+ |
+namespace ui { |
+namespace { |
+ |
+// The distance by which a handle image is offset from the focal point (i.e. |
+// text baseline) downwards. |
+const int kSelectionHandleVerticalVisualOffset = 2; |
+ |
+// The padding around the selection handle image can be used to extend the |
+// handle window so that touch events near the selection handle image are |
+// targeted to the selection handle window. |
+const int kSelectionHandlePadding = 0; |
+ |
+// Epsilon value used to compare float values to zero. |
+const float kEpsilon = 1e-8f; |
+ |
+// Returns the appropriate handle image based on the handle orientation. |
+gfx::Image* GetHandleImage(TouchHandleOrientation orientation) { |
+ int resource_id = 0; |
+ switch (orientation) { |
+ case TouchHandleOrientation::LEFT: |
+ resource_id = IDR_TEXT_SELECTION_HANDLE_LEFT; |
+ break; |
+ case TouchHandleOrientation::CENTER: |
+ resource_id = IDR_TEXT_SELECTION_HANDLE_CENTER; |
+ break; |
+ case TouchHandleOrientation::RIGHT: |
+ resource_id = IDR_TEXT_SELECTION_HANDLE_RIGHT; |
+ break; |
+ case TouchHandleOrientation::UNDEFINED: |
+ NOTREACHED() << "Invalid touch handle bound type."; |
+ return nullptr; |
+ }; |
+ return &ResourceBundle::GetSharedInstance().GetImageNamed(resource_id); |
+} |
+ |
+bool IsNearlyZero(float value) { |
+ return std::abs(value) < kEpsilon; |
+} |
+ |
+} // namespace |
+ |
+TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent) |
+ : window_delegate_(new aura_extra::ImageWindowDelegate), |
+ window_(new aura::Window(window_delegate_)), |
+ enabled_(false), |
+ alpha_(0), |
+ orientation_(TouchHandleOrientation::UNDEFINED) { |
+ window_delegate_->set_image_offset(gfx::Vector2d(kSelectionHandlePadding, |
+ kSelectionHandlePadding)); |
+ window_delegate_->set_background_color(SK_ColorTRANSPARENT); |
+ window_->SetTransparent(true); |
+ window_->Init(LAYER_TEXTURED); |
+ window_->set_owned_by_parent(false); |
+ window_->set_ignore_events(true); |
+ parent->AddChild(window_.get()); |
+} |
+ |
+TouchHandleDrawableAura::~TouchHandleDrawableAura() { |
+} |
+ |
+void TouchHandleDrawableAura::UpdateBounds() { |
+ gfx::RectF new_bounds = relative_bounds_; |
+ new_bounds.Offset(focal_position_.x(), focal_position_.y()); |
+ window_->SetBounds(gfx::ToEnclosingRect(new_bounds)); |
+} |
+ |
+void TouchHandleDrawableAura::SetEnabled(bool enabled) { |
+ if (enabled == enabled_) |
+ return; |
+ |
+ enabled_ = enabled; |
+ bool visible = !IsNearlyZero(alpha_); |
+ if (enabled_ && visible) |
+ window_->Show(); |
+ else |
+ window_->Hide(); |
+} |
+ |
+void TouchHandleDrawableAura::SetOrientation( |
+ TouchHandleOrientation orientation) { |
+ if (orientation_ == orientation) |
+ return; |
+ orientation_ = orientation; |
+ gfx::Image* image = GetHandleImage(orientation); |
+ window_delegate_->SetImage(*image); |
+ |
+ // Calculate the relative bounds. |
+ gfx::Size image_size = image->Size(); |
+ int window_width = image_size.width() + 2 * kSelectionHandlePadding; |
+ int window_height = image_size.height() + 2 * kSelectionHandlePadding; |
+ // Due to the shape of the handle images, the window is aligned differently to |
+ // the selection bound depending on the orientation. |
+ int window_left = 0; |
+ switch (orientation) { |
+ case TouchHandleOrientation::LEFT: |
+ window_left = -image_size.width() - kSelectionHandlePadding; |
+ break; |
+ case TouchHandleOrientation::RIGHT: |
+ window_left = -kSelectionHandlePadding; |
+ break; |
+ case TouchHandleOrientation::CENTER: |
+ window_left = -window_width / 2; |
+ break; |
+ case TouchHandleOrientation::UNDEFINED: |
+ NOTREACHED() << "Undefined handle orientation."; |
+ break; |
+ }; |
+ relative_bounds_ = gfx::RectF( |
+ window_left, |
+ kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding, |
+ window_width, |
+ window_height); |
+ UpdateBounds(); |
+} |
+ |
+void TouchHandleDrawableAura::SetAlpha(float alpha) { |
+ if (alpha == alpha_) |
+ return; |
+ |
+ alpha_ = alpha; |
+ window_->layer()->SetOpacity(alpha_); |
+ bool visible = !IsNearlyZero(alpha_); |
+ if (enabled_ && visible) |
+ window_->Show(); |
+ else |
+ window_->Hide(); |
+} |
+ |
+void TouchHandleDrawableAura::SetFocus(const gfx::PointF& position) { |
+ focal_position_ = position; |
+ UpdateBounds(); |
+} |
+ |
+gfx::RectF TouchHandleDrawableAura::GetVisibleBounds() const { |
+ gfx::RectF bounds(window_->bounds()); |
+ bounds.Inset(kSelectionHandlePadding, |
+ kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset, |
+ kSelectionHandlePadding, |
+ kSelectionHandlePadding); |
+ return bounds; |
+} |
+ |
+} // namespace ui |