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..f2cf135b447e523a21150a07e6d1a32ad2b33df2 |
--- /dev/null |
+++ b/ui/touch_selection/touch_handle_drawable_aura.cc |
@@ -0,0 +1,198 @@ |
+// Copyright 2014 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/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; |
+ |
+gfx::Image* GetCenterHandleImage() { |
+ static gfx::Image* handle_image = nullptr; |
+ if (!handle_image) { |
+ handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
jdduke (slow)
2015/01/28 16:35:32
How expensive are these calls? If they're relative
mohsen
2015/02/22 23:23:09
Yeah, apparently ResourceBundle has its own cachin
|
+ IDR_TEXT_SELECTION_HANDLE_CENTER); |
+ } |
+ return handle_image; |
+} |
+ |
+gfx::Image* GetLeftHandleImage() { |
+ static gfx::Image* handle_image = nullptr; |
+ if (!handle_image) { |
+ handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
+ IDR_TEXT_SELECTION_HANDLE_LEFT); |
+ } |
+ return handle_image; |
+} |
+ |
+gfx::Image* GetRightHandleImage() { |
+ static gfx::Image* handle_image = nullptr; |
+ if (!handle_image) { |
+ handle_image = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
+ IDR_TEXT_SELECTION_HANDLE_RIGHT); |
+ } |
+ return handle_image; |
+} |
+ |
+// Return the appropriate handle image based on the bound's type |
+gfx::Image* GetHandleImage(ui::TouchHandleOrientation orientation) { |
+ switch(orientation) { |
+ case ui::TOUCH_HANDLE_LEFT: |
+ return GetLeftHandleImage(); |
+ case ui::TOUCH_HANDLE_CENTER: |
+ return GetCenterHandleImage(); |
+ case ui::TOUCH_HANDLE_RIGHT: |
+ return GetRightHandleImage(); |
+ default: |
+ NOTREACHED() << "Invalid touch handle bound type."; |
+ return nullptr; |
+ }; |
+} |
+ |
+class TouchHandleDrawableAuraTargeter : public aura::WindowTargeter { |
+ protected: |
+ bool EventLocationInsideBounds(ui::EventTarget* target, |
+ const LocatedEvent& event) const override; |
+}; |
+ |
+bool TouchHandleDrawableAuraTargeter::EventLocationInsideBounds( |
+ EventTarget* target, |
+ const LocatedEvent& event) const { |
+ return false; |
+} |
+ |
+} |
+ |
+// static |
+gfx::Size TouchHandleDrawableAura::GetMaxHandleImageSize() { |
+ gfx::Rect center_rect = gfx::Rect(GetCenterHandleImage()->Size()); |
+ gfx::Rect left_rect = gfx::Rect(GetLeftHandleImage()->Size()); |
+ gfx::Rect right_rect = gfx::Rect(GetRightHandleImage()->Size()); |
+ gfx::Rect union_rect = center_rect; |
+ union_rect.Union(left_rect); |
+ union_rect.Union(right_rect); |
+ return union_rect.size(); |
+} |
+ |
+TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent) |
+ : window_(new aura::Window(this)), |
+ enabled_(false), |
+ alpha_(0), |
+ orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED) { |
+ SetSelfDestroy(false); |
+ SetImageOffset(gfx::Vector2d(kSelectionHandlePadding, |
+ kSelectionHandlePadding)); |
+ SetBackgroundColor(SK_ColorTRANSPARENT); |
+ window_->SetTransparent(true); |
+ window_->Init(aura::WINDOW_LAYER_TEXTURED); |
+ window_->set_owned_by_parent(false); |
+ window_->SetEventTargeter( |
+ scoped_ptr<EventTargeter>(new TouchHandleDrawableAuraTargeter)); |
+ 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::ToNearestRect(new_bounds)); |
+} |
+ |
+void TouchHandleDrawableAura::SetEnabled(bool enabled) { |
+ if (enabled == enabled_) |
+ return; |
+ |
+ enabled_ = enabled; |
+ bool visible = alpha_ > 0; // XXX: float comparison |
+ if (enabled_ && visible) |
+ window_->Show(); |
+ else |
+ window_->Hide(); |
+} |
+ |
+void TouchHandleDrawableAura::SetOrientation( |
+ TouchHandleOrientation orientation) { |
+ if (orientation_ == orientation) |
+ return; |
+ orientation_ = orientation; |
+ gfx::Image* image = GetHandleImage(orientation); |
+ 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 ui::TOUCH_HANDLE_LEFT: |
+ window_left = -image_size.width() - kSelectionHandlePadding; |
+ break; |
+ case ui::TOUCH_HANDLE_RIGHT: |
+ window_left = -kSelectionHandlePadding; |
+ break; |
+ case ui::TOUCH_HANDLE_CENTER: |
+ window_left = -window_width / 2; |
+ break; |
+ default: |
+ 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_) // XXX: float comparison |
+ return; |
+ |
+ alpha_ = alpha; |
+ window_->layer()->SetOpacity(alpha_); |
+ bool visible = alpha_ > 0; // XXX: float comparison |
+ 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 r(window_->bounds()); |
+ r.Inset(kSelectionHandlePadding, |
+ kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset, |
+ kSelectionHandlePadding, |
+ kSelectionHandlePadding); |
+ return r; |
+} |
+ |
+} // namespace ui |