Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/window/dialog_client_view.h" | |
| 6 | |
| 5 #include "base/macros.h" | 7 #include "base/macros.h" |
| 6 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 7 #include "build/build_config.h" | 9 #include "build/build_config.h" |
| 8 #include "ui/base/ui_base_types.h" | 10 #include "ui/base/ui_base_types.h" |
| 9 #include "ui/views/controls/button/label_button.h" | 11 #include "ui/views/controls/button/label_button.h" |
| 10 #include "ui/views/style/platform_style.h" | 12 #include "ui/views/style/platform_style.h" |
| 11 #include "ui/views/test/test_views.h" | 13 #include "ui/views/test/test_views.h" |
| 12 #include "ui/views/test/views_test_base.h" | 14 #include "ui/views/test/widget_test.h" |
| 13 #include "ui/views/widget/widget.h" | 15 #include "ui/views/widget/widget.h" |
| 14 #include "ui/views/window/dialog_client_view.h" | |
| 15 #include "ui/views/window/dialog_delegate.h" | 16 #include "ui/views/window/dialog_delegate.h" |
| 16 | 17 |
| 17 namespace views { | 18 namespace views { |
| 18 | 19 |
| 19 class TestDialogClientView : public DialogClientView { | 20 // Base class for tests. Also acts as the dialog delegate and contents view for |
| 21 // TestDialogClientView. | |
| 22 class DialogClientViewTest : public test::WidgetTest, | |
| 23 public DialogDelegateView { | |
| 20 public: | 24 public: |
| 21 explicit TestDialogClientView(DialogDelegateView* dialog_delegate_view) | 25 DialogClientViewTest() {} |
| 22 : DialogClientView(dialog_delegate_view), | |
| 23 dialog_delegate_view_(dialog_delegate_view) {} | |
| 24 ~TestDialogClientView() override {} | |
| 25 | 26 |
| 26 // DialogClientView implementation. | 27 // testing::Test: |
| 27 DialogDelegate* GetDialogDelegate() const override { | 28 void SetUp() override { |
| 28 return dialog_delegate_view_; | 29 WidgetTest::SetUp(); |
| 30 | |
| 31 // Note: not using DialogDelegate::CreateDialogWidget(..), since that can | |
| 32 // alter the frame type according to the platform. | |
| 33 widget_ = new views::Widget; | |
| 34 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 35 params.delegate = this; | |
| 36 widget_->Init(params); | |
| 37 EXPECT_EQ(this, GetContentsView()); | |
| 29 } | 38 } |
| 30 | 39 |
| 31 View* GetContentsView() { return contents_view(); } | 40 void TearDown() override { |
| 32 | 41 widget_->CloseNow(); |
| 33 void CreateExtraViews() { | 42 WidgetTest::TearDown(); |
| 34 CreateExtraView(); | |
| 35 } | 43 } |
| 36 | 44 |
| 37 private: | 45 // DialogDelegateView: |
| 38 DialogDelegateView* dialog_delegate_view_; | 46 ClientView* CreateClientView(Widget* widget) override { |
| 39 | 47 client_view_ = new DialogClientView(widget, this); |
| 40 DISALLOW_COPY_AND_ASSIGN(TestDialogClientView); | 48 return client_view_; |
| 41 }; | |
| 42 | |
| 43 // Base class for tests. Also acts as the dialog delegate and contents view for | |
| 44 // TestDialogClientView. | |
| 45 class DialogClientViewTest : public ViewsTestBase, | |
| 46 public DialogDelegateView { | |
| 47 public: | |
| 48 DialogClientViewTest() | |
| 49 : dialog_buttons_(ui::DIALOG_BUTTON_NONE), | |
| 50 extra_view_(nullptr) {} | |
| 51 ~DialogClientViewTest() override {} | |
| 52 | |
| 53 // testing::Test implementation. | |
| 54 void SetUp() override { | |
| 55 dialog_buttons_ = ui::DIALOG_BUTTON_NONE; | |
| 56 client_view_.reset(new TestDialogClientView(this)); | |
| 57 // Add this (i.e. the contents view) as a child of |client_view_|. This is | |
| 58 // generally done when the client view is added to the view hierarchy. | |
| 59 client_view_->AddChildViewAt(this, 0); | |
| 60 ViewsTestBase::SetUp(); | |
| 61 } | 49 } |
| 62 | 50 |
| 63 // DialogDelegateView implementation. | 51 bool ShouldUseCustomFrame() const override { return false; } |
| 64 View* CreateExtraView() override { return extra_view_; } | 52 |
| 53 void DeleteDelegate() override { | |
| 54 // DialogDelegateView would delete this, but |this| is owned by the test. | |
| 55 } | |
| 56 | |
| 57 View* CreateExtraView() override { return next_extra_view_.release(); } | |
| 58 | |
| 65 bool GetExtraViewPadding(int* padding) override { | 59 bool GetExtraViewPadding(int* padding) override { |
| 66 if (extra_view_padding_) | 60 if (extra_view_padding_) |
| 67 *padding = *extra_view_padding_; | 61 *padding = *extra_view_padding_; |
| 68 return extra_view_padding_.get() != nullptr; | 62 return extra_view_padding_.get() != nullptr; |
| 69 } | 63 } |
| 64 | |
| 70 int GetDialogButtons() const override { return dialog_buttons_; } | 65 int GetDialogButtons() const override { return dialog_buttons_; } |
| 71 | 66 |
| 72 protected: | 67 protected: |
| 73 gfx::Rect GetUpdatedClientBounds() { | 68 gfx::Rect GetUpdatedClientBounds() { |
| 74 client_view_->SizeToPreferredSize(); | 69 client_view_->SizeToPreferredSize(); |
| 75 client_view_->Layout(); | 70 client_view_->Layout(); |
| 76 return client_view_->bounds(); | 71 return client_view_->bounds(); |
| 77 } | 72 } |
| 78 | 73 |
| 79 // Makes sure that the content view is sized correctly. Width must be at least | 74 // Makes sure that the content view is sized correctly. Width must be at least |
| 80 // the requested amount, but height should always match exactly. | 75 // the requested amount, but height should always match exactly. |
| 81 void CheckContentsIsSetToPreferredSize() { | 76 void CheckContentsIsSetToPreferredSize() { |
| 82 const gfx::Rect client_bounds = GetUpdatedClientBounds(); | 77 const gfx::Rect client_bounds = GetUpdatedClientBounds(); |
| 83 const gfx::Size preferred_size = this->GetPreferredSize(); | 78 const gfx::Size preferred_size = this->GetPreferredSize(); |
| 84 EXPECT_EQ(preferred_size.height(), this->bounds().height()); | 79 EXPECT_EQ(preferred_size.height(), this->bounds().height()); |
| 85 EXPECT_LE(preferred_size.width(), this->bounds().width()); | 80 EXPECT_LE(preferred_size.width(), this->bounds().width()); |
| 86 EXPECT_EQ(this->origin(), client_bounds.origin()); | 81 EXPECT_EQ(gfx::Point(), this->origin()); |
| 87 EXPECT_EQ(this->bounds().right(), client_bounds.right()); | 82 EXPECT_EQ(client_bounds.width(), this->width()); |
|
tapted
2017/02/22 11:01:17
Using a Widget means it gets a NonClientFrameView,
| |
| 88 } | 83 } |
| 89 | 84 |
| 90 // Sets the buttons to show in the dialog and refreshes the dialog. | 85 // Sets the buttons to show in the dialog and refreshes the dialog. |
| 91 void SetDialogButtons(int dialog_buttons) { | 86 void SetDialogButtons(int dialog_buttons) { |
| 92 dialog_buttons_ = dialog_buttons; | 87 dialog_buttons_ = dialog_buttons; |
| 93 client_view_->UpdateDialogButtons(); | 88 client_view_->UpdateDialogButtons(); |
| 94 } | 89 } |
| 95 | 90 |
| 96 // Sets the extra view. | 91 // Sets the view to provide to CreateExtraView() and updates the dialog. This |
| 92 // can only be called a single time because DialogClientView caches the result | |
| 93 // of CreateExtraView() and never calls it again. | |
| 97 void SetExtraView(View* view) { | 94 void SetExtraView(View* view) { |
| 98 DCHECK(!extra_view_); | 95 EXPECT_FALSE(next_extra_view_); |
| 99 extra_view_ = view; | 96 next_extra_view_ = base::WrapUnique(view); |
| 100 client_view_->CreateExtraViews(); | 97 client_view_->UpdateDialogButtons(); |
| 98 EXPECT_FALSE(next_extra_view_); | |
| 101 } | 99 } |
| 102 | 100 |
| 103 // Sets the extra view padding. | 101 // Sets the extra view padding. |
| 104 void SetExtraViewPadding(int padding) { | 102 void SetExtraViewPadding(int padding) { |
| 105 DCHECK(!extra_view_padding_); | 103 DCHECK(!extra_view_padding_); |
| 106 extra_view_padding_.reset(new int(padding)); | 104 extra_view_padding_.reset(new int(padding)); |
| 107 client_view_->Layout(); | 105 client_view_->Layout(); |
| 108 } | 106 } |
| 109 | 107 |
| 110 TestDialogClientView* client_view() { return client_view_.get(); } | 108 View* FocusableViewAfter(View* view) { |
| 109 const bool dont_loop = false; | |
| 110 const bool reverse = false; | |
| 111 return GetFocusManager()->GetNextFocusableView(view, GetWidget(), reverse, | |
| 112 dont_loop); | |
| 113 } | |
| 114 | |
| 115 DialogClientView* client_view() { return client_view_; } | |
| 111 | 116 |
| 112 private: | 117 private: |
| 113 // The DialogClientView that's being tested. | 118 // The dialog Widget. |
| 114 std::unique_ptr<TestDialogClientView> client_view_; | 119 Widget* widget_ = nullptr; |
| 120 | |
| 121 // The DialogClientView that's being tested. Owned by |widget_|. | |
| 122 DialogClientView* client_view_; | |
| 123 | |
| 115 // The bitmask of buttons to show in the dialog. | 124 // The bitmask of buttons to show in the dialog. |
| 116 int dialog_buttons_; | 125 int dialog_buttons_ = ui::DIALOG_BUTTON_NONE; |
| 117 View* extra_view_; // weak | 126 |
| 118 std::unique_ptr<int> extra_view_padding_; // Null by default. | 127 // Set and cleared in SetExtraView(). |
| 128 std::unique_ptr<View> next_extra_view_; | |
| 129 | |
| 130 std::unique_ptr<int> extra_view_padding_; | |
| 119 | 131 |
| 120 DISALLOW_COPY_AND_ASSIGN(DialogClientViewTest); | 132 DISALLOW_COPY_AND_ASSIGN(DialogClientViewTest); |
| 121 }; | 133 }; |
| 122 | 134 |
| 123 TEST_F(DialogClientViewTest, UpdateButtons) { | 135 TEST_F(DialogClientViewTest, UpdateButtons) { |
| 124 // This dialog should start with no buttons. | 136 // This dialog should start with no buttons. |
| 125 EXPECT_EQ(GetDialogButtons(), ui::DIALOG_BUTTON_NONE); | 137 EXPECT_EQ(GetDialogButtons(), ui::DIALOG_BUTTON_NONE); |
| 126 EXPECT_EQ(NULL, client_view()->ok_button()); | 138 EXPECT_EQ(NULL, client_view()->ok_button()); |
| 127 EXPECT_EQ(NULL, client_view()->cancel_button()); | 139 EXPECT_EQ(NULL, client_view()->cancel_button()); |
| 128 const int height_without_buttons = GetUpdatedClientBounds().height(); | 140 const int height_without_buttons = GetUpdatedClientBounds().height(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 | 182 |
| 171 // Test that views inside the dialog client view have the correct focus order. | 183 // Test that views inside the dialog client view have the correct focus order. |
| 172 TEST_F(DialogClientViewTest, SetupFocusChain) { | 184 TEST_F(DialogClientViewTest, SetupFocusChain) { |
| 173 #if defined(OS_WIN) || defined(OS_CHROMEOS) | 185 #if defined(OS_WIN) || defined(OS_CHROMEOS) |
| 174 const bool kIsOkButtonOnLeftSide = true; | 186 const bool kIsOkButtonOnLeftSide = true; |
| 175 #else | 187 #else |
| 176 const bool kIsOkButtonOnLeftSide = false; | 188 const bool kIsOkButtonOnLeftSide = false; |
| 177 #endif | 189 #endif |
| 178 | 190 |
| 179 // Initially the dialog client view only contains the content view. | 191 // Initially the dialog client view only contains the content view. |
| 180 EXPECT_EQ(nullptr, client_view()->GetContentsView()->GetNextFocusableView()); | 192 EXPECT_EQ(nullptr, GetContentsView()->GetNextFocusableView()); |
| 181 | 193 |
| 182 // Add OK and cancel buttons. | 194 // Add OK and cancel buttons. |
| 183 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL); | 195 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL); |
| 184 | 196 |
| 185 if (kIsOkButtonOnLeftSide) { | 197 if (kIsOkButtonOnLeftSide) { |
| 186 EXPECT_EQ(client_view()->ok_button(), | 198 EXPECT_EQ(client_view()->ok_button(), |
| 187 client_view()->GetContentsView()->GetNextFocusableView()); | 199 GetContentsView()->GetNextFocusableView()); |
| 188 EXPECT_EQ(client_view()->cancel_button(), | 200 EXPECT_EQ(client_view()->cancel_button(), |
| 189 client_view()->ok_button()->GetNextFocusableView()); | 201 client_view()->ok_button()->GetNextFocusableView()); |
| 190 EXPECT_EQ(nullptr, client_view()->cancel_button()->GetNextFocusableView()); | 202 EXPECT_EQ(nullptr, client_view()->cancel_button()->GetNextFocusableView()); |
| 191 } else { | 203 } else { |
| 192 EXPECT_EQ(client_view()->cancel_button(), | 204 EXPECT_EQ(client_view()->cancel_button(), |
| 193 client_view()->GetContentsView()->GetNextFocusableView()); | 205 GetContentsView()->GetNextFocusableView()); |
| 194 EXPECT_EQ(client_view()->ok_button(), | 206 EXPECT_EQ(client_view()->ok_button(), |
| 195 client_view()->cancel_button()->GetNextFocusableView()); | 207 client_view()->cancel_button()->GetNextFocusableView()); |
| 196 EXPECT_EQ(nullptr, client_view()->ok_button()->GetNextFocusableView()); | 208 EXPECT_EQ(nullptr, client_view()->ok_button()->GetNextFocusableView()); |
| 197 } | 209 } |
| 198 | 210 |
| 199 // Add extra view and remove OK button. | 211 // Add extra view and remove OK button. |
| 200 View* extra_view = new StaticSizedView(gfx::Size(200, 200)); | 212 View* extra_view = new StaticSizedView(gfx::Size(200, 200)); |
| 213 extra_view->SetFocusBehavior(View::FocusBehavior::ALWAYS); | |
| 201 SetExtraView(extra_view); | 214 SetExtraView(extra_view); |
| 202 SetDialogButtons(ui::DIALOG_BUTTON_CANCEL); | 215 SetDialogButtons(ui::DIALOG_BUTTON_CANCEL); |
| 203 | 216 |
| 204 EXPECT_EQ(extra_view, | 217 EXPECT_EQ(extra_view, GetContentsView()->GetNextFocusableView()); |
| 205 client_view()->GetContentsView()->GetNextFocusableView()); | |
| 206 EXPECT_EQ(client_view()->cancel_button(), extra_view->GetNextFocusableView()); | 218 EXPECT_EQ(client_view()->cancel_button(), extra_view->GetNextFocusableView()); |
| 207 EXPECT_EQ(nullptr, client_view()->cancel_button()->GetNextFocusableView()); | 219 EXPECT_EQ(nullptr, client_view()->cancel_button()->GetNextFocusableView()); |
| 208 | 220 |
| 209 // Add a dummy view to the client view. | 221 // Add a dummy view to the contents view. Consult the FocusManager for the |
| 222 // traversal order since it now spans different levels of the view hierarchy. | |
| 210 View* dummy_view = new StaticSizedView(gfx::Size(200, 200)); | 223 View* dummy_view = new StaticSizedView(gfx::Size(200, 200)); |
| 211 client_view()->AddChildView(dummy_view); | 224 dummy_view->SetFocusBehavior(View::FocusBehavior::ALWAYS); |
| 212 EXPECT_EQ(dummy_view, client_view()->cancel_button()->GetNextFocusableView()); | 225 GetContentsView()->AddChildView(dummy_view); |
| 226 EXPECT_EQ(dummy_view, FocusableViewAfter(client_view()->cancel_button())); | |
| 227 EXPECT_EQ(extra_view, FocusableViewAfter(dummy_view)); | |
| 228 EXPECT_EQ(client_view()->cancel_button(), FocusableViewAfter(extra_view)); | |
| 229 | |
| 230 // Views are added to the contents view, not the client view, so the focus | |
| 231 // chain within the client view is not affected. | |
| 232 EXPECT_EQ(nullptr, client_view()->cancel_button()->GetNextFocusableView()); | |
| 213 } | 233 } |
| 214 | 234 |
| 215 // Test that the contents view gets its preferred size in the basic dialog | 235 // Test that the contents view gets its preferred size in the basic dialog |
| 216 // configuration. | 236 // configuration. |
| 217 TEST_F(DialogClientViewTest, ContentsSize) { | 237 TEST_F(DialogClientViewTest, ContentsSize) { |
| 218 CheckContentsIsSetToPreferredSize(); | 238 CheckContentsIsSetToPreferredSize(); |
| 219 EXPECT_EQ(GetContentsView()->bounds().bottom(), | 239 EXPECT_EQ(GetContentsView()->size(), client_view()->size()); |
| 220 client_view()->bounds().bottom()); | 240 // There's nothing in the contents view (i.e. |this|), so it should be 0x0. |
| 241 EXPECT_EQ(gfx::Size(), client_view()->size()); | |
|
tapted
2017/02/22 11:01:17
This fails for a similar reason (but also it's nev
| |
| 221 } | 242 } |
| 222 | 243 |
| 223 // Test the effect of the button strip on layout. | 244 // Test the effect of the button strip on layout. |
| 224 TEST_F(DialogClientViewTest, LayoutWithButtons) { | 245 TEST_F(DialogClientViewTest, LayoutWithButtons) { |
| 225 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL); | 246 SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL); |
| 226 CheckContentsIsSetToPreferredSize(); | 247 CheckContentsIsSetToPreferredSize(); |
| 227 | 248 |
| 228 EXPECT_LT(GetContentsView()->bounds().bottom(), | 249 EXPECT_LT(GetContentsView()->bounds().bottom(), |
| 229 client_view()->bounds().bottom()); | 250 client_view()->bounds().bottom()); |
| 230 gfx::Size no_extra_view_size = client_view()->bounds().size(); | 251 gfx::Size no_extra_view_size = client_view()->bounds().size(); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 248 EXPECT_EQ(no_extra_view_size.width(), client_view()->bounds().width()); | 269 EXPECT_EQ(no_extra_view_size.width(), client_view()->bounds().width()); |
| 249 | 270 |
| 250 // Try with a reduced-size dialog. | 271 // Try with a reduced-size dialog. |
| 251 extra_view->SetVisible(true); | 272 extra_view->SetVisible(true); |
| 252 client_view()->SetBoundsRect(gfx::Rect(gfx::Point(0, 0), no_extra_view_size)); | 273 client_view()->SetBoundsRect(gfx::Rect(gfx::Point(0, 0), no_extra_view_size)); |
| 253 client_view()->Layout(); | 274 client_view()->Layout(); |
| 254 EXPECT_GT(width_of_extra_view, extra_view->bounds().width()); | 275 EXPECT_GT(width_of_extra_view, extra_view->bounds().width()); |
| 255 } | 276 } |
| 256 | 277 |
| 257 } // namespace views | 278 } // namespace views |
| OLD | NEW |