// Copyright 2014 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/window/custom_frame_view.h" #include <vector> #include "ui/views/controls/button/image_button.h" #include "ui/views/test/views_test_base.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/window/window_button_order_provider.h" namespace views { namespace { // Allows for the control of whether or not the widget can maximize or not. // This can be set after initial setup in order to allow testing of both forms // of delegates. By default this can maximize. class MaximizeStateControlDelegate : public WidgetDelegateView { public: MaximizeStateControlDelegate() : can_maximize_(true) {} virtual ~MaximizeStateControlDelegate() {} void set_can_maximize(bool can_maximize) { can_maximize_ = can_maximize; } // WidgetDelegate: virtual bool CanMaximize() const OVERRIDE { return can_maximize_; } private: bool can_maximize_; DISALLOW_COPY_AND_ASSIGN(MaximizeStateControlDelegate); }; } // namespace class CustomFrameViewTest : public ViewsTestBase { public: CustomFrameViewTest() {} virtual ~CustomFrameViewTest() {} CustomFrameView* custom_frame_view() { return custom_frame_view_; } MaximizeStateControlDelegate* maximize_state_control_delegate() { return maximize_state_control_delegate_; } Widget* widget() { return widget_; } // ViewsTestBase: virtual void SetUp() OVERRIDE; virtual void TearDown() OVERRIDE; protected: const std::vector<views::FrameButton>& leading_buttons() { return WindowButtonOrderProvider::GetInstance()->leading_buttons(); } const std::vector<views::FrameButton>& trailing_buttons() { return WindowButtonOrderProvider::GetInstance()->trailing_buttons(); } ImageButton* minimize_button() { return custom_frame_view_->minimize_button_; } ImageButton* maximize_button() { return custom_frame_view_->maximize_button_; } ImageButton* restore_button() { return custom_frame_view_->restore_button_; } ImageButton* close_button() { return custom_frame_view_->close_button_; } gfx::Rect title_bounds() { return custom_frame_view_->title_bounds_; } void SetWindowButtonOrder( const std::vector<views::FrameButton> leading_buttons, const std::vector<views::FrameButton> trailing_buttons); private: // Parent container for |custom_frame_view_| Widget* widget_; // Owned by |widget_| CustomFrameView* custom_frame_view_; // Delegate of |widget_| which controls maximizing MaximizeStateControlDelegate* maximize_state_control_delegate_; DISALLOW_COPY_AND_ASSIGN(CustomFrameViewTest); }; void CustomFrameViewTest::SetUp() { ViewsTestBase::SetUp(); maximize_state_control_delegate_ = new MaximizeStateControlDelegate; widget_ = new Widget; Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); params.delegate = maximize_state_control_delegate_; params.remove_standard_frame = true; widget_->Init(params); custom_frame_view_ = new CustomFrameView; widget_->non_client_view()->SetFrameView(custom_frame_view_); } void CustomFrameViewTest::TearDown() { widget_->CloseNow(); ViewsTestBase::TearDown(); } void CustomFrameViewTest::SetWindowButtonOrder( const std::vector<views::FrameButton> leading_buttons, const std::vector<views::FrameButton> trailing_buttons) { WindowButtonOrderProvider::GetInstance()-> SetWindowButtonOrder(leading_buttons, trailing_buttons); } // Tests that there is a default button ordering before initialization causes // a configuration file check. TEST_F(CustomFrameViewTest, DefaultButtons) { const std::vector<views::FrameButton>& trailing = trailing_buttons(); EXPECT_EQ(trailing.size(), 3u); EXPECT_TRUE(leading_buttons().empty()); EXPECT_EQ(trailing[0], FRAME_BUTTON_MINIMIZE); EXPECT_EQ(trailing[1], FRAME_BUTTON_MAXIMIZE); EXPECT_EQ(trailing[2], FRAME_BUTTON_CLOSE); } // Tests that layout places the buttons in order, that the restore button is // hidden and the buttons are placed after the title. TEST_F(CustomFrameViewTest, DefaultButtonLayout) { Widget* parent = widget(); CustomFrameView* view = custom_frame_view(); view->Init(parent); parent->SetBounds(gfx::Rect(0, 0, 300, 100)); parent->Show(); EXPECT_LT(minimize_button()->x(), maximize_button()->x()); EXPECT_LT(maximize_button()->x(), close_button()->x()); EXPECT_FALSE(restore_button()->visible()); EXPECT_GT(minimize_button()->x(), title_bounds().x() + title_bounds().width()); } // Tests that setting the buttons to leading places them before the title. TEST_F(CustomFrameViewTest, LeadingButtonLayout) { Widget* parent = widget(); CustomFrameView* view = custom_frame_view(); std::vector<views::FrameButton> leading; leading.push_back(views::FRAME_BUTTON_CLOSE); leading.push_back(views::FRAME_BUTTON_MINIMIZE); leading.push_back(views::FRAME_BUTTON_MAXIMIZE); std::vector<views::FrameButton> trailing; SetWindowButtonOrder(leading, trailing); view->Init(parent); parent->SetBounds(gfx::Rect(0, 0, 300, 100)); parent->Show(); EXPECT_LT(close_button()->x(), minimize_button()->x()); EXPECT_LT(minimize_button()->x(), maximize_button()->x()); EXPECT_FALSE(restore_button()->visible()); EXPECT_LT(maximize_button()->x() + maximize_button()->width(), title_bounds().x()); } // Tests that layouts occuring while maximized swap the maximize button for the // restore button TEST_F(CustomFrameViewTest, MaximizeRevealsRestoreButton) { Widget* parent = widget(); CustomFrameView* view = custom_frame_view(); view->Init(parent); parent->SetBounds(gfx::Rect(0, 0, 300, 100)); parent->Show(); ASSERT_FALSE(restore_button()->visible()); ASSERT_TRUE(maximize_button()->visible()); parent->Maximize(); view->Layout(); EXPECT_TRUE(restore_button()->visible()); EXPECT_FALSE(maximize_button()->visible()); } // Tests that when the parent cannot maximize that the maximize button is not // visible TEST_F(CustomFrameViewTest, CannotMaximizeHidesButton) { Widget* parent = widget(); CustomFrameView* view = custom_frame_view(); MaximizeStateControlDelegate* delegate = maximize_state_control_delegate(); delegate->set_can_maximize(false); view->Init(parent); parent->SetBounds(gfx::Rect(0, 0, 300, 100)); parent->Show(); EXPECT_FALSE(restore_button()->visible()); EXPECT_FALSE(maximize_button()->visible()); } // Tests that when maximized that the edge button has an increased width. TEST_F(CustomFrameViewTest, LargerEdgeButtonsWhenMaximized) { Widget* parent = widget(); CustomFrameView* view = custom_frame_view(); // Custom ordering to have a button on each edge. std::vector<views::FrameButton> leading; leading.push_back(views::FRAME_BUTTON_CLOSE); leading.push_back(views::FRAME_BUTTON_MAXIMIZE); std::vector<views::FrameButton> trailing; trailing.push_back(views::FRAME_BUTTON_MINIMIZE); SetWindowButtonOrder(leading, trailing); view->Init(parent); parent->SetBounds(gfx::Rect(0, 0, 300, 100)); parent->Show(); gfx::Rect close_button_initial_bounds = close_button()->bounds(); gfx::Rect minimize_button_initial_bounds = minimize_button()->bounds(); parent->Maximize(); view->Layout(); EXPECT_GT(close_button()->bounds().width(), close_button_initial_bounds.width()); EXPECT_GT(minimize_button()->bounds().width(), minimize_button_initial_bounds.width()); } } // namespace views