blob: 206f850c916b1e1151eae3e71495eec52170919a [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/skia_util.h"
#include "ui/views/view.h"
#include "ui/views/view_class_properties.h"
namespace views {
HighlightPathGenerator::RoundRect::RoundRect() = default;
HighlightPathGenerator::RoundRect::RoundRect(const gfx::RectF& bounds,
float corner_radius)
: bounds(bounds), corner_radius(corner_radius) {}
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<HighlightPathGenerator::RoundRect>
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<HighlightPathGenerator::RoundRect> round_rect =
GetRoundRect(view);
DCHECK(round_rect);
return SkPath().addRRect(
SkRRect{gfx::RRectF(round_rect->bounds, round_rect->corner_radius)});
}
base::Optional<HighlightPathGenerator::RoundRect>
HighlightPathGenerator::GetRoundRect(const gfx::RectF& rect) {
return base::nullopt;
}
base::Optional<HighlightPathGenerator::RoundRect>
HighlightPathGenerator::GetRoundRect(const View* view) {
gfx::Rect bounds(view->GetLocalBounds());
bounds.Inset(insets_);
return GetRoundRect(gfx::RectF(bounds));
}
base::Optional<HighlightPathGenerator::RoundRect>
EmptyHighlightPathGenerator::GetRoundRect(const gfx::RectF& rect) {
return HighlightPathGenerator::RoundRect();
}
void InstallEmptyHighlightPathGenerator(View* view) {
HighlightPathGenerator::Install(
view, std::make_unique<EmptyHighlightPathGenerator>());
}
base::Optional<HighlightPathGenerator::RoundRect>
RectHighlightPathGenerator::GetRoundRect(const gfx::RectF& rect) {
return HighlightPathGenerator::RoundRect{rect, /*corner_radius=*/0};
}
void InstallRectHighlightPathGenerator(View* view) {
HighlightPathGenerator::Install(
view, std::make_unique<RectHighlightPathGenerator>());
}
CircleHighlightPathGenerator::CircleHighlightPathGenerator(
const gfx::Insets& insets)
: HighlightPathGenerator(insets) {}
base::Optional<HighlightPathGenerator::RoundRect>
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 HighlightPathGenerator::RoundRect{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));
}
SkPath PillHighlightPathGenerator::GetHighlightPath(const View* view) {
const SkRect rect = gfx::RectToSkRect(view->GetLocalBounds());
const SkScalar corner_radius =
SkScalarHalf(std::min(rect.width(), rect.height()));
return SkPath().addRoundRect(gfx::RectToSkRect(view->GetLocalBounds()),
corner_radius, corner_radius);
}
void InstallPillHighlightPathGenerator(View* view) {
HighlightPathGenerator::Install(
view, std::make_unique<PillHighlightPathGenerator>());
}
FixedSizeCircleHighlightPathGenerator::FixedSizeCircleHighlightPathGenerator(
int radius)
: radius_(radius) {}
base::Optional<HighlightPathGenerator::RoundRect>
FixedSizeCircleHighlightPathGenerator::GetRoundRect(const gfx::RectF& rect) {
gfx::RectF bounds = rect;
bounds.ClampToCenteredSize(gfx::SizeF(radius_ * 2, radius_ * 2));
return HighlightPathGenerator::RoundRect{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<HighlightPathGenerator::RoundRect>
RoundRectHighlightPathGenerator::GetRoundRect(const gfx::RectF& rect) {
return HighlightPathGenerator::RoundRect{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