blob: 7899b1affc0e9f984fa6550fa3d2f1630ec9f52c [file] [log] [blame]
// Copyright 2019 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/views/controls/highlight_path_generator.h"
#include <algorithm>
#include "third_party/skia/include/core/SkRect.h"
#include "ui/gfx/rrect_f.h"
#include "ui/gfx/skia_util.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"
namespace views {
HighlightPathGenerator::HighlightPathGenerator()
: HighlightPathGenerator(gfx::Insets()) {}
HighlightPathGenerator::HighlightPathGenerator(const gfx::Insets& insets)
: insets_(insets) {}
HighlightPathGenerator::~HighlightPathGenerator() = default;
// static
void HighlightPathGenerator::Install(
View* host,
std::unique_ptr<HighlightPathGenerator> generator) {
host->SetProperty(kHighlightPathGeneratorKey, generator.release());
}
// static
base::Optional<gfx::RRectF> HighlightPathGenerator::GetRoundRectForView(
const View* view) {
HighlightPathGenerator* path_generator =
view->GetProperty(kHighlightPathGeneratorKey);
return path_generator ? path_generator->GetRoundRect(view) : base::nullopt;
}
SkPath HighlightPathGenerator::GetHighlightPath(const View* view) {
// A rounded rectangle must be supplied if using this default implementation.
base::Optional<gfx::RRectF> round_rect = GetRoundRect(view);
DCHECK(round_rect);
return SkPath().addRRect(SkRRect{*round_rect});
}
base::Optional<gfx::RRectF> HighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
return base::nullopt;
}
base::Optional<gfx::RRectF> HighlightPathGenerator::GetRoundRect(
const View* view) {
gfx::Rect bounds =
use_contents_bounds_ ? view->GetContentsBounds() : view->GetLocalBounds();
bounds.Inset(insets_);
if (use_mirrored_rect_)
bounds = view->GetMirroredRect(bounds);
return GetRoundRect(gfx::RectF(bounds));
}
base::Optional<gfx::RRectF> EmptyHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
return gfx::RRectF();
}
void InstallEmptyHighlightPathGenerator(View* view) {
HighlightPathGenerator::Install(
view, std::make_unique<EmptyHighlightPathGenerator>());
}
base::Optional<gfx::RRectF> RectHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
return gfx::RRectF(rect);
}
void InstallRectHighlightPathGenerator(View* view) {
HighlightPathGenerator::Install(
view, std::make_unique<RectHighlightPathGenerator>());
}
CircleHighlightPathGenerator::CircleHighlightPathGenerator(
const gfx::Insets& insets)
: HighlightPathGenerator(insets) {}
base::Optional<gfx::RRectF> CircleHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
gfx::RectF bounds = rect;
const float corner_radius = std::min(bounds.width(), bounds.height()) / 2.f;
bounds.ClampToCenteredSize(
gfx::SizeF(corner_radius * 2.f, corner_radius * 2.f));
return gfx::RRectF(bounds, corner_radius);
}
void InstallCircleHighlightPathGenerator(View* view) {
InstallCircleHighlightPathGenerator(view, gfx::Insets());
}
void InstallCircleHighlightPathGenerator(View* view,
const gfx::Insets& insets) {
HighlightPathGenerator::Install(
view, std::make_unique<CircleHighlightPathGenerator>(insets));
}
base::Optional<gfx::RRectF> PillHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
gfx::RectF bounds = rect;
const float corner_radius = std::min(bounds.width(), bounds.height()) / 2.f;
return gfx::RRectF(bounds, corner_radius);
}
void InstallPillHighlightPathGenerator(View* view) {
HighlightPathGenerator::Install(
view, std::make_unique<PillHighlightPathGenerator>());
}
FixedSizeCircleHighlightPathGenerator::FixedSizeCircleHighlightPathGenerator(
int radius)
: radius_(radius) {}
base::Optional<gfx::RRectF> FixedSizeCircleHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
gfx::RectF bounds = rect;
bounds.ClampToCenteredSize(gfx::SizeF(radius_ * 2, radius_ * 2));
return gfx::RRectF(bounds, radius_);
}
void InstallFixedSizeCircleHighlightPathGenerator(View* view, int radius) {
HighlightPathGenerator::Install(
view, std::make_unique<FixedSizeCircleHighlightPathGenerator>(radius));
}
RoundRectHighlightPathGenerator::RoundRectHighlightPathGenerator(
const gfx::Insets& insets,
int corner_radius)
: HighlightPathGenerator(insets), corner_radius_(corner_radius) {}
base::Optional<gfx::RRectF> RoundRectHighlightPathGenerator::GetRoundRect(
const gfx::RectF& rect) {
return gfx::RRectF(rect, corner_radius_);
}
void InstallRoundRectHighlightPathGenerator(View* view,
const gfx::Insets& insets,
int corner_radius) {
HighlightPathGenerator::Install(
view,
std::make_unique<RoundRectHighlightPathGenerator>(insets, corner_radius));
}
} // namespace views