1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GtkAspectFrame: Ensure that the child window has a specified aspect ratio
5 * or, if obey_child, has the same aspect ratio as its requested size
7 * Copyright Owen Taylor 4/9/97
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS
27 * file for a list of people on the GTK+ Team. See the ChangeLog
28 * files for a list of changes. These files are distributed with
29 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 #include "gtkaspectframe.h"
34 #include "gtkprivate.h"
46 static void gtk_aspect_frame_set_property (GObject *object,
50 static void gtk_aspect_frame_get_property (GObject *object,
54 static void gtk_aspect_frame_compute_child_allocation (GtkFrame *frame,
55 GtkAllocation *child_allocation);
57 #define MAX_RATIO 10000.0
58 #define MIN_RATIO 0.0001
60 G_DEFINE_TYPE (GtkAspectFrame, gtk_aspect_frame, GTK_TYPE_FRAME)
63 gtk_aspect_frame_class_init (GtkAspectFrameClass *class)
65 GObjectClass *gobject_class;
66 GtkFrameClass *frame_class;
68 gobject_class = (GObjectClass*) class;
69 frame_class = (GtkFrameClass*) class;
71 gobject_class->set_property = gtk_aspect_frame_set_property;
72 gobject_class->get_property = gtk_aspect_frame_get_property;
74 frame_class->compute_child_allocation = gtk_aspect_frame_compute_child_allocation;
76 g_object_class_install_property (gobject_class,
78 g_param_spec_float ("xalign",
79 P_("Horizontal Alignment"),
80 P_("X alignment of the child"),
82 GTK_PARAM_READWRITE));
83 g_object_class_install_property (gobject_class,
85 g_param_spec_float ("yalign",
86 P_("Vertical Alignment"),
87 P_("Y alignment of the child"),
89 GTK_PARAM_READWRITE));
90 g_object_class_install_property (gobject_class,
92 g_param_spec_float ("ratio",
94 P_("Aspect ratio if obey_child is FALSE"),
95 MIN_RATIO, MAX_RATIO, 0.5,
96 GTK_PARAM_READWRITE));
97 g_object_class_install_property (gobject_class,
99 g_param_spec_boolean ("obey-child",
101 P_("Force aspect ratio to match that of the frame's child"),
103 GTK_PARAM_READWRITE));
107 gtk_aspect_frame_init (GtkAspectFrame *aspect_frame)
109 aspect_frame->xalign = 0.5;
110 aspect_frame->yalign = 0.5;
111 aspect_frame->ratio = 1.0;
112 aspect_frame->obey_child = TRUE;
116 gtk_aspect_frame_set_property (GObject *object,
121 GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (object);
125 /* g_object_notify is handled by the _frame_set function */
127 gtk_aspect_frame_set (aspect_frame,
128 g_value_get_float (value),
129 aspect_frame->yalign,
131 aspect_frame->obey_child);
134 gtk_aspect_frame_set (aspect_frame,
135 aspect_frame->xalign,
136 g_value_get_float (value),
138 aspect_frame->obey_child);
141 gtk_aspect_frame_set (aspect_frame,
142 aspect_frame->xalign,
143 aspect_frame->yalign,
144 g_value_get_float (value),
145 aspect_frame->obey_child);
147 case PROP_OBEY_CHILD:
148 gtk_aspect_frame_set (aspect_frame,
149 aspect_frame->xalign,
150 aspect_frame->yalign,
152 g_value_get_boolean (value));
155 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
161 gtk_aspect_frame_get_property (GObject *object,
166 GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (object);
171 g_value_set_float (value, aspect_frame->xalign);
174 g_value_set_float (value, aspect_frame->yalign);
177 g_value_set_float (value, aspect_frame->ratio);
179 case PROP_OBEY_CHILD:
180 g_value_set_boolean (value, aspect_frame->obey_child);
183 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
189 gtk_aspect_frame_new (const gchar *label,
195 GtkAspectFrame *aspect_frame;
197 aspect_frame = g_object_new (GTK_TYPE_ASPECT_FRAME, NULL);
199 aspect_frame->xalign = CLAMP (xalign, 0.0, 1.0);
200 aspect_frame->yalign = CLAMP (yalign, 0.0, 1.0);
201 aspect_frame->ratio = CLAMP (ratio, MIN_RATIO, MAX_RATIO);
202 aspect_frame->obey_child = obey_child != FALSE;
204 gtk_frame_set_label (GTK_FRAME(aspect_frame), label);
206 return GTK_WIDGET (aspect_frame);
210 gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
216 g_return_if_fail (GTK_IS_ASPECT_FRAME (aspect_frame));
218 xalign = CLAMP (xalign, 0.0, 1.0);
219 yalign = CLAMP (yalign, 0.0, 1.0);
220 ratio = CLAMP (ratio, MIN_RATIO, MAX_RATIO);
221 obey_child = obey_child != FALSE;
223 if ( (aspect_frame->xalign != xalign)
224 || (aspect_frame->yalign != yalign)
225 || (aspect_frame->ratio != ratio)
226 || (aspect_frame->obey_child != obey_child))
228 g_object_freeze_notify (G_OBJECT (aspect_frame));
230 if (aspect_frame->xalign != xalign)
232 aspect_frame->xalign = xalign;
233 g_object_notify (G_OBJECT (aspect_frame), "xalign");
235 if (aspect_frame->yalign != yalign)
237 aspect_frame->yalign = yalign;
238 g_object_notify (G_OBJECT (aspect_frame), "yalign");
240 if (aspect_frame->ratio != ratio)
242 aspect_frame->ratio = ratio;
243 g_object_notify (G_OBJECT (aspect_frame), "ratio");
245 if (aspect_frame->obey_child != obey_child)
247 aspect_frame->obey_child = obey_child;
248 g_object_notify (G_OBJECT (aspect_frame), "obey-child");
250 g_object_thaw_notify (G_OBJECT (aspect_frame));
252 gtk_widget_queue_resize (GTK_WIDGET (aspect_frame));
257 gtk_aspect_frame_compute_child_allocation (GtkFrame *frame,
258 GtkAllocation *child_allocation)
260 GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (frame);
261 GtkBin *bin = GTK_BIN (frame);
264 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
266 GtkAllocation full_allocation;
268 if (aspect_frame->obey_child)
270 GtkRequisition child_requisition;
272 gtk_widget_get_child_requisition (bin->child, &child_requisition);
273 if (child_requisition.height != 0)
275 ratio = ((gdouble) child_requisition.width /
276 child_requisition.height);
277 if (ratio < MIN_RATIO)
280 else if (child_requisition.width != 0)
286 ratio = aspect_frame->ratio;
288 GTK_FRAME_CLASS (gtk_aspect_frame_parent_class)->compute_child_allocation (frame, &full_allocation);
290 if (ratio * full_allocation.height > full_allocation.width)
292 child_allocation->width = full_allocation.width;
293 child_allocation->height = full_allocation.width / ratio + 0.5;
297 child_allocation->width = ratio * full_allocation.height + 0.5;
298 child_allocation->height = full_allocation.height;
301 child_allocation->x = full_allocation.x + aspect_frame->xalign * (full_allocation.width - child_allocation->width);
302 child_allocation->y = full_allocation.y + aspect_frame->yalign * (full_allocation.height - child_allocation->height);
305 GTK_FRAME_CLASS (gtk_aspect_frame_parent_class)->compute_child_allocation (frame, child_allocation);
308 #define __GTK_ASPECT_FRAME_C__
309 #include "gtkaliasdef.c"