Chromium Code Reviews| 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 |