8 #include <yui/Libyui_config.h> 10 #include "ygtkratiobox.h" 12 G_DEFINE_ABSTRACT_TYPE (
YGtkRatioBox, ygtk_ratio_box, GTK_TYPE_CONTAINER)
16 gtk_widget_set_has_window (GTK_WIDGET(box), FALSE);
17 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (box), FALSE);
20 static GType ygtk_ratio_box_child_type (GtkContainer* container)
21 {
return GTK_TYPE_WIDGET; }
23 void ygtk_ratio_box_pack (
YGtkRatioBox *box, GtkWidget *child, gfloat ratio)
27 child_info->widget = child;
28 child_info->ratio = ratio;
30 box->children = g_list_append (box->children, child_info);
32 gtk_widget_freeze_child_notify (child);
33 gtk_widget_set_parent (child, GTK_WIDGET (box));
34 gtk_widget_thaw_child_notify (child);
41 for (list = box->children; list; list = list->next) {
43 if (i->widget == child)
51 static void ygtk_ratio_box_add (GtkContainer *container, GtkWidget *child)
53 ygtk_ratio_box_pack (YGTK_RATIO_BOX (container), child, 1.0);
56 static void ygtk_ratio_box_remove (GtkContainer *container, GtkWidget *widget)
60 GList* child = box->children;
61 for (child = box->children; child; child = child->next) {
63 if (box_child->widget == widget) {
64 gboolean was_visible = gtk_widget_get_visible (widget);
65 gtk_widget_unparent (widget);
67 box->children = g_list_remove_link (box->children, child);
72 gtk_widget_queue_resize (GTK_WIDGET (container));
78 static void ygtk_ratio_box_forall (GtkContainer *container, gboolean include_internals,
79 GtkCallback callback, gpointer callback_data)
81 g_return_if_fail (callback != NULL);
85 GList* children = box->children;
88 children = children->next;
89 (* callback) (child->widget, callback_data);
96 static void ygtk_ratio_box_get_preferred_size (GtkWidget *widget,
97 GtkRequisition *requisition,
98 GtkOrientation orientation)
100 requisition->width = requisition->height = 0;
103 gint children_nb = 0;
105 for (i = box->children; i; i = i->next) {
107 if (!gtk_widget_get_visible (child->widget))
110 GtkRequisition min_child_req;
111 GtkRequisition nat_child_req;
112 gtk_widget_get_preferred_size (child->widget, &min_child_req, &nat_child_req);
113 if (orientation == GTK_ORIENTATION_HORIZONTAL)
114 requisition->height = MAX (requisition->height, min_child_req.height);
116 requisition->width = MAX (requisition->width, min_child_req.width);
119 gint spacing = children_nb ? box->spacing*(children_nb-1) : 0;
120 if (orientation == GTK_ORIENTATION_HORIZONTAL)
121 requisition->width += spacing;
123 requisition->height += spacing;
125 int border = gtk_container_get_border_width(GTK_CONTAINER (box));
126 requisition->width += border*2;
127 requisition->height += border*2;
130 static void ygtk_ratio_box_size_allocate (GtkWidget *widget,
131 GtkAllocation *allocation,
132 GtkOrientation orientation)
136 gfloat ratios_sum = 0;
137 gint children_nb = 0;
140 for (i = box->children; i; i = i->next) {
142 if (!gtk_widget_get_visible (child->widget))
145 ratios_sum += child->ratio;
149 gint spacing = children_nb ? box->spacing*(children_nb-1) : 0;
151 int border = gtk_container_get_border_width(GTK_CONTAINER (box));
152 int x = allocation->x + border, y = allocation->y + border,
153 width = allocation->width - border*2, height = allocation->height - border*2;
156 if (orientation == GTK_ORIENTATION_HORIZONTAL)
157 length = width - spacing;
159 length = height - spacing;
162 for (i = box->children; i; i = i->next) {
164 if (!gtk_widget_get_visible (child->widget))
167 gint child_length = (child->ratio * length) / ratios_sum;
169 child_length = length - child_pos;
171 GtkAllocation child_alloc;
172 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
173 child_alloc.x = x + child_pos;
175 child_alloc.width = child_length;
176 child_alloc.height = height;
180 child_alloc.y = y + child_pos;
181 child_alloc.width = width;
182 child_alloc.height = child_length;
185 GtkRequisition min_child_req;
186 GtkRequisition nat_child_req;
187 gtk_widget_get_preferred_size (child->widget, &min_child_req, &nat_child_req);
189 child_alloc.width = MAX (child_alloc.width, 1);
190 child_alloc.height = MAX (child_alloc.height, 1);
192 gtk_widget_size_allocate (child->widget, &child_alloc);
193 child_pos += child_length + box->spacing;
197 void ygtk_ratio_box_set_child_packing (
YGtkRatioBox *box, GtkWidget *child, gfloat ratio)
200 child_info = ygtk_ratio_get_child_info (box, child);
202 gtk_widget_freeze_child_notify (child);
203 child_info->ratio = ratio;
204 if (gtk_widget_get_visible (child) && gtk_widget_get_visible (GTK_WIDGET(box)))
205 gtk_widget_queue_resize (child);
207 gtk_widget_thaw_child_notify (child);
211 void ygtk_ratio_box_set_spacing (
YGtkRatioBox *box, guint spacing)
213 box->spacing = spacing;
218 ygtk_ratio_box_parent_class = (GtkContainerClass*) g_type_class_peek_parent (klass);
220 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
221 container_class->add = ygtk_ratio_box_add;
222 container_class->remove = ygtk_ratio_box_remove;
223 container_class->forall = ygtk_ratio_box_forall;
224 container_class->child_type = ygtk_ratio_box_child_type;
229 G_DEFINE_TYPE (
YGtkRatioHBox, ygtk_ratio_hbox, YGTK_TYPE_RATIO_BOX)
234 static void ygtk_ratio_hbox_get_preferred_size (GtkWidget *widget,
235 GtkRequisition *requisition)
236 { ygtk_ratio_box_get_preferred_size (widget, requisition, GTK_ORIENTATION_HORIZONTAL); }
239 ygtk_ratio_hbox_get_preferred_width (GtkWidget *widget,
243 GtkRequisition requisition;
244 ygtk_ratio_hbox_get_preferred_size (widget, &requisition);
245 *minimal_width = *natural_width = requisition.width;
249 ygtk_ratio_hbox_get_preferred_height (GtkWidget *widget,
250 gint *minimal_height,
251 gint *natural_height)
253 GtkRequisition requisition;
254 ygtk_ratio_hbox_get_preferred_size (widget, &requisition);
255 *minimal_height = *natural_height = requisition.height;
258 static void ygtk_ratio_hbox_size_allocate (GtkWidget *widget,
259 GtkAllocation *allocation)
260 { ygtk_ratio_box_size_allocate (widget, allocation, GTK_ORIENTATION_HORIZONTAL); }
262 GtkWidget* ygtk_ratio_hbox_new (gint spacing)
265 box->spacing = spacing;
266 return GTK_WIDGET (box);
271 ygtk_ratio_hbox_parent_class = (
YGtkRatioBoxClass*) g_type_class_peek_parent (klass);
273 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
274 widget_class->get_preferred_width = ygtk_ratio_hbox_get_preferred_width;
275 widget_class->get_preferred_height = ygtk_ratio_hbox_get_preferred_height;
277 widget_class->size_allocate = ygtk_ratio_hbox_size_allocate;
282 G_DEFINE_TYPE (
YGtkRatioVBox, ygtk_ratio_vbox, YGTK_TYPE_RATIO_BOX)
287 static void ygtk_ratio_vbox_get_preferred_size (GtkWidget *widget,
288 GtkRequisition *requisition)
289 { ygtk_ratio_box_get_preferred_size (widget, requisition, GTK_ORIENTATION_VERTICAL); }
292 ygtk_ratio_vbox_get_preferred_width (GtkWidget *widget,
296 GtkRequisition requisition;
297 ygtk_ratio_vbox_get_preferred_size (widget, &requisition);
298 *minimal_width = *natural_width = requisition.width;
302 ygtk_ratio_vbox_get_preferred_height (GtkWidget *widget,
303 gint *minimal_height,
304 gint *natural_height)
306 GtkRequisition requisition;
307 ygtk_ratio_vbox_get_preferred_size (widget, &requisition);
308 *minimal_height = *natural_height = requisition.height;
311 static void ygtk_ratio_vbox_size_allocate (GtkWidget *widget,
312 GtkAllocation *allocation)
313 { ygtk_ratio_box_size_allocate (widget, allocation, GTK_ORIENTATION_VERTICAL); }
315 GtkWidget* ygtk_ratio_vbox_new (gint spacing)
318 box->spacing = spacing;
319 return GTK_WIDGET (box);
324 ygtk_ratio_vbox_parent_class = g_type_class_peek_parent (klass);
326 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
327 widget_class->get_preferred_width = ygtk_ratio_vbox_get_preferred_width;
328 widget_class->get_preferred_height = ygtk_ratio_vbox_get_preferred_height;
329 widget_class->size_allocate = ygtk_ratio_vbox_size_allocate;
334 G_DEFINE_TYPE (
YGtkAdjSize, ygtk_adj_size, GTK_TYPE_BIN)
336 static void ygtk_adj_size_init (
YGtkAdjSize *adj_size)
338 gtk_widget_set_has_window(GTK_WIDGET(adj_size), FALSE);
339 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (adj_size), FALSE);
342 static void ygtk_adj_size_get_preferred_size (
343 GtkWidget *widget, GtkRequisition *requisition)
345 GtkWidget *child = gtk_bin_get_child(GTK_BIN (widget));
347 requisition->width = requisition->height = 0;
348 if (child && gtk_widget_get_visible((child))) {
349 gtk_widget_get_preferred_size(child, NULL, requisition);
351 guint border = gtk_container_get_border_width(GTK_CONTAINER (widget));
352 requisition->width += border * 2;
353 requisition->height += border * 2;
356 if (adj_size->min_size_cb) {
357 guint min_width, min_height;
358 adj_size->min_size_cb (&min_width, &min_height, adj_size->min_size_data);
359 requisition->width = MAX (requisition->width, min_width);
360 requisition->height = MAX (requisition->height, min_height);
362 requisition->width = MAX (requisition->width, adj_size->min_width);
363 requisition->height = MAX (requisition->height, adj_size->min_height);
365 if (adj_size->max_width)
366 requisition->width = MIN (requisition->width, adj_size->max_width);
367 if (adj_size->max_height)
368 requisition->height = MIN (requisition->height, adj_size->max_height);
370 if (adj_size->only_expand) {
371 adj_size->min_width = requisition->width;
372 adj_size->min_height = requisition->height;
378 ygtk_adj_size_get_preferred_width (GtkWidget *widget,
382 GtkRequisition requisition;
383 ygtk_adj_size_get_preferred_size (widget, &requisition);
384 *minimal_width = *natural_width = requisition.width;
388 ygtk_adj_size_get_preferred_height (GtkWidget *widget,
389 gint *minimal_height,
390 gint *natural_height)
392 GtkRequisition requisition;
393 ygtk_adj_size_get_preferred_size (widget, &requisition);
394 *minimal_height = *natural_height = requisition.height;
397 static void ygtk_adj_size_size_allocate (GtkWidget *widget,
398 GtkAllocation *allocation)
400 GtkWidget *child = gtk_bin_get_child(GTK_BIN (widget));
401 if (child && gtk_widget_get_visible (child)) {
402 GtkAllocation child_alloc = *allocation;
403 guint border = gtk_container_get_border_width(GTK_CONTAINER (widget));
404 child_alloc.x += border;
405 child_alloc.y += border;
406 child_alloc.width -= border * 2;
407 child_alloc.height -= border * 2;
409 GtkRequisition min_child_req;
410 GtkRequisition nat_child_req;
411 gtk_widget_get_preferred_size (child, &min_child_req, &nat_child_req);
413 child_alloc.width = MAX (child_alloc.width, 1);
414 child_alloc.height = MAX (child_alloc.height, 1);
415 gtk_widget_size_allocate (child, &child_alloc);
417 GTK_WIDGET_CLASS (ygtk_adj_size_parent_class)->size_allocate (widget, allocation);
420 GtkWidget* ygtk_adj_size_new (
void)
422 return GTK_WIDGET (g_object_new (YGTK_TYPE_ADJ_SIZE, NULL));
425 void ygtk_adj_size_set_min (
YGtkAdjSize *adj_size, guint min_width, guint min_height)
427 adj_size->min_width = min_width;
428 adj_size->min_height = min_height;
431 void ygtk_adj_size_set_max (
YGtkAdjSize *adj_size, guint max_width, guint max_height)
433 adj_size->max_width = max_width;
434 adj_size->max_height = max_height;
437 void ygtk_adj_size_set_min_cb (
YGtkAdjSize *adj_size, LimitSizeCb min_size_cb, gpointer data)
439 adj_size->min_size_cb = min_size_cb;
440 adj_size->min_size_data = data;
443 void ygtk_adj_size_set_only_expand (
YGtkAdjSize *adj_size, gboolean only_expand)
445 adj_size->only_expand = only_expand;
450 ygtk_adj_size_parent_class = g_type_class_peek_parent (klass);
452 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
453 widget_class->get_preferred_width = ygtk_adj_size_get_preferred_width;
454 widget_class->get_preferred_height = ygtk_adj_size_get_preferred_height;
455 widget_class->size_allocate = ygtk_adj_size_size_allocate;