Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: chrome/browser/gtk/gtk_chrome_shrinkable_hbox.cc

Issue 6251001: Move chrome/browser/gtk/ to chrome/browser/ui/gtk/... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/gtk/gtk_chrome_shrinkable_hbox.h"
6
7 #include <gtk/gtk.h>
8 #include <algorithm>
9
10 namespace {
11
12 enum {
13 PROP_0,
14 PROP_HIDE_CHILD_DIRECTLY
15 };
16
17 struct SizeAllocateData {
18 GtkChromeShrinkableHBox* box;
19 GtkAllocation* allocation;
20 GtkTextDirection direction;
21 bool homogeneous;
22 int border_width;
23
24 // Maximum child width when |homogeneous| is TRUE.
25 int homogeneous_child_width;
26 };
27
28 void CountVisibleChildren(GtkWidget* child, gpointer userdata) {
29 if (GTK_WIDGET_VISIBLE(child))
30 ++(*reinterpret_cast<int*>(userdata));
31 }
32
33 void SumChildrenWidthRequisition(GtkWidget* child, gpointer userdata) {
34 if (GTK_WIDGET_VISIBLE(child)) {
35 GtkRequisition req;
36 gtk_widget_get_child_requisition(child, &req);
37 (*reinterpret_cast<int*>(userdata)) += std::max(req.width, 0);
38 }
39 }
40
41 void ShowInvisibleChildren(GtkWidget* child, gpointer userdata) {
42 if (!GTK_WIDGET_VISIBLE(child)) {
43 gtk_widget_show(child);
44 ++(*reinterpret_cast<int*>(userdata));
45 }
46 }
47
48 void ChildSizeAllocate(GtkWidget* child, gpointer userdata) {
49 if (!GTK_WIDGET_VISIBLE(child))
50 return;
51
52 SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata);
53 GtkAllocation child_allocation = child->allocation;
54
55 if (data->homogeneous) {
56 // Make sure the child is not overlapped with others' boundary.
57 if (child_allocation.width > data->homogeneous_child_width) {
58 child_allocation.x +=
59 (child_allocation.width - data->homogeneous_child_width) / 2;
60 child_allocation.width = data->homogeneous_child_width;
61 }
62 } else {
63 guint padding;
64 GtkPackType pack_type;
65 gtk_box_query_child_packing(GTK_BOX(data->box), child, NULL, NULL,
66 &padding, &pack_type);
67
68 if ((data->direction == GTK_TEXT_DIR_RTL && pack_type == GTK_PACK_START) ||
69 (data->direction != GTK_TEXT_DIR_RTL && pack_type == GTK_PACK_END)) {
70 // All children are right aligned, so make sure the child won't overflow
71 // its parent's left edge.
72 int overflow = (data->allocation->x + data->border_width + padding -
73 child_allocation.x);
74 if (overflow > 0) {
75 child_allocation.width -= overflow;
76 child_allocation.x += overflow;
77 }
78 } else {
79 // All children are left aligned, so make sure the child won't overflow
80 // its parent's right edge.
81 int overflow = (child_allocation.x + child_allocation.width + padding -
82 (data->allocation->x + data->allocation->width - data->border_width));
83 if (overflow > 0)
84 child_allocation.width -= overflow;
85 }
86 }
87
88 if (child_allocation.width != child->allocation.width) {
89 if (data->box->hide_child_directly || child_allocation.width <= 1)
90 gtk_widget_hide(child);
91 else
92 gtk_widget_size_allocate(child, &child_allocation);
93 }
94 }
95
96 } // namespace
97
98 G_BEGIN_DECLS
99
100 static void gtk_chrome_shrinkable_hbox_set_property(GObject* object,
101 guint prop_id,
102 const GValue* value,
103 GParamSpec* pspec);
104 static void gtk_chrome_shrinkable_hbox_get_property(GObject* object,
105 guint prop_id,
106 GValue* value,
107 GParamSpec* pspec);
108 static void gtk_chrome_shrinkable_hbox_size_allocate(GtkWidget* widget,
109 GtkAllocation* allocation);
110
111 G_DEFINE_TYPE(GtkChromeShrinkableHBox, gtk_chrome_shrinkable_hbox,
112 GTK_TYPE_HBOX)
113
114 static void gtk_chrome_shrinkable_hbox_class_init(
115 GtkChromeShrinkableHBoxClass *klass) {
116 GObjectClass* object_class = G_OBJECT_CLASS(klass);
117 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
118
119 object_class->set_property = gtk_chrome_shrinkable_hbox_set_property;
120 object_class->get_property = gtk_chrome_shrinkable_hbox_get_property;
121
122 widget_class->size_allocate = gtk_chrome_shrinkable_hbox_size_allocate;
123
124 g_object_class_install_property(object_class, PROP_HIDE_CHILD_DIRECTLY,
125 g_param_spec_boolean("hide-child-directly",
126 "Hide child directly",
127 "Whether the children should be hid directly, "
128 "if there is no enough space in its parent",
129 FALSE,
130 static_cast<GParamFlags>(
131 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
132 }
133
134 static void gtk_chrome_shrinkable_hbox_init(GtkChromeShrinkableHBox* box) {
135 box->hide_child_directly = FALSE;
136 box->children_width_requisition = 0;
137 }
138
139 static void gtk_chrome_shrinkable_hbox_set_property(GObject* object,
140 guint prop_id,
141 const GValue* value,
142 GParamSpec* pspec) {
143 GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(object);
144
145 switch (prop_id) {
146 case PROP_HIDE_CHILD_DIRECTLY:
147 gtk_chrome_shrinkable_hbox_set_hide_child_directly(
148 box, g_value_get_boolean(value));
149 break;
150 default:
151 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
152 break;
153 }
154 }
155
156 static void gtk_chrome_shrinkable_hbox_get_property(GObject* object,
157 guint prop_id,
158 GValue* value,
159 GParamSpec* pspec) {
160 GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(object);
161
162 switch (prop_id) {
163 case PROP_HIDE_CHILD_DIRECTLY:
164 g_value_set_boolean(value, box->hide_child_directly);
165 break;
166 default:
167 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
168 break;
169 }
170 }
171
172 static void gtk_chrome_shrinkable_hbox_size_allocate(
173 GtkWidget* widget, GtkAllocation* allocation) {
174 GtkChromeShrinkableHBox* box = GTK_CHROME_SHRINKABLE_HBOX(widget);
175 gint children_width_requisition = 0;
176 gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
177 &children_width_requisition);
178
179 // If we are allocated to more width or some children are removed or shrunk,
180 // then we need to show all invisible children before calling parent class's
181 // size_allocate method, because the new width may be enough to show those
182 // hidden children.
183 if (widget->allocation.width < allocation->width ||
184 box->children_width_requisition > children_width_requisition) {
185 gtk_container_foreach(GTK_CONTAINER(widget),
186 reinterpret_cast<GtkCallback>(gtk_widget_show), NULL);
187
188 // If there were any invisible children, showing them will trigger another
189 // allocate. But we still need to go through the size allocate process
190 // in this iteration, otherwise before the next allocate iteration, the
191 // children may be redrawn on the screen with incorrect size allocation.
192 }
193
194 // Let the parent class do size allocation first. After that all children will
195 // be allocated with reasonable position and size according to their size
196 // request.
197 (GTK_WIDGET_CLASS(gtk_chrome_shrinkable_hbox_parent_class)->size_allocate)
198 (widget, allocation);
199
200 gint visible_children_count =
201 gtk_chrome_shrinkable_hbox_get_visible_child_count(
202 GTK_CHROME_SHRINKABLE_HBOX(widget));
203
204 box->children_width_requisition = 0;
205 if (visible_children_count == 0)
206 return;
207
208 SizeAllocateData data;
209 data.box = GTK_CHROME_SHRINKABLE_HBOX(widget);
210 data.allocation = allocation;
211 data.direction = gtk_widget_get_direction(widget);
212 data.homogeneous = gtk_box_get_homogeneous(GTK_BOX(widget));
213 data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget));
214 data.homogeneous_child_width =
215 (allocation->width - data.border_width * 2 -
216 (visible_children_count - 1) * gtk_box_get_spacing(GTK_BOX(widget))) /
217 visible_children_count;
218
219 // Shrink or hide children if necessary.
220 gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data);
221
222 // Record current width requisition of visible children, so we can know if
223 // it's necessary to show invisible children next time.
224 gtk_container_foreach(GTK_CONTAINER(widget), SumChildrenWidthRequisition,
225 &box->children_width_requisition);
226 }
227
228 GtkWidget* gtk_chrome_shrinkable_hbox_new(gboolean hide_child_directly,
229 gboolean homogeneous,
230 gint spacing) {
231 return GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_SHRINKABLE_HBOX,
232 "hide-child-directly", hide_child_directly,
233 "homogeneous", homogeneous,
234 "spacing", spacing,
235 NULL));
236 }
237
238 void gtk_chrome_shrinkable_hbox_set_hide_child_directly(
239 GtkChromeShrinkableHBox* box, gboolean hide_child_directly) {
240 g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
241
242 if (hide_child_directly != box->hide_child_directly) {
243 box->hide_child_directly = hide_child_directly;
244 g_object_notify(G_OBJECT(box), "hide-child-directly");
245 gtk_widget_queue_resize(GTK_WIDGET(box));
246 }
247 }
248
249 gboolean gtk_chrome_shrinkable_hbox_get_hide_child_directly(
250 GtkChromeShrinkableHBox* box) {
251 g_return_val_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box), FALSE);
252
253 return box->hide_child_directly;
254 }
255
256 void gtk_chrome_shrinkable_hbox_pack_start(GtkChromeShrinkableHBox* box,
257 GtkWidget* child,
258 guint padding) {
259 g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
260 g_return_if_fail(GTK_IS_WIDGET(child));
261
262 gtk_box_pack_start(GTK_BOX(box), child, FALSE, FALSE, 0);
263 }
264
265 void gtk_chrome_shrinkable_hbox_pack_end(GtkChromeShrinkableHBox* box,
266 GtkWidget* child,
267 guint padding) {
268 g_return_if_fail(GTK_IS_CHROME_SHRINKABLE_HBOX(box));
269 g_return_if_fail(GTK_IS_WIDGET(child));
270
271 gtk_box_pack_end(GTK_BOX(box), child, FALSE, FALSE, 0);
272 }
273
274 gint gtk_chrome_shrinkable_hbox_get_visible_child_count(
275 GtkChromeShrinkableHBox* box) {
276 gint visible_children_count = 0;
277 gtk_container_foreach(GTK_CONTAINER(box), CountVisibleChildren,
278 &visible_children_count);
279 return visible_children_count;
280 }
281
282 G_END_DECLS
OLDNEW
« no previous file with comments | « chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h ('k') | chrome/browser/gtk/gtk_chrome_shrinkable_hbox_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698