| 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 "ui/base/gtk/gtk_expanded_container.h" | |
| 6 | |
| 7 #include <gtk/gtk.h> | |
| 8 | |
| 9 #include <algorithm> | |
| 10 | |
| 11 #include "ui/gfx/gtk_compat.h" | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 enum { | |
| 16 CHILD_SIZE_REQUEST, | |
| 17 LAST_SIGNAL | |
| 18 }; | |
| 19 | |
| 20 guint expanded_container_signals[LAST_SIGNAL] = { 0 }; | |
| 21 | |
| 22 struct SizeAllocateData { | |
| 23 GtkWidget* container; | |
| 24 GtkAllocation* allocation; | |
| 25 int border_width; | |
| 26 }; | |
| 27 | |
| 28 void GetChildPosition(GtkWidget* container, GtkWidget* child, int* x, int* y) { | |
| 29 GValue v = { 0 }; | |
| 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); | |
| 35 g_value_unset(&v); | |
| 36 } | |
| 37 | |
| 38 void ChildSizeAllocate(GtkWidget* child, gpointer userdata) { | |
| 39 if (!gtk_widget_get_visible(child)) | |
| 40 return; | |
| 41 | |
| 42 SizeAllocateData* data = reinterpret_cast<SizeAllocateData*>(userdata); | |
| 43 | |
| 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; | |
| 47 | |
| 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); | |
| 53 | |
| 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; | |
| 63 } | |
| 64 | |
| 65 int x, y; | |
| 66 GetChildPosition(data->container, child, &x, &y); | |
| 67 | |
| 68 child_allocation.x = x + data->border_width; | |
| 69 child_allocation.y = y + data->border_width; | |
| 70 | |
| 71 if (!gtk_widget_get_has_window(data->container)) { | |
| 72 child_allocation.x += data->allocation->x; | |
| 73 child_allocation.y += data->allocation->y; | |
| 74 } | |
| 75 gtk_widget_size_allocate(child, &child_allocation); | |
| 76 } | |
| 77 | |
| 78 void Marshal_VOID__OBJECT_BOXED(GClosure* closure, | |
| 79 GValue* return_value G_GNUC_UNUSED, | |
| 80 guint n_param_values, | |
| 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, | |
| 85 gpointer arg_1, | |
| 86 gpointer arg_2, | |
| 87 gpointer data2); | |
| 88 register GMarshalFunc_VOID__OBJECT_BOXED callback; | |
| 89 register GCClosure *cc = reinterpret_cast<GCClosure*>(closure); | |
| 90 register gpointer data1, data2; | |
| 91 | |
| 92 g_return_if_fail(n_param_values == 3); | |
| 93 | |
| 94 if (G_CCLOSURE_SWAP_DATA(closure)) { | |
| 95 data1 = closure->data; | |
| 96 data2 = g_value_peek_pointer(param_values + 0); | |
| 97 } else { | |
| 98 data1 = g_value_peek_pointer(param_values + 0); | |
| 99 data2 = closure->data; | |
| 100 } | |
| 101 | |
| 102 callback = reinterpret_cast<GMarshalFunc_VOID__OBJECT_BOXED>( | |
| 103 marshal_data ? marshal_data : cc->callback); | |
| 104 | |
| 105 callback(data1, | |
| 106 g_value_get_object(param_values + 1), | |
| 107 g_value_get_boxed(param_values + 2), | |
| 108 data2); | |
| 109 } | |
| 110 | |
| 111 } // namespace | |
| 112 | |
| 113 G_BEGIN_DECLS | |
| 114 | |
| 115 static void gtk_expanded_container_size_allocate(GtkWidget* widget, | |
| 116 GtkAllocation* allocation); | |
| 117 | |
| 118 G_DEFINE_TYPE(GtkExpandedContainer, gtk_expanded_container, GTK_TYPE_FIXED) | |
| 119 | |
| 120 static void gtk_expanded_container_class_init( | |
| 121 GtkExpandedContainerClass *klass) { | |
| 122 GtkObjectClass* object_class = | |
| 123 reinterpret_cast<GtkObjectClass*>(klass); | |
| 124 | |
| 125 GtkWidgetClass* widget_class = | |
| 126 reinterpret_cast<GtkWidgetClass*>(klass); | |
| 127 widget_class->size_allocate = gtk_expanded_container_size_allocate; | |
| 128 | |
| 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), | |
| 133 0, | |
| 134 NULL, NULL, | |
| 135 Marshal_VOID__OBJECT_BOXED, | |
| 136 G_TYPE_NONE, 2, | |
| 137 GTK_TYPE_WIDGET, | |
| 138 GTK_TYPE_REQUISITION | G_SIGNAL_TYPE_STATIC_SCOPE); | |
| 139 } | |
| 140 | |
| 141 static void gtk_expanded_container_init(GtkExpandedContainer* container) { | |
| 142 } | |
| 143 | |
| 144 static void gtk_expanded_container_size_allocate(GtkWidget* widget, | |
| 145 GtkAllocation* allocation) { | |
| 146 gtk_widget_set_allocation(widget, allocation); | |
| 147 | |
| 148 if (gtk_widget_get_has_window(widget) && gtk_widget_get_realized(widget)) { | |
| 149 gdk_window_move_resize(gtk_widget_get_window(widget), | |
| 150 allocation->x, | |
| 151 allocation->y, | |
| 152 allocation->width, | |
| 153 allocation->height); | |
| 154 } | |
| 155 | |
| 156 SizeAllocateData data; | |
| 157 data.container = widget; | |
| 158 data.allocation = allocation; | |
| 159 data.border_width = gtk_container_get_border_width(GTK_CONTAINER(widget)); | |
| 160 | |
| 161 gtk_container_foreach(GTK_CONTAINER(widget), ChildSizeAllocate, &data); | |
| 162 } | |
| 163 | |
| 164 GtkWidget* gtk_expanded_container_new() { | |
| 165 return GTK_WIDGET(g_object_new(GTK_TYPE_EXPANDED_CONTAINER, NULL)); | |
| 166 } | |
| 167 | |
| 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); | |
| 173 } | |
| 174 | |
| 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); | |
| 180 } | |
| 181 | |
| 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); | |
| 187 } | |
| 188 | |
| 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)); | |
| 193 } | |
| 194 | |
| 195 G_END_DECLS | |
| OLD | NEW |