#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/compositor/layer.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 {
const int kSelectionHandleVerticalVisualOffset = 2;
const int kSelectionHandlePadding = 0;
const float kEpsilon = 1e-8f;
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;
}
}
TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent)
: window_(
std::make_unique<aura::Window>(new aura_extra::ImageWindowDelegate)),
window_delegate_(
static_cast<aura_extra::ImageWindowDelegate*>(window_->delegate())),
enabled_(false),
alpha_(0),
orientation_(TouchHandleOrientation::UNDEFINED) {
window_delegate_->set_image_offset(gfx::Vector2d(kSelectionHandlePadding,
kSelectionHandlePadding));
window_->SetTransparent(true);
window_->Init(LAYER_TEXTURED);
window_->set_owned_by_parent(false);
window_->SetEventTargetingPolicy(aura::EventTargetingPolicy::kNone);
parent->AddChild(window_.get());
}
TouchHandleDrawableAura::~TouchHandleDrawableAura() {
}
void TouchHandleDrawableAura::UpdateBounds() {
gfx::RectF new_bounds = relative_bounds_;
new_bounds.Offset(origin_position_.x(), origin_position_.y());
window_->SetBounds(gfx::ToEnclosingRect(new_bounds));
}
bool TouchHandleDrawableAura::IsVisible() const {
return enabled_ && !IsNearlyZero(alpha_);
}
void TouchHandleDrawableAura::SetEnabled(bool enabled) {
if (enabled == enabled_)
return;
enabled_ = enabled;
if (IsVisible())
window_->Show();
else
window_->Hide();
}
void TouchHandleDrawableAura::SetOrientation(TouchHandleOrientation orientation,
bool mirror_vertical,
bool mirror_horizontal) {
DCHECK(window_delegate_);
DCHECK(!mirror_vertical);
DCHECK(!mirror_horizontal);
if (orientation_ == orientation)
return;
orientation_ = orientation;
gfx::Image* image = GetHandleImage(orientation);
window_delegate_->SetImage(*image);
gfx::Size image_size = image->Size();
int window_width = image_size.width() + 2 * kSelectionHandlePadding;
int window_height = image_size.height() + 2 * kSelectionHandlePadding;
relative_bounds_ =
gfx::RectF(-kSelectionHandlePadding,
kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding,
window_width, window_height);
gfx::Rect paint_bounds(relative_bounds_.x(), relative_bounds_.y(),
relative_bounds_.width(), relative_bounds_.height());
window_->SchedulePaintInRect(paint_bounds);
UpdateBounds();
}
void TouchHandleDrawableAura::SetOrigin(const gfx::PointF& position) {
origin_position_ = position;
UpdateBounds();
}
void TouchHandleDrawableAura::SetAlpha(float alpha) {
if (alpha == alpha_)
return;
alpha_ = alpha;
window_->layer()->SetOpacity(alpha_);
if (IsVisible())
window_->Show();
else
window_->Hide();
}
gfx::RectF TouchHandleDrawableAura::GetVisibleBounds() const {
gfx::RectF bounds(window_->bounds());
bounds.Inset(gfx::InsetsF::TLBR(
kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset,
kSelectionHandlePadding, kSelectionHandlePadding,
kSelectionHandlePadding));
return bounds;
}
float TouchHandleDrawableAura::GetDrawableHorizontalPaddingRatio() const {
return 0.0f;
}
#if BUILDFLAG(IS_OHOS)
void TouchHandleDrawableAura::SetEdge(const gfx::PointF& top,
const gfx::PointF& bottom) {}
#endif
}