Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / views / style / mac / dialog_button_border_mac_unittest.cc
blob3b8b30e883b7f4f21f588fa983de90de9495aab3
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/style/mac/dialog_button_border_mac.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "third_party/skia/include/core/SkCanvas.h"
9 #include "ui/compositor/canvas_painter.h"
10 #include "ui/gfx/canvas.h"
11 #include "ui/views/border.h"
12 #include "ui/views/controls/button/label_button.h"
13 #include "ui/views/test/views_test_base.h"
15 namespace views {
16 namespace {
18 // LabelButton that can optionally provide a custom border.
19 class TestLabelButton : public LabelButton {
20 public:
21 explicit TestLabelButton(const char* text)
22 : LabelButton(nullptr, base::ASCIIToUTF16(text)) {}
24 void SimulateAddToWidget() { OnNativeThemeChanged(nullptr); }
25 void set_provide_custom_border(bool value) { provide_custom_border_ = value; }
27 // LabelButton:
28 scoped_ptr<LabelButtonBorder> CreateDefaultBorder() const override {
29 if (!provide_custom_border_)
30 return LabelButton::CreateDefaultBorder();
32 return make_scoped_ptr(new LabelButtonAssetBorder(style()));
35 private:
36 bool provide_custom_border_ = false;
38 DISALLOW_COPY_AND_ASSIGN(TestLabelButton);
41 gfx::Size DialogButtonBorderMacSize() {
42 const DialogButtonBorderMac template_border;
43 return template_border.GetMinimumSize();
46 // A heuristic that tries to determine whether the border on |view| is a
47 // DialogButtonBorderMac by checking its minimum size.
48 bool BorderIsDialogButton(const View& view) {
49 const Border* border = view.border();
50 return border && DialogButtonBorderMacSize() == border->GetMinimumSize();
53 SkColor TestPaint(View* view) {
54 EXPECT_TRUE(view->visible());
55 EXPECT_FALSE(view->bounds().IsEmpty());
56 const gfx::Point center = view->bounds().CenterPoint();
57 gfx::Canvas canvas(view->bounds().size(), 1.0, false /* is_opaque */);
58 SkCanvas* sk_canvas = canvas.sk_canvas();
60 // Read a pixel - it should be blank.
61 SkColor initial_pixel;
62 SkBitmap bitmap;
63 bitmap.allocN32Pixels(1, 1);
64 EXPECT_TRUE(sk_canvas->readPixels(&bitmap, center.x(), center.y()));
65 initial_pixel = bitmap.getColor(0, 0);
66 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), initial_pixel);
68 view->Paint(ui::CanvasPainter(&canvas, 1.f).context());
70 // Ensure save()/restore() calls are balanced.
71 EXPECT_EQ(1, sk_canvas->getSaveCount());
73 // Ensure "something" happened. This assumes the border is a
74 // DialogButtonBorderMac, which always modifies the center pixel.
75 EXPECT_TRUE(sk_canvas->readPixels(&bitmap, center.x(), center.y()));
76 return bitmap.getColor(0, 0);
79 void TestPaintAllStates(CustomButton* button, bool verify) {
80 for (int i = 0; i < Button::STATE_COUNT; ++i) {
81 Button::ButtonState state = static_cast<Button::ButtonState>(i);
82 SCOPED_TRACE(testing::Message() << "Button::ButtonState: " << state);
83 button->SetState(state);
84 SkColor color = TestPaint(button);
85 if (verify)
86 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), color);
90 } // namespace
92 using DialogButtonBorderMacTest = ViewsTestBase;
94 // Verify that the DialogButtonBorderMac insets are consistent with the
95 // minimum size, and they're correctly carried across to the View's preferred
96 // size.
97 TEST_F(DialogButtonBorderMacTest, DrawMinimumSize) {
98 TestLabelButton button("");
99 button.SetStyle(Button::STYLE_BUTTON);
100 button.SimulateAddToWidget();
102 EXPECT_TRUE(BorderIsDialogButton(button));
104 // The border minimum size should be at least the size of the insets.
105 const gfx::Size border_min_size = DialogButtonBorderMacSize();
106 const gfx::Insets insets = button.GetInsets();
107 EXPECT_LE(insets.width(), border_min_size.width());
108 EXPECT_LE(insets.height(), border_min_size.height());
110 // The view preferred size should be at least as big as the border minimum.
111 gfx::Size view_preferred_size = button.GetPreferredSize();
112 EXPECT_LE(border_min_size.width(), view_preferred_size.width());
113 EXPECT_LE(border_min_size.height(), view_preferred_size.height());
115 // Calling SetStyle(STYLE_BUTTON) sets a default minimum height that is larger
116 // than the border minimum height. Override that to match the border.
117 button.SetMinSize(gfx::Size());
118 view_preferred_size = button.GetPreferredSize();
119 EXPECT_EQ(border_min_size.width(), view_preferred_size.width());
120 EXPECT_EQ(border_min_size.height(), view_preferred_size.height());
122 button.SizeToPreferredSize();
123 EXPECT_EQ(view_preferred_size.width(), button.width());
124 EXPECT_EQ(view_preferred_size.height(), button.height());
127 SCOPED_TRACE("Preferred Size");
128 TestPaintAllStates(&button, true);
131 // The View can ignore the border minimum size. To account for shadows, the
132 // border will paint something as small as 4x4.
134 SCOPED_TRACE("Minimum Paint Size");
135 button.SetSize(gfx::Size(4, 4));
136 TestPaintAllStates(&button, true);
139 // Smaller than that, nothing gets painted, but the paint code should be sane.
141 SCOPED_TRACE("Size 1x1");
142 button.SetSize(gfx::Size(1, 1));
143 TestPaintAllStates(&button, false);
147 // Test drawing with some text. The usual case.
148 TEST_F(DialogButtonBorderMacTest, DrawWithLabel) {
149 TestLabelButton button("Label Text That Exceeds the Minimum Button Size");
150 button.SetStyle(Button::STYLE_BUTTON);
151 button.SimulateAddToWidget();
153 EXPECT_TRUE(BorderIsDialogButton(button));
155 button.SetMinSize(gfx::Size());
156 button.SizeToPreferredSize();
158 // Long label, so the button width should be greater than in DrawMinimumSize.
159 const gfx::Size border_min_size = DialogButtonBorderMacSize();
160 EXPECT_LT(border_min_size.width(), button.width());
161 EXPECT_EQ(border_min_size.height(), button.height());
163 TestPaintAllStates(&button, true);
166 // Test that the themed style is not used for STYLE_TEXTBUTTON (the default), or
167 // when a custom Border is set, or when a LabelButton subclass provides its own
168 // default border.
169 TEST_F(DialogButtonBorderMacTest, ChecksButtonStyle) {
170 TestLabelButton button("");
171 button.SimulateAddToWidget();
173 // Default style is STYLE_TEXTBUTTON, which doesn't use the themed border.
174 EXPECT_FALSE(BorderIsDialogButton(button));
176 button.SetStyle(Button::STYLE_BUTTON);
177 button.SimulateAddToWidget();
178 EXPECT_TRUE(BorderIsDialogButton(button));
180 button.set_provide_custom_border(true);
181 button.SimulateAddToWidget();
182 EXPECT_FALSE(BorderIsDialogButton(button));
184 button.set_provide_custom_border(false);
185 button.SimulateAddToWidget();
186 EXPECT_TRUE(BorderIsDialogButton(button));
188 // Any call to SetBorder() will immediately prevent themed buttons and adding
189 // to a Widget (to pick up a NativeTheme) shouldn't restore them.
190 button.SetBorder(Border::NullBorder());
191 EXPECT_FALSE(BorderIsDialogButton(button));
192 button.SimulateAddToWidget();
193 EXPECT_FALSE(BorderIsDialogButton(button));
196 } // namespace views