- add sources.
[platform/framework/web/crosswalk.git] / src / ui / views / window / dialog_client_view_unittest.cc
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
3 // found in the LICENSE file.
4
5 #include "base/basictypes.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "ui/base/ui_base_types.h"
8 #include "ui/views/controls/button/label_button.h"
9 #include "ui/views/test/test_views.h"
10 #include "ui/views/test/views_test_base.h"
11 #include "ui/views/widget/widget.h"
12 #include "ui/views/window/dialog_client_view.h"
13 #include "ui/views/window/dialog_delegate.h"
14
15 namespace views {
16
17 class TestDialogClientView : public DialogClientView {
18  public:
19   TestDialogClientView(View* contents_view,
20                        DialogDelegate* dialog_delegate)
21       : DialogClientView(contents_view),
22         dialog_(dialog_delegate) {}
23   virtual ~TestDialogClientView() {}
24
25   // DialogClientView implementation.
26   virtual DialogDelegate* GetDialogDelegate() const OVERRIDE { return dialog_; }
27
28   View* GetContentsView() { return contents_view(); }
29
30   void CreateExtraViews() {
31     CreateExtraView();
32     CreateFootnoteView();
33   }
34
35  private:
36   DialogDelegate* dialog_;
37
38   DISALLOW_COPY_AND_ASSIGN(TestDialogClientView);
39 };
40
41 class DialogClientViewTest : public ViewsTestBase,
42                              public DialogDelegateView {
43  public:
44   DialogClientViewTest()
45       : dialog_buttons_(ui::DIALOG_BUTTON_NONE),
46         extra_view_(NULL),
47         footnote_view_(NULL) {}
48   virtual ~DialogClientViewTest() {}
49
50   // testing::Test implementation.
51   virtual void SetUp() OVERRIDE {
52     dialog_buttons_ = ui::DIALOG_BUTTON_NONE;
53     contents_.reset(new StaticSizedView(gfx::Size(100, 200)));
54     client_view_.reset(new TestDialogClientView(contents_.get(), this));
55
56     ViewsTestBase::SetUp();
57   }
58
59   // DialogDelegateView implementation.
60   virtual View* GetContentsView() OVERRIDE { return contents_.get(); }
61   virtual View* CreateExtraView() OVERRIDE { return extra_view_; }
62   virtual View* CreateFootnoteView() OVERRIDE { return footnote_view_; }
63   virtual int GetDialogButtons() const OVERRIDE { return dialog_buttons_; }
64
65  protected:
66   gfx::Rect GetUpdatedClientBounds() {
67     client_view_->SizeToPreferredSize();
68     client_view_->Layout();
69     return client_view_->bounds();
70   }
71
72   // Makes sure that the content view is sized correctly. Width must be at least
73   // the requested amount, but height should always match exactly.
74   void CheckContentsIsSetToPreferredSize() {
75     const gfx::Rect client_bounds = GetUpdatedClientBounds();
76     const gfx::Size preferred_size = contents_->GetPreferredSize();
77     EXPECT_EQ(preferred_size.height(), contents_->bounds().height());
78     EXPECT_LE(preferred_size.width(), contents_->bounds().width());
79     EXPECT_EQ(contents_->bounds().origin(), client_bounds.origin());
80     EXPECT_EQ(contents_->bounds().right(), client_bounds.right());
81   }
82
83   // Sets the buttons to show in the dialog and refreshes the dialog.
84   void SetDialogButtons(int dialog_buttons) {
85     dialog_buttons_ = dialog_buttons;
86     client_view_->UpdateDialogButtons();
87   }
88
89   // Sets the extra view.
90   void SetExtraView(View* view) {
91     DCHECK(!extra_view_);
92     extra_view_ = view;
93     client_view_->CreateExtraViews();
94   }
95
96   // Sets the footnote view.
97   void SetFootnoteView(View* view) {
98     DCHECK(!footnote_view_);
99     footnote_view_ = view;
100     client_view_->CreateExtraViews();
101   }
102
103   TestDialogClientView* client_view() { return client_view_.get(); }
104
105  private:
106   // The contents of the dialog.
107   scoped_ptr<View> contents_;
108   // The DialogClientView that's being tested.
109   scoped_ptr<TestDialogClientView> client_view_;
110   // The bitmask of buttons to show in the dialog.
111   int dialog_buttons_;
112   View* extra_view_;  // weak
113   View* footnote_view_;  // weak
114
115   DISALLOW_COPY_AND_ASSIGN(DialogClientViewTest);
116 };
117
118 TEST_F(DialogClientViewTest, UpdateButtons) {
119   // This dialog should start with no buttons.
120   EXPECT_EQ(GetDialogButtons(), ui::DIALOG_BUTTON_NONE);
121   EXPECT_EQ(NULL, client_view()->ok_button());
122   EXPECT_EQ(NULL, client_view()->cancel_button());
123   const int height_without_buttons = GetUpdatedClientBounds().height();
124
125   // Update to use both buttons.
126   SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
127   EXPECT_TRUE(client_view()->ok_button()->is_default());
128   EXPECT_FALSE(client_view()->cancel_button()->is_default());
129   const int height_with_buttons = GetUpdatedClientBounds().height();
130   EXPECT_GT(height_with_buttons, height_without_buttons);
131
132   // Remove the dialog buttons.
133   SetDialogButtons(ui::DIALOG_BUTTON_NONE);
134   EXPECT_EQ(NULL, client_view()->ok_button());
135   EXPECT_EQ(NULL, client_view()->cancel_button());
136   EXPECT_EQ(GetUpdatedClientBounds().height(), height_without_buttons);
137
138   // Reset with just an ok button.
139   SetDialogButtons(ui::DIALOG_BUTTON_OK);
140   EXPECT_TRUE(client_view()->ok_button()->is_default());
141   EXPECT_EQ(NULL, client_view()->cancel_button());
142   EXPECT_EQ(GetUpdatedClientBounds().height(), height_with_buttons);
143
144   // Reset with just a cancel button.
145   SetDialogButtons(ui::DIALOG_BUTTON_CANCEL);
146   EXPECT_EQ(NULL, client_view()->ok_button());
147   EXPECT_TRUE(client_view()->cancel_button()->is_default());
148   EXPECT_EQ(GetUpdatedClientBounds().height(), height_with_buttons);
149 }
150
151 TEST_F(DialogClientViewTest, RemoveAndUpdateButtons) {
152   // Removing buttons from another context should clear the local pointer.
153   SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
154   delete client_view()->ok_button();
155   EXPECT_EQ(NULL, client_view()->ok_button());
156   delete client_view()->cancel_button();
157   EXPECT_EQ(NULL, client_view()->cancel_button());
158
159   // Updating should restore the requested buttons properly.
160   SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
161   EXPECT_TRUE(client_view()->ok_button()->is_default());
162   EXPECT_FALSE(client_view()->cancel_button()->is_default());
163 }
164
165 // Test that the contents view gets its preferred size in the basic dialog
166 // configuration.
167 TEST_F(DialogClientViewTest, ContentsSize) {
168   CheckContentsIsSetToPreferredSize();
169   EXPECT_EQ(GetContentsView()->bounds().bottom(),
170             client_view()->bounds().bottom());
171 }
172
173 // Test the effect of the button strip on layout.
174 TEST_F(DialogClientViewTest, LayoutWithButtons) {
175   SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
176   CheckContentsIsSetToPreferredSize();
177   EXPECT_LT(GetContentsView()->bounds().bottom(),
178             client_view()->bounds().bottom());
179   gfx::Size no_extra_view_size = client_view()->bounds().size();
180
181   View* extra_view = new StaticSizedView(gfx::Size(200, 200));
182   SetExtraView(extra_view);
183   CheckContentsIsSetToPreferredSize();
184   EXPECT_GT(client_view()->bounds().height(), no_extra_view_size.height());
185   int width_of_extra_view = extra_view->bounds().width();
186
187   // Visibility of extra view is respected.
188   extra_view->SetVisible(false);
189   CheckContentsIsSetToPreferredSize();
190   EXPECT_EQ(no_extra_view_size.height(), client_view()->bounds().height());
191   EXPECT_EQ(no_extra_view_size.width(), client_view()->bounds().width());
192
193   // Try with a reduced-size dialog.
194   extra_view->SetVisible(true);
195   client_view()->SetBoundsRect(gfx::Rect(gfx::Point(0, 0), no_extra_view_size));
196   client_view()->Layout();
197   DCHECK_GT(width_of_extra_view, extra_view->bounds().width());
198 }
199
200 // Test the effect of the footnote view on layout.
201 TEST_F(DialogClientViewTest, LayoutWithFootnote) {
202   CheckContentsIsSetToPreferredSize();
203   gfx::Size no_footnote_size = client_view()->bounds().size();
204
205   View* footnote_view = new StaticSizedView(gfx::Size(200, 200));
206   SetFootnoteView(footnote_view);
207   CheckContentsIsSetToPreferredSize();
208   EXPECT_GT(client_view()->bounds().height(), no_footnote_size.height());
209   EXPECT_EQ(200, footnote_view->bounds().height());
210   gfx::Size with_footnote_size = client_view()->bounds().size();
211   EXPECT_EQ(with_footnote_size.width(), footnote_view->bounds().width());
212
213   SetDialogButtons(ui::DIALOG_BUTTON_CANCEL);
214   CheckContentsIsSetToPreferredSize();
215   EXPECT_LE(with_footnote_size.height(), client_view()->bounds().height());
216   EXPECT_LE(with_footnote_size.width(), client_view()->bounds().width());
217   gfx::Size with_footnote_and_button_size = client_view()->bounds().size();
218
219   SetDialogButtons(ui::DIALOG_BUTTON_NONE);
220   footnote_view->SetVisible(false);
221   CheckContentsIsSetToPreferredSize();
222   EXPECT_EQ(no_footnote_size.height(), client_view()->bounds().height());
223   EXPECT_EQ(no_footnote_size.width(), client_view()->bounds().width());
224 }
225
226 // Test that GetHeightForWidth is respected for the footnote view.
227 TEST_F(DialogClientViewTest, LayoutWithFootnoteHeightForWidth) {
228   CheckContentsIsSetToPreferredSize();
229   gfx::Size no_footnote_size = client_view()->bounds().size();
230
231   View* footnote_view = new ProportionallySizedView(3);
232   SetFootnoteView(footnote_view);
233   CheckContentsIsSetToPreferredSize();
234   EXPECT_GT(client_view()->bounds().height(), no_footnote_size.height());
235   EXPECT_EQ(footnote_view->bounds().width() * 3,
236             footnote_view->bounds().height());
237 }
238
239 // Test that the DialogClientView's FocusManager is properly updated when the
240 // DialogClientView belongs to a non top level widget and the widget is
241 // reparented. The DialogClientView belongs to a non top level widget in the
242 // case of constrained windows. The constrained window's widget is reparented
243 // when a browser tab is dragged to a different browser window.
244 TEST_F(DialogClientViewTest, FocusManager) {
245   scoped_ptr<Widget> toplevel1(new Widget);
246   Widget::InitParams toplevel1_params =
247       CreateParams(Widget::InitParams::TYPE_WINDOW);
248   toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
249   toplevel1->Init(toplevel1_params);
250
251   scoped_ptr<Widget> toplevel2(new Widget);
252   Widget::InitParams toplevel2_params =
253       CreateParams(Widget::InitParams::TYPE_WINDOW);
254   toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
255   toplevel2->Init(toplevel2_params);
256
257   Widget* dialog = new Widget;
258   Widget::InitParams dialog_params =
259       CreateParams(Widget::InitParams::TYPE_WINDOW);
260   dialog_params.child = true;
261   dialog_params.delegate = new DialogDelegateView();
262   dialog_params.parent = toplevel1->GetNativeView();
263   dialog->Init(dialog_params);
264
265   // Test that the FocusManager has been properly set when the DialogClientView
266   // was parented to |dialog|.
267   DialogClientView* client_view =
268       static_cast<DialogClientView*>(dialog->client_view());
269   EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_);
270
271   // Test that the FocusManager is properly updated when the DialogClientView's
272   // top level widget is changed.
273   Widget::ReparentNativeView(dialog->GetNativeView(), NULL);
274   EXPECT_EQ(NULL, client_view->focus_manager_);
275   Widget::ReparentNativeView(dialog->GetNativeView(),
276                              toplevel2->GetNativeView());
277   EXPECT_EQ(toplevel2->GetFocusManager(), client_view->focus_manager_);
278   Widget::ReparentNativeView(dialog->GetNativeView(),
279                              toplevel1->GetNativeView());
280   EXPECT_NE(toplevel1->GetFocusManager(), toplevel2->GetFocusManager());
281   EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_);
282
283   // Test that the FocusManager is properly cleared when the DialogClientView is
284   // removed from |dialog| during the widget's destruction.
285   client_view->set_owned_by_client();
286   scoped_ptr<DialogClientView> owned_client_view(client_view);
287   toplevel1->CloseNow();
288   toplevel2->CloseNow();
289   EXPECT_EQ(NULL, owned_client_view->focus_manager_);
290 }
291
292 }  // namespace views