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.
5 #include "ui/base/gtk/gtk_expanded_container.h"
11 #include "ui/gfx/gtk_compat.h"
20 guint expanded_container_signals
[LAST_SIGNAL
] = { 0 };
22 struct SizeAllocateData
{
24 GtkAllocation
* allocation
;
28 void GetChildPosition(GtkWidget
* container
, GtkWidget
* child
, int* x
, int* y
) {
30 g_value_init(&v
, G_TYPE_INT
);
31 gtk_container_child_get_property(GTK_CONTAINER(container
), child
, "x", &v
);
32 *x
= g_value_get_int(&v
);
33 gtk_container_child_get_property(GTK_CONTAINER(container
), child
, "y", &v
);
34 *y
= g_value_get_int(&v
);
38 void ChildSizeAllocate(GtkWidget
* child
, gpointer userdata
) {
39 if (!gtk_widget_get_visible(child
))
42 SizeAllocateData
* data
= reinterpret_cast<SizeAllocateData
*>(userdata
);
44 GtkRequisition child_requisition
;
45 child_requisition
.width
= data
->allocation
->width
- data
->border_width
* 2;
46 child_requisition
.height
= data
->allocation
->height
- data
->border_width
* 2;
48 // We need to give whoever is pulling our strings a chance to adjust the
49 // size of our children.
50 g_signal_emit(data
->container
,
51 expanded_container_signals
[CHILD_SIZE_REQUEST
], 0,
52 child
, &child_requisition
);
54 GtkAllocation child_allocation
;
55 child_allocation
.width
= child_requisition
.width
;
56 child_allocation
.height
= child_requisition
.height
;
57 if (child_allocation
.width
< 0 || child_allocation
.height
< 0) {
58 gtk_widget_get_child_requisition(child
, &child_requisition
);
59 if (child_allocation
.width
< 0)
60 child_allocation
.width
= child_requisition
.width
;
61 if (child_allocation
.height
< 0)
62 child_allocation
.height
= child_requisition
.height
;
66 GetChildPosition(data
->container
, child
, &x
, &y
);
68 child_allocation
.x
= x
+ data
->border_width
;
69 child_allocation
.y
= y
+ data
->border_width
;
71 if (!gtk_widget_get_has_window(data
->container
)) {
72 child_allocation
.x
+= data
->allocation
->x
;
73 child_allocation
.y
+= data
->allocation
->y
;
75 gtk_widget_size_allocate(child
, &child_allocation
);
78 void Marshal_VOID__OBJECT_BOXED(GClosure
* closure
,
79 GValue
* return_value G_GNUC_UNUSED
,
81 const GValue
* param_values
,
82 gpointer invocation_hint G_GNUC_UNUSED
,
83 gpointer marshal_data
) {
84 typedef void (*GMarshalFunc_VOID__OBJECT_BOXED
) (gpointer data1
,
88 register GMarshalFunc_VOID__OBJECT_BOXED callback
;
89 register GCClosure
*cc
= reinterpret_cast<GCClosure
*>(closure
);
90 register gpointer data1
, data2
;
92 g_return_if_fail(n_param_values
== 3);
94 if (G_CCLOSURE_SWAP_DATA(closure
)) {
95 data1
= closure
->data
;
96 data2
= g_value_peek_pointer(param_values
+ 0);
98 data1
= g_value_peek_pointer(param_values
+ 0);
99 data2
= closure
->data
;
102 callback
= reinterpret_cast<GMarshalFunc_VOID__OBJECT_BOXED
>(
103 marshal_data
? marshal_data
: cc
->callback
);
106 g_value_get_object(param_values
+ 1),
107 g_value_get_boxed(param_values
+ 2),
115 static void gtk_expanded_container_size_allocate(GtkWidget
* widget
,
116 GtkAllocation
* allocation
);
118 G_DEFINE_TYPE(GtkExpandedContainer
, gtk_expanded_container
, GTK_TYPE_FIXED
)
120 static void gtk_expanded_container_class_init(
121 GtkExpandedContainerClass
*klass
) {
122 GtkObjectClass
* object_class
=
123 reinterpret_cast<GtkObjectClass
*>(klass
);
125 GtkWidgetClass
* widget_class
=
126 reinterpret_cast<GtkWidgetClass
*>(klass
);
127 widget_class
->size_allocate
= gtk_expanded_container_size_allocate
;
129 expanded_container_signals
[CHILD_SIZE_REQUEST
] =
130 g_signal_new("child-size-request",
131 G_OBJECT_CLASS_TYPE(object_class
),
132 static_cast<GSignalFlags
>(G_SIGNAL_RUN_FIRST
),
135 Marshal_VOID__OBJECT_BOXED
,
138 GTK_TYPE_REQUISITION
| G_SIGNAL_TYPE_STATIC_SCOPE
);
141 static void gtk_expanded_container_init(GtkExpandedContainer
* container
) {
144 static void gtk_expanded_container_size_allocate(GtkWidget
* widget
,
145 GtkAllocation
* allocation
) {
146 gtk_widget_set_allocation(widget
, allocation
);
148 if (gtk_widget_get_has_window(widget
) && gtk_widget_get_realized(widget
)) {
149 gdk_window_move_resize(gtk_widget_get_window(widget
),
156 SizeAllocateData data
;
157 data
.container
= widget
;
158 data
.allocation
= allocation
;
159 data
.border_width
= gtk_container_get_border_width(GTK_CONTAINER(widget
));
161 gtk_container_foreach(GTK_CONTAINER(widget
), ChildSizeAllocate
, &data
);
164 GtkWidget
* gtk_expanded_container_new() {
165 return GTK_WIDGET(g_object_new(GTK_TYPE_EXPANDED_CONTAINER
, NULL
));
168 void gtk_expanded_container_put(GtkExpandedContainer
* container
,
169 GtkWidget
* widget
, gint x
, gint y
) {
170 g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container
));
171 g_return_if_fail(GTK_IS_WIDGET(widget
));
172 gtk_fixed_put(GTK_FIXED(container
), widget
, x
, y
);
175 void gtk_expanded_container_move(GtkExpandedContainer
* container
,
176 GtkWidget
* widget
, gint x
, gint y
) {
177 g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container
));
178 g_return_if_fail(GTK_IS_WIDGET(widget
));
179 gtk_fixed_move(GTK_FIXED(container
), widget
, x
, y
);
182 void gtk_expanded_container_set_has_window(GtkExpandedContainer
* container
,
183 gboolean has_window
) {
184 g_return_if_fail(GTK_IS_EXPANDED_CONTAINER(container
));
185 g_return_if_fail(!gtk_widget_get_realized(GTK_WIDGET(container
)));
186 gtk_widget_set_has_window(GTK_WIDGET(container
), has_window
);
189 gboolean
gtk_expanded_container_get_has_window(
190 GtkExpandedContainer
* container
) {
191 g_return_val_if_fail(GTK_IS_EXPANDED_CONTAINER(container
), FALSE
);
192 return gtk_widget_get_has_window(GTK_WIDGET(container
));