Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / gtk_chrome_shrinkable_hbox_unittest.cc
1 // Copyright (c) 2011 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 "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
6
7 #include <vector>
8
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace {
12
13 const int kSpacing = 3;
14 const int kBorderWidth = 5;
15
16 }  // namespace
17
18 class GtkChromeShrinkableHBoxTest : public testing::Test {
19  protected:
20   GtkChromeShrinkableHBoxTest()
21       : window_(gtk_window_new(GTK_WINDOW_TOPLEVEL)),
22         box_(gtk_chrome_shrinkable_hbox_new(FALSE, FALSE, kSpacing)) {
23     gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
24     gtk_window_set_default_size(GTK_WINDOW(window_), 200, 200);
25     gtk_container_add(GTK_CONTAINER(window_), box_);
26     gtk_container_set_border_width(GTK_CONTAINER(box_), kBorderWidth);
27   }
28
29   virtual ~GtkChromeShrinkableHBoxTest() {
30     gtk_widget_destroy(window_);
31   }
32
33   // Add some children widgets with arbitrary width and padding.
34   void AddChildren(bool pack_start) {
35     static struct {
36       int width;
37       int padding;
38     } kChildrenData[] = {
39       { 60, 2 },
40       { 70, 3 },
41       { 80, 5 },
42       { 50, 7 },
43       { 40, 11 },
44       { 60, 0 },
45       { 0, 0 }
46     };
47
48     for (size_t i = 0; kChildrenData[i].width; ++i) {
49       GtkWidget* child = gtk_fixed_new();
50       gtk_widget_set_size_request(child, kChildrenData[i].width, -1);
51       if (pack_start) {
52         gtk_chrome_shrinkable_hbox_pack_start(
53             GTK_CHROME_SHRINKABLE_HBOX(box_), child, kChildrenData[i].padding);
54       } else {
55         gtk_chrome_shrinkable_hbox_pack_end(
56             GTK_CHROME_SHRINKABLE_HBOX(box_), child, kChildrenData[i].padding);
57       }
58     }
59   }
60
61   // Check if all children's size allocation are inside the |box_|'s boundary.
62   void Validate(bool pack_start) {
63     std::vector<ChildData> children_data;
64     gtk_container_foreach(GTK_CONTAINER(box_), CollectChildData,
65                           &children_data);
66
67     size_t children_count = children_data.size();
68     size_t visible_children_count = 0;
69     for (size_t i = 0; i < children_count; ++i) {
70       if (children_data[i].visible)
71         ++visible_children_count;
72     }
73
74     if (visible_children_count == 0)
75       return;
76
77     int border_width = gtk_container_get_border_width(GTK_CONTAINER(box_));
78     int x = box_->allocation.x + border_width;
79     int width = box_->allocation.width - border_width * 2;
80     int spacing = gtk_box_get_spacing(GTK_BOX(box_));
81     bool homogeneous = gtk_box_get_homogeneous(GTK_BOX(box_));
82
83     if (homogeneous) {
84       // If the |box_| is in homogeneous mode, then check if the visible
85       // children are not overlapped with each other.
86       int homogeneous_child_width =
87           (width - (visible_children_count - 1) * spacing) /
88           visible_children_count;
89
90       for (size_t i = 0; i < children_count; ++i) {
91         SCOPED_TRACE(testing::Message() << "Validate homogeneous child " << i
92                      << " visible: " << children_data[i].visible
93                      << " padding: " << children_data[i].padding
94                      << " x: " << children_data[i].x
95                      << " width: " << children_data[i].width);
96
97         if (children_data[i].visible)
98           ASSERT_LE(children_data[i].width, homogeneous_child_width);
99       }
100     } else {
101       // If the |box_| is not in homogeneous mode, then just check if all
102       // visible children are inside the |box_|'s boundary. And for those
103       // hidden children which are out of the boundary, they should only
104       // be hidden one by one from the end of the |box_|.
105       bool last_visible = pack_start;
106       bool visibility_changed = false;
107       for (size_t i = 0; i < children_count; ++i) {
108         SCOPED_TRACE(testing::Message() << "Validate child " << i
109                      << " visible: " << children_data[i].visible
110                      << " padding: " << children_data[i].padding
111                      << " x: " << children_data[i].x
112                      << " width: " << children_data[i].width);
113
114         if (last_visible != children_data[i].visible) {
115           ASSERT_FALSE(visibility_changed);
116           visibility_changed = true;
117           last_visible = children_data[i].visible;
118         }
119         if (children_data[i].visible) {
120           ASSERT_GE(children_data[i].x,
121                     x + children_data[i].padding);
122           ASSERT_LE(children_data[i].x + children_data[i].width,
123                     x + width - children_data[i].padding);
124         }
125       }
126     }
127   }
128
129   void Test(bool pack_start) {
130     gtk_widget_show_all(window_);
131     GtkAllocation allocation = { 0, 0, 0, 200 };
132     gtk_chrome_shrinkable_hbox_set_hide_child_directly(
133         GTK_CHROME_SHRINKABLE_HBOX(box_), FALSE);
134     for (int width = 500; width > kBorderWidth * 2; --width) {
135       SCOPED_TRACE(testing::Message() << "Shrink hide_child_directly = FALSE,"
136                    << " width = " << width);
137
138       allocation.width = width;
139       // Reducing the width may cause some children to be hidden, which will
140       // cause queue resize, so it's necessary to do another size allocation to
141       // emulate the queue resize.
142       gtk_widget_size_allocate(box_, &allocation);
143       gtk_widget_size_allocate(box_, &allocation);
144       ASSERT_NO_FATAL_FAILURE(Validate(pack_start)) << "width = " << width;
145     }
146
147     for (int width = kBorderWidth * 2; width <= 500; ++width) {
148       SCOPED_TRACE(testing::Message() << "Expand hide_child_directly = FALSE,"
149                    << " width = " << width);
150
151       allocation.width = width;
152       // Expanding the width may cause some invisible children to be shown,
153       // which will cause queue resize, so it's necessary to do another size
154       // allocation to emulate the queue resize.
155       gtk_widget_size_allocate(box_, &allocation);
156       gtk_widget_size_allocate(box_, &allocation);
157       ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
158     }
159
160     gtk_chrome_shrinkable_hbox_set_hide_child_directly(
161         GTK_CHROME_SHRINKABLE_HBOX(box_), TRUE);
162     for (int width = 500; width > kBorderWidth * 2; --width) {
163       SCOPED_TRACE(testing::Message() << "Shrink hide_child_directly = TRUE,"
164                    << " width = " << width);
165
166       allocation.width = width;
167       gtk_widget_size_allocate(box_, &allocation);
168       gtk_widget_size_allocate(box_, &allocation);
169       ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
170     }
171
172     for (int width = kBorderWidth * 2; width <= 500; ++width) {
173       SCOPED_TRACE(testing::Message() << "Expand hide_child_directly = TRUE,"
174                    << " width = " << width);
175
176       allocation.width = width;
177       gtk_widget_size_allocate(box_, &allocation);
178       gtk_widget_size_allocate(box_, &allocation);
179       ASSERT_NO_FATAL_FAILURE(Validate(pack_start));
180     }
181   }
182
183  protected:
184   GtkWidget* window_;
185   GtkWidget* box_;
186
187  private:
188   struct ChildData {
189     bool visible;
190     int padding;
191     int x;
192     int width;
193   };
194
195   static void CollectChildData(GtkWidget* child, gpointer userdata) {
196     guint padding;
197     gtk_box_query_child_packing(GTK_BOX(gtk_widget_get_parent(child)), child,
198                                 NULL, NULL, &padding, NULL);
199
200     ChildData data;
201     data.visible = gtk_widget_get_visible(child);
202     data.padding = padding;
203     data.x = child->allocation.x;
204     data.width = child->allocation.width;
205
206     reinterpret_cast<std::vector<ChildData>*>(userdata)->push_back(data);
207   }
208 };
209
210 TEST_F(GtkChromeShrinkableHBoxTest, PackStart) {
211   AddChildren(true);
212
213   {
214     SCOPED_TRACE("Test LTR");
215     gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
216     EXPECT_NO_FATAL_FAILURE(Test(true));
217   }
218   {
219     SCOPED_TRACE("Test RTL");
220     gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
221     EXPECT_NO_FATAL_FAILURE(Test(true));
222   }
223 }
224
225 TEST_F(GtkChromeShrinkableHBoxTest, PackEnd) {
226   AddChildren(false);
227
228   {
229     SCOPED_TRACE("Test LTR");
230     gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
231     EXPECT_NO_FATAL_FAILURE(Test(false));
232   }
233   {
234     SCOPED_TRACE("Test RTL");
235     gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
236     EXPECT_NO_FATAL_FAILURE(Test(false));
237   }
238 }
239
240 TEST_F(GtkChromeShrinkableHBoxTest, Homogeneous) {
241   AddChildren(true);
242   gtk_box_set_homogeneous(GTK_BOX(box_), true);
243
244   {
245     SCOPED_TRACE("Test LTR");
246     gtk_widget_set_direction(box_, GTK_TEXT_DIR_LTR);
247     EXPECT_NO_FATAL_FAILURE(Test(true));
248   }
249   {
250     SCOPED_TRACE("Test RTL");
251     gtk_widget_set_direction(box_, GTK_TEXT_DIR_RTL);
252     EXPECT_NO_FATAL_FAILURE(Test(true));
253   }
254 }