OLD | NEW |
| (Empty) |
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_expanded_container.h" | |
6 | |
7 #include <gtk/gtk.h> | |
8 | |
9 #include <algorithm> | |
10 | |
11 namespace { | |
12 | |
13 enum { | |
14 CHILD_SIZE_REQUEST, | |
15 LAST_SIGNAL | |
16 }; | |
17 | |
18 guint expanded_container_signals[LAST_SIGNAL] = { 0 }; | |
19 | |
20 struct SizeAllocateData { | |
21 GtkWidget* container; | |
22 GtkAllocation* allocation; | |
23 int border_width; | |
24 }; | |
25 | |
26 void GetChildPosition(GtkWidget* container, GtkWidget* child, int* x, int* y) { | |
27 GValue v = { 0 }; | |
28 g_value_init(&v, G_TYPE_INT); | |
29 gtk_container_child_get_property(GTK_CONTAINER(container), child, "x", &v); | |
30 *x = g_value_get_int(&v); | |
31 gtk_container_child_get_property(GTK_CONTAINER(container), child, "y", &v); | |
32 *y = g_value_get_int(&v); | |
33 g_value_unset(&v); | |
34 } | |
35 | |
36 void ChildSizeAllocate(GtkWidget* child, gpointer userdata) { | |
37 if (!gtk_widget_get_visible(child)) | |
38 return; | |
39 | |
40 SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata); | |
41 | |
42 GtkRequisition child_requisition; | |
43 child_requisition.width = data->allocation->width - data->border_width * 2; | |
44 child_requisition.height = data->allocation->height - data->border_width * 2; | |
45 | |
46 // We need to give whoever is pulling our strings a chance to adjust the | |
47 // size of our children. | |
48 g_signal_emit(data->container, | |
49 expanded_container_signals[CHILD_SIZE_REQUEST], 0, | |
50 child, &child_requisition); | |
51 | |
52 GtkAllocation child_allocation; | |
53 child_allocation.width = child_requisition.width; | |
54 child_allocation.height = child_requisition.height; | |
55 if (child_allocation.width < 0 || child_allocation.height < 0) { | |
56 gtk_widget_get_child_requisition(child, &child_requisition); | |
57 if (child_allocation.width < 0) | |
58 child_allocation.width = child_requisition.width; | |
59 if (child_allocation.height < 0) | |
60 child_allocation.height = child_requisition.height; | |
61 } | |
62 | |
63 int x, y; | |
64 GetChildPosition(data->container, child, &x, &y); | |
65 | |
66 child_allocation.x = x + data->border_width; | |
67 child_allocation.y = y + data->border_width; | |
68 | |
69 if (GTK_WIDGET_NO_WINDOW(data->container)) { | |
70 child_allocation.x += data->allocation->x; | |
71 child_allocation.y += data->allocation->y; | |
72 } | |
73 gtk_widget_size_allocate(child, &child_allocation); | |
74 } | |
75 | |
76 void Marshal_VOID__OBJECT_BOXED(GClosure* closure, | |
77 GValue* return_value G_GNUC_UNUSED, | |
78 guint n_param_values, | |
79 const GValue* param_values, | |
80 gpointer invocation_hint G_GNUC_UNUSED, | |
81 gpointer marshal_data) { | |
82 typedef void (*GMarshalFunc_VOID__OBJECT_BOXED) (gpointer data1, | |
83 gpointer arg_1, | |
84 gpointer arg_2, | |
85 gpointer data2); | |
86 register GMarshalFunc_VOID__OBJECT_BOXED callback; | |
87 register GCClosure *cc = reinterpret_cast<GCClosure*>(closure); | |
88 register gpointer data1, data2; | |
89 | |
90 g_return_if_fail(n_param_values == 3); | |
91 | |
92 if (G_CCLOSURE_SWAP_DATA(closure)) { | |
93 data1 = closure->data; | |
94 data2 = g_value_peek_pointer(param_values + 0); | |
95 } else { | |
96 data1 = g_value_peek_pointer(param_values + 0); | |
97 data2 = closure->data; | |
98 } | |
99 | |
100 callback = reinterpret_cast<GMarshalFunc_VOID__OBJECT_BOXED>( | |
101 marshal_data ? marshal_data : cc->callback); | |
102 | |
103 callback(data1, | |
104 g_value_get_object(param_values + 1), | |
105 g_value_get_boxed(param_values + 2), | |
106 data2); | |
107 } | |
108 | |
109 } // namespace | |
110 | |
111 G_BEGIN_DECLS | |
112 | |
113 static void gtk_expanded_container_size_allocate(GtkWidget* widget, | |
114 GtkAllocation* allocation); | |
115 | |
116 G_DEFINE_TYPE(GtkExpandedContainer, gtk_expanded_container, GTK_TYPE_FIXED) | |
117 | |
118 static void gtk_expanded_container_class_init( | |
119 GtkExpandedContainerClass *klass) { | |
120 GtkObjectClass* object_class = | |
121 reinterpret_cast<GtkObjectClass*>(klass); | |
122 | |
123 GtkWidgetClass* widget_class = | |
124 reinterpret_cast<GtkWidgetClass*>(klass); | |
125 widget_class->size_allocate = gtk_expanded_container_size_allocate; | |
126 | |
127 expanded_container_signals[CHILD_SIZE_REQUEST] = | |
128 g_signal_new("child-size-request", | |
129 G_OBJECT_CLASS_TYPE(object_class), | |
130 static_cast<GSignalFlags>(G_SIGNAL_RUN_FIRST), | |
131 0, | |
132 NULL, NULL, | |
133 Marshal_VOID__OBJECT_BOXED, | |
134 G_TYPE_NONE, 2, | |
135 GTK_TYPE_WIDGET, | |
136 GTK_TYPE_REQUISITION | G_SIGNAL_TYPE_STATIC_SCOPE); | |
137 } | |
138 | |
139 static void gtk_expanded_container_init(GtkExpandedContainer* container) { | |
140 } | |
141 | |
142 static void gtk_expanded_container_size_allocate(GtkWidget* widget, | |
143 GtkAllocation* allocation) { | |
144 widget->allocation = *allocation; | |
145 | |
146 if (!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)) { | |
147 gdk_window_move_resize(widget->window, | |
148 allocation->x, | |
149 allocation->y, | |
150 allocation->width, | |
151 allocation->height); | |
152 } | |
153 | |
154 SizeAllocateData data; | |
155 data.container = widget; | |
156 data.allocation = allocation; | |
157 data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget)); | |
158 | |
159 gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data); | |
160 } | |
161 | |
162 GtkWidget* gtk_expanded_container_new() { | |
163 return GTK_WIDGET(g_object_new(GTK_TYPE_EXPANDED_CONTAINER, NULL)); | |
164 } | |
165 | |
166 void gtk_expanded_container_put(GtkExpandedContainer* container, | |
167 GtkWidget* widget, gint x, gint y) { | |
168 g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container)); | |
169 g_return_if_fail(GTK_IS_WIDGET(widget)); | |
170 gtk_fixed_put(GTK_FIXED(container), widget, x, y); | |
171 } | |
172 | |
173 void gtk_expanded_container_move(GtkExpandedContainer* container, | |
174 GtkWidget* widget, gint x, gint y) { | |
175 g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container)); | |
176 g_return_if_fail(GTK_IS_WIDGET(widget)); | |
177 gtk_fixed_move(GTK_FIXED(container), widget, x, y); | |
178 } | |
179 | |
180 void gtk_expanded_container_set_has_window(GtkExpandedContainer* container, | |
181 gboolean has_window) { | |
182 g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container)); | |
183 g_return_if_fail(!GTK_WIDGET_REALIZED(container)); | |
184 gtk_fixed_set_has_window(GTK_FIXED(container), has_window); | |
185 } | |
186 | |
187 gboolean gtk_expanded_container_get_has_window( | |
188 GtkExpandedContainer* container) { | |
189 g_return_val_if_fail(GTK_IS_EXPANDED_CONTAINER(container), FALSE); | |
190 return gtk_fixed_get_has_window(GTK_FIXED(container)); | |
191 } | |
192 | |
193 G_END_DECLS | |
OLD | NEW |