1 // Copyright 2014 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. 4 5 #include "ui/views/window/custom_frame_view.h" 6 7 #include <vector> 8 9 #include "ui/views/controls/button/image_button.h" 10 #include "ui/views/test/views_test_base.h" 11 #include "ui/views/widget/widget.h" 12 #include "ui/views/widget/widget_delegate.h" 13 #include "ui/views/window/window_button_order_provider.h" 14 15 namespace views { 16 17 namespace { 18 19 // Allows for the control of whether or not the widget can minimize/maximize or 20 // not. This can be set after initial setup in order to allow testing of both 21 // forms of delegates. By default this can minimize and maximize. 22 class MinimizeAndMaximizeStateControlDelegate : public WidgetDelegateView { 23 public: 24 MinimizeAndMaximizeStateControlDelegate() 25 : can_maximize_(true), 26 can_minimize_(true) {} 27 virtual ~MinimizeAndMaximizeStateControlDelegate() {} 28 29 void set_can_maximize(bool can_maximize) { 30 can_maximize_ = can_maximize; 31 } 32 33 void set_can_minimize(bool can_minimize) { 34 can_minimize_ = can_minimize; 35 } 36 37 // WidgetDelegate: 38 virtual bool CanMaximize() const OVERRIDE { return can_maximize_; } 39 virtual bool CanMinimize() const OVERRIDE { return can_minimize_; } 40 41 private: 42 bool can_maximize_; 43 bool can_minimize_; 44 45 DISALLOW_COPY_AND_ASSIGN(MinimizeAndMaximizeStateControlDelegate); 46 }; 47 48 } // namespace 49 50 class CustomFrameViewTest : public ViewsTestBase { 51 public: 52 CustomFrameViewTest() {} 53 virtual ~CustomFrameViewTest() {} 54 55 CustomFrameView* custom_frame_view() { 56 return custom_frame_view_; 57 } 58 59 MinimizeAndMaximizeStateControlDelegate* 60 minimize_and_maximize_state_control_delegate() { 61 return minimize_and_maximize_state_control_delegate_; 62 } 63 64 Widget* widget() { 65 return widget_; 66 } 67 68 // ViewsTestBase: 69 virtual void SetUp() OVERRIDE; 70 virtual void TearDown() OVERRIDE; 71 72 protected: 73 const std::vector<views::FrameButton>& leading_buttons() { 74 return WindowButtonOrderProvider::GetInstance()->leading_buttons(); 75 } 76 77 const std::vector<views::FrameButton>& trailing_buttons() { 78 return WindowButtonOrderProvider::GetInstance()->trailing_buttons(); 79 } 80 81 ImageButton* minimize_button() { 82 return custom_frame_view_->minimize_button_; 83 } 84 85 ImageButton* maximize_button() { 86 return custom_frame_view_->maximize_button_; 87 } 88 89 ImageButton* restore_button() { 90 return custom_frame_view_->restore_button_; 91 } 92 93 ImageButton* close_button() { 94 return custom_frame_view_->close_button_; 95 } 96 97 gfx::Rect title_bounds() { 98 return custom_frame_view_->title_bounds_; 99 } 100 101 void SetWindowButtonOrder( 102 const std::vector<views::FrameButton> leading_buttons, 103 const std::vector<views::FrameButton> trailing_buttons); 104 105 private: 106 // Parent container for |custom_frame_view_| 107 Widget* widget_; 108 109 // Owned by |widget_| 110 CustomFrameView* custom_frame_view_; 111 112 // Delegate of |widget_| which controls minimizing and maximizing 113 MinimizeAndMaximizeStateControlDelegate* 114 minimize_and_maximize_state_control_delegate_; 115 116 DISALLOW_COPY_AND_ASSIGN(CustomFrameViewTest); 117 }; 118 119 void CustomFrameViewTest::SetUp() { 120 ViewsTestBase::SetUp(); 121 122 minimize_and_maximize_state_control_delegate_ = 123 new MinimizeAndMaximizeStateControlDelegate; 124 widget_ = new Widget; 125 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); 126 params.delegate = minimize_and_maximize_state_control_delegate_; 127 params.remove_standard_frame = true; 128 widget_->Init(params); 129 130 custom_frame_view_ = new CustomFrameView; 131 widget_->non_client_view()->SetFrameView(custom_frame_view_); 132 } 133 134 void CustomFrameViewTest::TearDown() { 135 widget_->CloseNow(); 136 137 ViewsTestBase::TearDown(); 138 } 139 140 void CustomFrameViewTest::SetWindowButtonOrder( 141 const std::vector<views::FrameButton> leading_buttons, 142 const std::vector<views::FrameButton> trailing_buttons) { 143 WindowButtonOrderProvider::GetInstance()-> 144 SetWindowButtonOrder(leading_buttons, trailing_buttons); 145 } 146 147 // Tests that there is a default button ordering before initialization causes 148 // a configuration file check. 149 TEST_F(CustomFrameViewTest, DefaultButtons) { 150 const std::vector<views::FrameButton>& trailing = trailing_buttons(); 151 EXPECT_EQ(trailing.size(), 3u); 152 EXPECT_TRUE(leading_buttons().empty()); 153 EXPECT_EQ(trailing[0], FRAME_BUTTON_MINIMIZE); 154 EXPECT_EQ(trailing[1], FRAME_BUTTON_MAXIMIZE); 155 EXPECT_EQ(trailing[2], FRAME_BUTTON_CLOSE); 156 } 157 158 // Tests that layout places the buttons in order, that the restore button is 159 // hidden and the buttons are placed after the title. 160 TEST_F(CustomFrameViewTest, DefaultButtonLayout) { 161 Widget* parent = widget(); 162 CustomFrameView* view = custom_frame_view(); 163 view->Init(parent); 164 parent->SetBounds(gfx::Rect(0, 0, 300, 100)); 165 parent->Show(); 166 167 EXPECT_LT(minimize_button()->x(), maximize_button()->x()); 168 EXPECT_LT(maximize_button()->x(), close_button()->x()); 169 EXPECT_FALSE(restore_button()->visible()); 170 171 EXPECT_GT(minimize_button()->x(), 172 title_bounds().x() + title_bounds().width()); 173 } 174 175 // Tests that setting the buttons to leading places them before the title. 176 TEST_F(CustomFrameViewTest, LeadingButtonLayout) { 177 Widget* parent = widget(); 178 CustomFrameView* view = custom_frame_view(); 179 180 std::vector<views::FrameButton> leading; 181 leading.push_back(views::FRAME_BUTTON_CLOSE); 182 leading.push_back(views::FRAME_BUTTON_MINIMIZE); 183 leading.push_back(views::FRAME_BUTTON_MAXIMIZE); 184 185 std::vector<views::FrameButton> trailing; 186 187 SetWindowButtonOrder(leading, trailing); 188 189 view->Init(parent); 190 parent->SetBounds(gfx::Rect(0, 0, 300, 100)); 191 parent->Show(); 192 EXPECT_LT(close_button()->x(), minimize_button()->x()); 193 EXPECT_LT(minimize_button()->x(), maximize_button()->x()); 194 EXPECT_FALSE(restore_button()->visible()); 195 EXPECT_LT(maximize_button()->x() + maximize_button()->width(), 196 title_bounds().x()); 197 } 198 199 // Tests that layouts occuring while maximized swap the maximize button for the 200 // restore button 201 TEST_F(CustomFrameViewTest, MaximizeRevealsRestoreButton) { 202 Widget* parent = widget(); 203 CustomFrameView* view = custom_frame_view(); 204 view->Init(parent); 205 parent->SetBounds(gfx::Rect(0, 0, 300, 100)); 206 parent->Show(); 207 208 ASSERT_FALSE(restore_button()->visible()); 209 ASSERT_TRUE(maximize_button()->visible()); 210 211 parent->Maximize(); 212 view->Layout(); 213 214 EXPECT_TRUE(restore_button()->visible()); 215 EXPECT_FALSE(maximize_button()->visible()); 216 } 217 218 // Tests that when the parent cannot maximize that the maximize button is not 219 // visible 220 TEST_F(CustomFrameViewTest, CannotMaximizeHidesButton) { 221 Widget* parent = widget(); 222 CustomFrameView* view = custom_frame_view(); 223 MinimizeAndMaximizeStateControlDelegate* delegate = 224 minimize_and_maximize_state_control_delegate(); 225 delegate->set_can_maximize(false); 226 227 view->Init(parent); 228 parent->SetBounds(gfx::Rect(0, 0, 300, 100)); 229 parent->Show(); 230 231 EXPECT_FALSE(restore_button()->visible()); 232 EXPECT_FALSE(maximize_button()->visible()); 233 } 234 235 // Tests that when the parent cannot minimize that the minimize button is not 236 // visible 237 TEST_F(CustomFrameViewTest, CannotMinimizeHidesButton) { 238 Widget* parent = widget(); 239 CustomFrameView* view = custom_frame_view(); 240 MinimizeAndMaximizeStateControlDelegate* delegate = 241 minimize_and_maximize_state_control_delegate(); 242 delegate->set_can_minimize(false); 243 244 view->Init(parent); 245 parent->SetBounds(gfx::Rect(0, 0, 300, 100)); 246 parent->Show(); 247 248 EXPECT_FALSE(minimize_button()->visible()); 249 } 250 251 // Tests that when maximized that the edge button has an increased width. 252 TEST_F(CustomFrameViewTest, LargerEdgeButtonsWhenMaximized) { 253 Widget* parent = widget(); 254 CustomFrameView* view = custom_frame_view(); 255 256 // Custom ordering to have a button on each edge. 257 std::vector<views::FrameButton> leading; 258 leading.push_back(views::FRAME_BUTTON_CLOSE); 259 leading.push_back(views::FRAME_BUTTON_MAXIMIZE); 260 std::vector<views::FrameButton> trailing; 261 trailing.push_back(views::FRAME_BUTTON_MINIMIZE); 262 SetWindowButtonOrder(leading, trailing); 263 264 view->Init(parent); 265 parent->SetBounds(gfx::Rect(0, 0, 300, 100)); 266 parent->Show(); 267 268 gfx::Rect close_button_initial_bounds = close_button()->bounds(); 269 gfx::Rect minimize_button_initial_bounds = minimize_button()->bounds(); 270 271 parent->Maximize(); 272 view->Layout(); 273 274 EXPECT_GT(close_button()->bounds().width(), 275 close_button_initial_bounds.width()); 276 EXPECT_GT(minimize_button()->bounds().width(), 277 minimize_button_initial_bounds.width()); 278 } 279 280 } // namespace views 281