blob: cb52093d8d189e5acbcf8ebd2ff25a25558c58fe [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/enterprise/watermark/watermark_example.h"
#include <memory>
#include "base/strings/stringprintf.h"
#include "cc/paint/paint_canvas.h"
#include "chrome/browser/enterprise/watermark/watermark_view.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/layout/layout_manager.h"
namespace {
constexpr SkColor kDefaultExampleFillColor = SkColorSetARGB(0x2A, 0, 0, 0);
constexpr SkColor kDefaultExampleOutlineColor = SkColorSetARGB(0x3D, 0, 0, 0);
constexpr int kDefaultExampleFontSize = 24;
class GradientView : public views::View {
public:
METADATA_HEADER(GradientView, views::View)
void OnPaintBackground(gfx::Canvas* canvas) override {
cc::PaintFlags flags;
SkColor left = SkColorSetARGB(0xff, 0xff, 0xff, 0xff);
SkColor right = SkColorSetARGB(0xff, 0, 0, 0);
flags.setShader(gfx::CreateGradientShader(
gfx::Point(width(), 0), gfx::Point(0, height()), left, right));
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->DrawRect(GetLocalBounds(), flags);
}
};
class CustomLayoutManager : views::LayoutManager {
// views::LayoutManager
void Layout(views::View* host) override {}
private:
raw_ptr<views::View> contents_view_;
raw_ptr<views::View> watermark_view_;
};
BEGIN_METADATA(GradientView)
END_METADATA
} // namespace
WatermarkExample::WatermarkExample()
: ExampleBase("Watermark"),
rotation_sliders_(4),
rotation_slider_labels_(4),
translate_sliders_(2),
translate_slider_labels_(2) {}
void WatermarkExample::CreateExampleView(views::View* container) {
auto* box_layout =
container->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
// top view
auto* watermark_container =
container->AddChildView(std::make_unique<views::View>());
watermark_container->SetUseDefaultFillLayout(true);
watermark_container->AddChildView(std::make_unique<GradientView>());
watermark_container->SetPaintToLayer();
watermark_view_ = watermark_container->AddChildView(
std::make_unique<enterprise_watermark::WatermarkView>());
watermark_view_->SetString("Private! Confidential", kDefaultExampleFillColor,
kDefaultExampleOutlineColor,
kDefaultExampleFontSize);
box_layout->SetFlexForView(watermark_container, 13);
// Background checkbox and text
auto* checkbox_container =
container->AddChildView(std::make_unique<views::BoxLayoutView>());
background_checkbox_ =
checkbox_container->AddChildView(std::make_unique<views::Checkbox>(
u"Show Background",
base::BindRepeating(&WatermarkExample::UpdateWatermarkViewBackground,
base::Unretained(this))));
auto* watermark_textarea = checkbox_container->AddChildView(
std::make_unique<WatermarkTextArea>(watermark_view_));
watermark_textarea->SetController(this);
watermark_textarea->GetViewAccessibility().SetName(u"WM textarea");
watermark_textarea->SetDefaultWidthInChars(100);
box_layout->SetFlexForView(checkbox_container, 1);
// Rotation Axis
std::vector<SliderInfo> slider_infos = {
{.label = "x", .initial_value = 0.0},
{.label = "y", .initial_value = 0.0},
{.label = "z", .initial_value = 0.0},
{.label = "angle", .initial_value = 0.0}};
auto slider_container = AddSliderGroup(
"Rotation", slider_infos, rotation_sliders_, rotation_slider_labels_);
auto* ptr = container->AddChildView(std::move(slider_container));
box_layout->SetFlexForView(ptr, 1);
// Translate sliders
std::vector<SliderInfo> translate_slider_infos = {
{.label = "x", .initial_value = 0.5},
{.label = "y", .initial_value = 0.5}};
slider_container =
AddSliderGroup("Translation", translate_slider_infos, translate_sliders_,
translate_slider_labels_);
ptr = container->AddChildView(std::move(slider_container));
box_layout->SetFlexForView(ptr, 1);
// had to call Slider::SetValue() after, because the SliderValueChanged()
// callback references all sliders, so I needed all of them to be constructed
// before calling SetValue()
for (int i = 0; i < 4; ++i) {
rotation_sliders_[i]->SetValue(slider_infos[i].initial_value);
}
for (int i = 0; i < 2; ++i) {
translate_sliders_[i]->SetValue(slider_infos[i].initial_value);
}
watermark_view_->SetSize({2000, 2000});
}
std::unique_ptr<views::BoxLayoutView> WatermarkExample::AddSliderGroup(
const std::string& name,
const std::vector<SliderInfo>& slider_infos,
std::vector<views::Slider*>& sliders,
std::vector<views::Label*>& labels) {
assert(slider_infos.size() == sliders.size());
assert(slider_infos.size() == labels.size());
auto slider_container = std::make_unique<views::BoxLayoutView>();
slider_container->SetLayoutManager(std::make_unique<views::BoxLayout>());
slider_container->AddChildView(
std::make_unique<views::Label>(base::ASCIIToUTF16(name)));
for (size_t i = 0; i < slider_infos.size(); ++i) {
auto slider_view = std::make_unique<views::BoxLayoutView>();
slider_view->SetLayoutManager(std::make_unique<views::BoxLayout>());
slider_view->AddChildView(std::make_unique<views::Label>(base::ASCIIToUTF16(
base::StringPrintf("%s: ", slider_infos[i].label.c_str()))));
labels[i] = slider_view->AddChildView(
std::make_unique<views::Label>(base::ASCIIToUTF16(
base::StringPrintf("%.3lf ", slider_infos[i].initial_value))));
auto* slider =
slider_view->AddChildView(std::make_unique<views::Slider>(this));
// Setting view accessibility is required by a DCHECK, I just set it
// randomly for now
slider->GetViewAccessibility().SetName("Slider",
ax::mojom::NameFrom::kAttribute);
sliders[i] = slider;
slider_container->AddChildView(std::move(slider_view));
}
return slider_container;
}
void WatermarkExample::SliderValueChanged(views::Slider* sender,
float value,
float old_value,
views::SliderChangeReason reason) {
// Set the view's rotation
gfx::Transform transform;
transform.Translate(translate_sliders_[0]->GetValue() * 500 - 250,
translate_sliders_[1]->GetValue() * 500 - 250);
transform.RotateAbout(rotation_sliders_[0]->GetValue(),
rotation_sliders_[1]->GetValue(),
rotation_sliders_[2]->GetValue(),
rotation_sliders_[3]->GetValue() * 360.0);
watermark_view_->SetTransform(transform);
// update rotation labels
for (int i = 0; i < 3; ++i) {
rotation_slider_labels_[i]->SetText(base::ASCIIToUTF16(
base::StringPrintf("%.3lf ", rotation_sliders_[i]->GetValue())));
}
rotation_slider_labels_[3]->SetText(base::ASCIIToUTF16(
base::StringPrintf("%.3lf ", rotation_sliders_[3]->GetValue() * 360.0)));
// update translation labels
for (int i = 0; i < 2; ++i) {
translate_slider_labels_[i]->SetText(base::ASCIIToUTF16(base::StringPrintf(
"%.3lf ", translate_sliders_[i]->GetValue() * 500 - 250)));
}
}
void WatermarkExample::UpdateWatermarkViewBackground() {
if (background_checkbox_->GetChecked()) {
watermark_view_->SetBackgroundColor(SkColorSetARGB(0xc, 0xff, 0, 0));
} else {
watermark_view_->SetBackgroundColor(SkColorSetARGB(0, 0, 0, 0));
}
}
WatermarkExample::~WatermarkExample() = default;
// WatermarkTextArea
WatermarkTextArea::WatermarkTextArea(enterprise_watermark::WatermarkView* view)
: watermark_view_(view) {}
void WatermarkTextArea::OnTextChanged() {
Textfield::OnTextChanged();
watermark_view_->SetString(
base::UTF16ToUTF8(GetText()), kDefaultExampleFillColor,
kDefaultExampleOutlineColor, kDefaultExampleFontSize);
}
BEGIN_METADATA(WatermarkTextArea)
END_METADATA