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..8f56d5c1ac8b52cbaba957bc272fef3b4400fa2c |
| --- /dev/null |
| +++ b/ui/touch_selection/touch_handle_drawable_aura.cc |
| @@ -0,0 +1,187 @@ |
| +// 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/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; |
| + 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; |
| + default: |
|
sadrul
2015/03/05 12:37:03
Remove default, explicitly list UNDEFINED
mohsen
2015/03/06 23:10:08
Done.
|
| + NOTREACHED() << "Invalid touch handle bound type."; |
| + return nullptr; |
| + }; |
| + return &ResourceBundle::GetSharedInstance().GetImageNamed(resource_id); |
| +} |
| + |
| +bool IsNearlyZero(float value) { |
| + return std::abs(value) < kEpsilon; |
| +} |
| + |
| +// A window targeter for touch handles that will let every touch event pass |
| +// through handles to the underlying window. |
|
sadrul
2015/03/05 12:37:03
Can you set Window::set_ignore_events() instead?
mfomitchev
2015/03/05 16:07:54
So this is a bit awkward because at this point we
sadrul
2015/03/05 16:56:22
We shouldn't do this in a roundabout way to fit in
mfomitchev
2015/03/05 18:03:24
Yes, that's what I meant. Thus we'd have to switch
mohsen
2015/03/06 23:10:08
This is how ui::TouchSelectionController is implem
|
| +class TouchHandleDrawableAuraTargeter : public aura::WindowTargeter { |
| + protected: |
| + bool EventLocationInsideBounds(EventTarget* target, |
| + const LocatedEvent& event) const override; |
| +}; |
| + |
| +bool TouchHandleDrawableAuraTargeter::EventLocationInsideBounds( |
| + EventTarget* target, |
| + const LocatedEvent& event) const { |
| + return false; |
| +} |
| + |
| +} |
| + |
| +TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent) |
| + : window_(new aura::Window(this)), |
| + enabled_(false), |
| + alpha_(0), |
| + orientation_(TouchHandleOrientation::UNDEFINED) { |
| + set_image_offset(gfx::Vector2d(kSelectionHandlePadding, |
| + kSelectionHandlePadding)); |
| + set_background_color(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() { |
| +} |
| + |
| +// static |
| +gfx::Size TouchHandleDrawableAura::GetMaxHandleImageSize() { |
| + gfx::Size max_size(GetHandleImage(TouchHandleOrientation::CENTER)->Size()); |
| + max_size.SetToMax(GetHandleImage(TouchHandleOrientation::LEFT)->Size()); |
| + max_size.SetToMax(GetHandleImage(TouchHandleOrientation::RIGHT)->Size()); |
| + return max_size; |
| +} |
| + |
| +void TouchHandleDrawableAura::OnWindowDestroyed(aura::Window* window) { |
| + // Overriding ImageWindowDelegate's implementation, which calls |delete this| |
| + // when the window is destroyed - in our case the delegate owns the window, |
| + // and not vice versa. |
| +} |
| + |
| +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 = !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); |
| + 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; |
| + default: |
|
sadrul
2015/03/05 12:37:03
case UNDEFINED: instead of default:
mohsen
2015/03/06 23:10:08
Done.
|
| + 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 |