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))
171 gint child_length = (child->ratio * length) / ratios_sum;
173 child_length = length - child_pos;
175 GtkAllocation child_alloc;
176 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
177 child_alloc.x = x + child_pos;
179 child_alloc.width = child_length;
180 child_alloc.height = height;
184 child_alloc.y = y + child_pos;
185 child_alloc.width = width;
186 child_alloc.height = child_length;
188 child_alloc.width = MAX (child_alloc.width, 1);
189 child_alloc.height = MAX (child_alloc.height, 1);
191 gtk_widget_size_allocate (child->widget, &child_alloc);
192 child_pos += child_length + box->spacing;
196 void ygtk_ratio_box_set_child_packing (
YGtkRatioBox *box, GtkWidget *child, gfloat ratio)
199 child_info = ygtk_ratio_get_child_info (box, child);
201 gtk_widget_freeze_child_notify (child);
202 child_info->ratio = ratio;
203 if (gtk_widget_get_visible (child) && gtk_widget_get_visible (GTK_WIDGET(box)))
204 gtk_widget_queue_resize (child);
206 gtk_widget_thaw_child_notify (child);
210 void ygtk_ratio_box_set_spacing (
YGtkRatioBox *box, guint spacing)
212 box->spacing = spacing;
217 ygtk_ratio_box_parent_class = (GtkContainerClass*) g_type_class_peek_parent (klass);
219 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
220 container_class->add = ygtk_ratio_box_add;
221 container_class->remove = ygtk_ratio_box_remove;
222 container_class->forall = ygtk_ratio_box_forall;
223 container_class->child_type = ygtk_ratio_box_child_type;
228 G_DEFINE_TYPE (
YGtkRatioHBox, ygtk_ratio_hbox, YGTK_TYPE_RATIO_BOX)
233 static void ygtk_ratio_hbox_get_preferred_size (GtkWidget *widget,
234 GtkRequisition *requisition)
235 { ygtk_ratio_box_get_preferred_size (widget, requisition, GTK_ORIENTATION_HORIZONTAL); }
238 ygtk_ratio_hbox_get_preferred_width (GtkWidget *widget,
242 GtkRequisition requisition;
243 ygtk_ratio_hbox_get_preferred_size (widget, &requisition);
244 *minimal_width = *natural_width = requisition.width;
248 ygtk_ratio_hbox_get_preferred_height (GtkWidget *widget,
249 gint *minimal_height,
250 gint *natural_height)
252 GtkRequisition requisition;
253 ygtk_ratio_hbox_get_preferred_size (widget, &requisition);
254 *minimal_height = *natural_height = requisition.height;
257 static void ygtk_ratio_hbox_size_allocate (GtkWidget *widget,
258 GtkAllocation *allocation)
259 { ygtk_ratio_box_size_allocate (widget, allocation, GTK_ORIENTATION_HORIZONTAL); }
261 GtkWidget* ygtk_ratio_hbox_new (gint spacing)
264 box->spacing = spacing;
265 return GTK_WIDGET (box);
270 ygtk_ratio_hbox_parent_class = (
YGtkRatioBoxClass*) g_type_class_peek_parent (klass);
272 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
273 widget_class->get_preferred_width = ygtk_ratio_hbox_get_preferred_width;
274 widget_class->get_preferred_height = ygtk_ratio_hbox_get_preferred_height;
276 widget_class->size_allocate = ygtk_ratio_hbox_size_allocate;
281 G_DEFINE_TYPE (
YGtkRatioVBox, ygtk_ratio_vbox, YGTK_TYPE_RATIO_BOX)
286 static void ygtk_ratio_vbox_get_preferred_size (GtkWidget *widget,
287 GtkRequisition *requisition)
288 { ygtk_ratio_box_get_preferred_size (widget, requisition, GTK_ORIENTATION_VERTICAL); }
291 ygtk_ratio_vbox_get_preferred_width (GtkWidget *widget,
295 GtkRequisition requisition;
296 ygtk_ratio_vbox_get_preferred_size (widget, &requisition);
297 *minimal_width = *natural_width = requisition.width;
301 ygtk_ratio_vbox_get_preferred_height (GtkWidget *widget,
302 gint *minimal_height,
303 gint *natural_height)
305 GtkRequisition requisition;
306 ygtk_ratio_vbox_get_preferred_size (widget, &requisition);
307 *minimal_height = *natural_height = requisition.height;
310 static void ygtk_ratio_vbox_size_allocate (GtkWidget *widget,
311 GtkAllocation *allocation)
312 { ygtk_ratio_box_size_allocate (widget, allocation, GTK_ORIENTATION_VERTICAL); }
314 GtkWidget* ygtk_ratio_vbox_new (gint spacing)
317 box->spacing = spacing;
318 return GTK_WIDGET (box);
323 ygtk_ratio_vbox_parent_class = g_type_class_peek_parent (klass);
325 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
326 widget_class->get_preferred_width = ygtk_ratio_vbox_get_preferred_width;
327 widget_class->get_preferred_height = ygtk_ratio_vbox_get_preferred_height;
328 widget_class->size_allocate = ygtk_ratio_vbox_size_allocate;
333 G_DEFINE_TYPE (
YGtkAdjSize, ygtk_adj_size, GTK_TYPE_BIN)
335 static
void ygtk_adj_size_init (
YGtkAdjSize *adj_size)
337 gtk_widget_set_has_window(GTK_WIDGET(adj_size), FALSE);
338 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (adj_size), FALSE);
341 static void ygtk_adj_size_get_preferred_size (
342 GtkWidget *widget, GtkRequisition *requisition)
344 GtkWidget *child = gtk_bin_get_child(GTK_BIN (widget));
346 requisition->width = requisition->height = 0;
347 if (child && gtk_widget_get_visible((child))) {
348 gtk_widget_get_preferred_size(child, NULL, requisition);
350 guint border = gtk_container_get_border_width(GTK_CONTAINER (widget));
351 requisition->width += border * 2;
352 requisition->height += border * 2;
355 if (adj_size->min_size_cb) {
356 guint min_width, min_height;
357 adj_size->min_size_cb (&min_width, &min_height, adj_size->min_size_data);
358 requisition->width = MAX (requisition->width, min_width);
359 requisition->height = MAX (requisition->height, min_height);
361 requisition->width = MAX (requisition->width, adj_size->min_width);
362 requisition->height = MAX (requisition->height, adj_size->min_height);
364 if (adj_size->max_width)
365 requisition->width = MIN (requisition->width, adj_size->max_width);
366 if (adj_size->max_height)
367 requisition->height = MIN (requisition->height, adj_size->max_height);
369 if (adj_size->only_expand) {
370 adj_size->min_width = requisition->width;
371 adj_size->min_height = requisition->height;
377 ygtk_adj_size_get_preferred_width (GtkWidget *widget,
381 GtkRequisition requisition;
382 ygtk_adj_size_get_preferred_size (widget, &requisition);
383 *minimal_width = *natural_width = requisition.width;
387 ygtk_adj_size_get_preferred_height (GtkWidget *widget,
388 gint *minimal_height,
389 gint *natural_height)
391 GtkRequisition requisition;
392 ygtk_adj_size_get_preferred_size (widget, &requisition);
393 *minimal_height = *natural_height = requisition.height;
396 static void ygtk_adj_size_size_allocate (GtkWidget *widget,
397 GtkAllocation *allocation)
399 GtkWidget *child = gtk_bin_get_child(GTK_BIN (widget));
400 if (child && gtk_widget_get_visible (child)) {
401 GtkAllocation child_alloc = *allocation;
402 guint border = gtk_container_get_border_width(GTK_CONTAINER (widget));
403 child_alloc.x += border;
404 child_alloc.y += border;
405 child_alloc.width -= border * 2;
406 child_alloc.height -= border * 2;
407 child_alloc.width = MAX (child_alloc.width, 1);
408 child_alloc.height = MAX (child_alloc.height, 1);
409 gtk_widget_size_allocate (child, &child_alloc);
411 GTK_WIDGET_CLASS (ygtk_adj_size_parent_class)->size_allocate (widget, allocation);
414 GtkWidget* ygtk_adj_size_new (
void)
416 return GTK_WIDGET (g_object_new (YGTK_TYPE_ADJ_SIZE, NULL));
419 void ygtk_adj_size_set_min (
YGtkAdjSize *adj_size, guint min_width, guint min_height)
421 adj_size->min_width = min_width;
422 adj_size->min_height = min_height;
425 void ygtk_adj_size_set_max (
YGtkAdjSize *adj_size, guint max_width, guint max_height)
427 adj_size->max_width = max_width;
428 adj_size->max_height = max_height;
431 void ygtk_adj_size_set_min_cb (
YGtkAdjSize *adj_size, LimitSizeCb min_size_cb, gpointer data)
433 adj_size->min_size_cb = min_size_cb;
434 adj_size->min_size_data = data;
437 void ygtk_adj_size_set_only_expand (
YGtkAdjSize *adj_size, gboolean only_expand)
439 adj_size->only_expand = only_expand;
444 ygtk_adj_size_parent_class = g_type_class_peek_parent (klass);
446 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
447 widget_class->get_preferred_width = ygtk_adj_size_get_preferred_width;
448 widget_class->get_preferred_height = ygtk_adj_size_get_preferred_height;
449 widget_class->size_allocate = ygtk_adj_size_size_allocate;