1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gtkalignment.h"
29 #include "gtkprivate.h"
49 #define GTK_ALIGNMENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ALIGNMENT, GtkAlignmentPrivate))
51 struct _GtkAlignmentPrivate
59 static void gtk_alignment_size_request (GtkWidget *widget,
60 GtkRequisition *requisition);
61 static void gtk_alignment_size_allocate (GtkWidget *widget,
62 GtkAllocation *allocation);
63 static void gtk_alignment_set_property (GObject *object,
67 static void gtk_alignment_get_property (GObject *object,
72 G_DEFINE_TYPE (GtkAlignment, gtk_alignment, GTK_TYPE_BIN)
75 gtk_alignment_class_init (GtkAlignmentClass *class)
77 GObjectClass *gobject_class;
78 GtkWidgetClass *widget_class;
80 gobject_class = (GObjectClass*) class;
81 widget_class = (GtkWidgetClass*) class;
83 gobject_class->set_property = gtk_alignment_set_property;
84 gobject_class->get_property = gtk_alignment_get_property;
86 widget_class->size_request = gtk_alignment_size_request;
87 widget_class->size_allocate = gtk_alignment_size_allocate;
89 g_object_class_install_property (gobject_class,
91 g_param_spec_float("xalign",
92 P_("Horizontal alignment"),
93 P_("Horizontal position of child in available space. 0.0 is left aligned, 1.0 is right aligned"),
97 GTK_PARAM_READWRITE));
99 g_object_class_install_property (gobject_class,
101 g_param_spec_float("yalign",
102 P_("Vertical alignment"),
103 P_("Vertical position of child in available space. 0.0 is top aligned, 1.0 is bottom aligned"),
107 GTK_PARAM_READWRITE));
108 g_object_class_install_property (gobject_class,
110 g_param_spec_float("xscale",
111 P_("Horizontal scale"),
112 P_("If available horizontal space is bigger than needed for the child, how much of it to use for the child. 0.0 means none, 1.0 means all"),
116 GTK_PARAM_READWRITE));
117 g_object_class_install_property (gobject_class,
119 g_param_spec_float("yscale",
120 P_("Vertical scale"),
121 P_("If available vertical space is bigger than needed for the child, how much of it to use for the child. 0.0 means none, 1.0 means all"),
125 GTK_PARAM_READWRITE));
129 * GtkAlignment:top-padding:
131 * The padding to insert at the top of the widget.
135 g_object_class_install_property (gobject_class,
137 g_param_spec_uint("top-padding",
139 P_("The padding to insert at the top of the widget."),
143 GTK_PARAM_READWRITE));
146 * GtkAlignment:bottom-padding:
148 * The padding to insert at the bottom of the widget.
152 g_object_class_install_property (gobject_class,
154 g_param_spec_uint("bottom-padding",
155 P_("Bottom Padding"),
156 P_("The padding to insert at the bottom of the widget."),
160 GTK_PARAM_READWRITE));
163 * GtkAlignment:left-padding:
165 * The padding to insert at the left of the widget.
169 g_object_class_install_property (gobject_class,
171 g_param_spec_uint("left-padding",
173 P_("The padding to insert at the left of the widget."),
177 GTK_PARAM_READWRITE));
180 * GtkAlignment:right-padding:
182 * The padding to insert at the right of the widget.
186 g_object_class_install_property (gobject_class,
188 g_param_spec_uint("right-padding",
190 P_("The padding to insert at the right of the widget."),
194 GTK_PARAM_READWRITE));
196 g_type_class_add_private (gobject_class, sizeof (GtkAlignmentPrivate));
200 gtk_alignment_init (GtkAlignment *alignment)
202 GtkAlignmentPrivate *priv;
204 GTK_WIDGET_SET_FLAGS (alignment, GTK_NO_WINDOW);
205 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (alignment), FALSE);
207 alignment->xalign = 0.5;
208 alignment->yalign = 0.5;
209 alignment->xscale = 1.0;
210 alignment->yscale = 1.0;
212 /* Initialize padding with default values: */
213 priv = GTK_ALIGNMENT_GET_PRIVATE (alignment);
214 priv->padding_top = 0;
215 priv->padding_bottom = 0;
216 priv->padding_left = 0;
217 priv->padding_right = 0;
221 gtk_alignment_new (gfloat xalign,
226 GtkAlignment *alignment;
228 alignment = g_object_new (GTK_TYPE_ALIGNMENT, NULL);
230 alignment->xalign = CLAMP (xalign, 0.0, 1.0);
231 alignment->yalign = CLAMP (yalign, 0.0, 1.0);
232 alignment->xscale = CLAMP (xscale, 0.0, 1.0);
233 alignment->yscale = CLAMP (yscale, 0.0, 1.0);
235 return GTK_WIDGET (alignment);
239 gtk_alignment_set_property (GObject *object,
244 GtkAlignment *alignment;
245 GtkAlignmentPrivate *priv;
247 alignment = GTK_ALIGNMENT (object);
248 priv = GTK_ALIGNMENT_GET_PRIVATE (alignment);
253 gtk_alignment_set (alignment,
254 g_value_get_float (value),
260 gtk_alignment_set (alignment,
262 g_value_get_float (value),
267 gtk_alignment_set (alignment,
270 g_value_get_float (value),
274 gtk_alignment_set (alignment,
278 g_value_get_float (value));
282 case PROP_TOP_PADDING:
283 gtk_alignment_set_padding (alignment,
284 g_value_get_uint (value),
285 priv->padding_bottom,
287 priv->padding_right);
289 case PROP_BOTTOM_PADDING:
290 gtk_alignment_set_padding (alignment,
292 g_value_get_uint (value),
294 priv->padding_right);
296 case PROP_LEFT_PADDING:
297 gtk_alignment_set_padding (alignment,
299 priv->padding_bottom,
300 g_value_get_uint (value),
301 priv->padding_right);
303 case PROP_RIGHT_PADDING:
304 gtk_alignment_set_padding (alignment,
306 priv->padding_bottom,
308 g_value_get_uint (value));
312 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
318 gtk_alignment_get_property (GObject *object,
323 GtkAlignment *alignment;
324 GtkAlignmentPrivate *priv;
326 alignment = GTK_ALIGNMENT (object);
327 priv = GTK_ALIGNMENT_GET_PRIVATE (alignment);
332 g_value_set_float(value, alignment->xalign);
335 g_value_set_float(value, alignment->yalign);
338 g_value_set_float(value, alignment->xscale);
341 g_value_set_float(value, alignment->yscale);
345 case PROP_TOP_PADDING:
346 g_value_set_uint (value, priv->padding_top);
348 case PROP_BOTTOM_PADDING:
349 g_value_set_uint (value, priv->padding_bottom);
351 case PROP_LEFT_PADDING:
352 g_value_set_uint (value, priv->padding_left);
354 case PROP_RIGHT_PADDING:
355 g_value_set_uint (value, priv->padding_right);
359 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
365 gtk_alignment_set (GtkAlignment *alignment,
371 g_return_if_fail (GTK_IS_ALIGNMENT (alignment));
373 xalign = CLAMP (xalign, 0.0, 1.0);
374 yalign = CLAMP (yalign, 0.0, 1.0);
375 xscale = CLAMP (xscale, 0.0, 1.0);
376 yscale = CLAMP (yscale, 0.0, 1.0);
378 if ( (alignment->xalign != xalign)
379 || (alignment->yalign != yalign)
380 || (alignment->xscale != xscale)
381 || (alignment->yscale != yscale))
383 g_object_freeze_notify (G_OBJECT (alignment));
384 if (alignment->xalign != xalign)
386 alignment->xalign = xalign;
387 g_object_notify (G_OBJECT (alignment), "xalign");
389 if (alignment->yalign != yalign)
391 alignment->yalign = yalign;
392 g_object_notify (G_OBJECT (alignment), "yalign");
394 if (alignment->xscale != xscale)
396 alignment->xscale = xscale;
397 g_object_notify (G_OBJECT (alignment), "xscale");
399 if (alignment->yscale != yscale)
401 alignment->yscale = yscale;
402 g_object_notify (G_OBJECT (alignment), "yscale");
404 g_object_thaw_notify (G_OBJECT (alignment));
406 if (GTK_BIN (alignment)->child)
407 gtk_widget_queue_resize (GTK_BIN (alignment)->child);
408 gtk_widget_queue_draw (GTK_WIDGET (alignment));
414 gtk_alignment_size_request (GtkWidget *widget,
415 GtkRequisition *requisition)
418 GtkAlignmentPrivate *priv;
420 bin = GTK_BIN (widget);
421 priv = GTK_ALIGNMENT_GET_PRIVATE (widget);
423 requisition->width = GTK_CONTAINER (widget)->border_width * 2;
424 requisition->height = GTK_CONTAINER (widget)->border_width * 2;
426 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
428 GtkRequisition child_requisition;
430 gtk_widget_size_request (bin->child, &child_requisition);
432 requisition->width += child_requisition.width;
433 requisition->height += child_requisition.height;
435 /* Request extra space for the padding: */
436 requisition->width += (priv->padding_left + priv->padding_right);
437 requisition->height += (priv->padding_top + priv->padding_bottom);
442 gtk_alignment_size_allocate (GtkWidget *widget,
443 GtkAllocation *allocation)
445 GtkAlignment *alignment;
447 GtkAllocation child_allocation;
448 GtkRequisition child_requisition;
451 gint padding_horizontal, padding_vertical;
452 GtkAlignmentPrivate *priv;
454 padding_horizontal = 0;
455 padding_vertical = 0;
457 widget->allocation = *allocation;
458 alignment = GTK_ALIGNMENT (widget);
459 bin = GTK_BIN (widget);
461 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
463 gtk_widget_get_child_requisition (bin->child, &child_requisition);
465 border_width = GTK_CONTAINER (alignment)->border_width;
467 priv = GTK_ALIGNMENT_GET_PRIVATE (widget);
468 padding_horizontal = priv->padding_left + priv->padding_right;
469 padding_vertical = priv->padding_top + priv->padding_bottom;
471 width = allocation->width - padding_horizontal - 2 * border_width;
472 height = allocation->height - padding_vertical - 2 * border_width;
474 if (width > child_requisition.width)
475 child_allocation.width = (child_requisition.width *
476 (1.0 - alignment->xscale) +
477 width * alignment->xscale);
479 child_allocation.width = width;
481 if (height > child_requisition.height)
482 child_allocation.height = (child_requisition.height *
483 (1.0 - alignment->yscale) +
484 height * alignment->yscale);
486 child_allocation.height = height;
488 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
489 child_allocation.x = (1.0 - alignment->xalign) * (width - child_allocation.width) + allocation->x + border_width + priv->padding_right;
491 child_allocation.x = alignment->xalign * (width - child_allocation.width) + allocation->x + border_width + priv->padding_left;
493 child_allocation.y = alignment->yalign * (height - child_allocation.height) + allocation->y + border_width + priv->padding_top;
495 gtk_widget_size_allocate (bin->child, &child_allocation);
500 * gtk_alignment_set_padding:
501 * @alignment: a #GtkAlignment
502 * @padding_top: the padding at the top of the widget
503 * @padding_bottom: the padding at the bottom of the widget
504 * @padding_left: the padding at the left of the widget
505 * @padding_right: the padding at the right of the widget.
507 * Sets the padding on the different sides of the widget.
508 * The padding adds blank space to the sides of the widget. For instance,
509 * this can be used to indent the child widget towards the right by adding
510 * padding on the left.
515 gtk_alignment_set_padding (GtkAlignment *alignment,
517 guint padding_bottom,
521 GtkAlignmentPrivate *priv;
523 g_return_if_fail (GTK_IS_ALIGNMENT (alignment));
525 priv = GTK_ALIGNMENT_GET_PRIVATE (alignment);
527 g_object_freeze_notify (G_OBJECT (alignment));
529 if (priv->padding_top != padding_top)
531 priv->padding_top = padding_top;
532 g_object_notify (G_OBJECT (alignment), "top-padding");
534 if (priv->padding_bottom != padding_bottom)
536 priv->padding_bottom = padding_bottom;
537 g_object_notify (G_OBJECT (alignment), "bottom-padding");
539 if (priv->padding_left != padding_left)
541 priv->padding_left = padding_left;
542 g_object_notify (G_OBJECT (alignment), "left-padding");
544 if (priv->padding_right != padding_right)
546 priv->padding_right = padding_right;
547 g_object_notify (G_OBJECT (alignment), "right-padding");
550 g_object_thaw_notify (G_OBJECT (alignment));
552 /* Make sure that the widget and children are redrawn with the new setting: */
553 if (GTK_BIN (alignment)->child)
554 gtk_widget_queue_resize (GTK_BIN (alignment)->child);
556 gtk_widget_queue_draw (GTK_WIDGET (alignment));
560 * gtk_alignment_get_padding:
561 * @alignment: a #GtkAlignment
562 * @padding_top: location to store the padding for the top of the widget, or %NULL
563 * @padding_bottom: location to store the padding for the bottom of the widget, or %NULL
564 * @padding_left: location to store the padding for the left of the widget, or %NULL
565 * @padding_right: location to store the padding for the right of the widget, or %NULL
567 * Gets the padding on the different sides of the widget.
568 * See gtk_alignment_set_padding ().
573 gtk_alignment_get_padding (GtkAlignment *alignment,
575 guint *padding_bottom,
577 guint *padding_right)
579 GtkAlignmentPrivate *priv;
581 g_return_if_fail (GTK_IS_ALIGNMENT (alignment));
583 priv = GTK_ALIGNMENT_GET_PRIVATE (alignment);
585 *padding_top = priv->padding_top;
587 *padding_bottom = priv->padding_bottom;
589 *padding_left = priv->padding_left;
591 *padding_right = priv->padding_right;
594 #define __GTK_ALIGNMENT_C__
595 #include "gtkaliasdef.c"