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

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

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

Powered by Google App Engine
This is Rietveld 408576698