| // 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 |