blob: 153411dc40d61413a70935104fa6856944d2b44a [file] [log] [blame]
// Copyright (c) 2012 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/border.h"
#include <memory>
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/views/painter.h"
#include "ui/views/view.h"
namespace views {
namespace {
// A simple border with different thicknesses on each side and single color.
class SolidSidedBorder : public Border {
public:
SolidSidedBorder(const gfx::Insets& insets, SkColor color);
// Overridden from Border:
void Paint(const View& view, gfx::Canvas* canvas) override;
gfx::Insets GetInsets() const override;
gfx::Size GetMinimumSize() const override;
private:
const gfx::Insets insets_;
const SkColor color_;
DISALLOW_COPY_AND_ASSIGN(SolidSidedBorder);
};
SolidSidedBorder::SolidSidedBorder(const gfx::Insets& insets, SkColor color)
: insets_(insets),
color_(color) {
}
void SolidSidedBorder::Paint(const View& view, gfx::Canvas* canvas) {
// Top border.
canvas->FillRect(gfx::Rect(0, 0, view.width(), insets_.top()), color_);
// Left border.
canvas->FillRect(gfx::Rect(0, insets_.top(), insets_.left(),
view.height() - insets_.height()), color_);
// Bottom border.
canvas->FillRect(gfx::Rect(0, view.height() - insets_.bottom(), view.width(),
insets_.bottom()), color_);
// Right border.
canvas->FillRect(gfx::Rect(view.width() - insets_.right(), insets_.top(),
insets_.right(), view.height() - insets_.height()),
color_);
}
gfx::Insets SolidSidedBorder::GetInsets() const {
return insets_;
}
gfx::Size SolidSidedBorder::GetMinimumSize() const {
return gfx::Size(insets_.width(), insets_.height());
}
// A border with a rounded rectangle and single color.
class RoundedRectBorder : public Border {
public:
RoundedRectBorder(int thickness, int corner_radius, SkColor color);
// Overridden from Border:
void Paint(const View& view, gfx::Canvas* canvas) override;
gfx::Insets GetInsets() const override;
gfx::Size GetMinimumSize() const override;
private:
const int thickness_;
const int corner_radius_;
const SkColor color_;
DISALLOW_COPY_AND_ASSIGN(RoundedRectBorder);
};
RoundedRectBorder::RoundedRectBorder(int thickness,
int corner_radius,
SkColor color)
: thickness_(thickness), corner_radius_(corner_radius), color_(color) {}
void RoundedRectBorder::Paint(const View& view, gfx::Canvas* canvas) {
SkPaint paint;
paint.setStrokeWidth(thickness_);
paint.setColor(color_);
paint.setStyle(SkPaint::kStroke_Style);
paint.setAntiAlias(true);
float half_thickness = thickness_ / 2.0f;
gfx::RectF bounds(view.GetLocalBounds());
bounds.Inset(half_thickness, half_thickness);
canvas->DrawRoundRect(bounds, corner_radius_, paint);
}
gfx::Insets RoundedRectBorder::GetInsets() const {
return gfx::Insets(thickness_);
}
gfx::Size RoundedRectBorder::GetMinimumSize() const {
return gfx::Size(thickness_ * 2, thickness_ * 2);
}
class EmptyBorder : public Border {
public:
explicit EmptyBorder(const gfx::Insets& insets);
// Overridden from Border:
void Paint(const View& view, gfx::Canvas* canvas) override;
gfx::Insets GetInsets() const override ;
gfx::Size GetMinimumSize() const override;
private:
const gfx::Insets insets_;
DISALLOW_COPY_AND_ASSIGN(EmptyBorder);
};
EmptyBorder::EmptyBorder(const gfx::Insets& insets) : insets_(insets) {
}
void EmptyBorder::Paint(const View& view, gfx::Canvas* canvas) {
}
gfx::Insets EmptyBorder::GetInsets() const {
return insets_;
}
gfx::Size EmptyBorder::GetMinimumSize() const {
return gfx::Size();
}
class BorderPainter : public Border {
public:
BorderPainter(std::unique_ptr<Painter> painter, const gfx::Insets& insets);
// Overridden from Border:
void Paint(const View& view, gfx::Canvas* canvas) override;
gfx::Insets GetInsets() const override;
gfx::Size GetMinimumSize() const override;
private:
std::unique_ptr<Painter> painter_;
const gfx::Insets insets_;
DISALLOW_COPY_AND_ASSIGN(BorderPainter);
};
BorderPainter::BorderPainter(std::unique_ptr<Painter> painter,
const gfx::Insets& insets)
: painter_(std::move(painter)), insets_(insets) {
DCHECK(painter_);
}
void BorderPainter::Paint(const View& view, gfx::Canvas* canvas) {
Painter::PaintPainterAt(canvas, painter_.get(), view.GetLocalBounds());
}
gfx::Insets BorderPainter::GetInsets() const {
return insets_;
}
gfx::Size BorderPainter::GetMinimumSize() const {
return painter_->GetMinimumSize();
}
} // namespace
Border::Border() {
}
Border::~Border() {
}
// static
std::unique_ptr<Border> Border::NullBorder() {
return nullptr;
}
// static
std::unique_ptr<Border> Border::CreateSolidBorder(int thickness,
SkColor color) {
return base::MakeUnique<SolidSidedBorder>(gfx::Insets(thickness), color);
}
// static
std::unique_ptr<Border> Border::CreateEmptyBorder(const gfx::Insets& insets) {
return base::MakeUnique<EmptyBorder>(insets);
}
// static
std::unique_ptr<Border> Border::CreateRoundedRectBorder(int thickness,
int corner_radius,
SkColor color) {
return base::MakeUnique<RoundedRectBorder>(thickness, corner_radius, color);
}
// static
std::unique_ptr<Border> Border::CreateEmptyBorder(int top,
int left,
int bottom,
int right) {
return CreateEmptyBorder(gfx::Insets(top, left, bottom, right));
}
// static
std::unique_ptr<Border> Border::CreateSolidSidedBorder(int top,
int left,
int bottom,
int right,
SkColor color) {
return base::MakeUnique<SolidSidedBorder>(
gfx::Insets(top, left, bottom, right), color);
}
// static
std::unique_ptr<Border> Border::CreateBorderPainter(
std::unique_ptr<Painter> painter,
const gfx::Insets& insets) {
return base::WrapUnique(new BorderPainter(std::move(painter), insets));
}
} // namespace views