]> Pileus Git - ~andy/gtk/blob - gtk/gtkaspectframe.c
Deprecate widget flag: GTK_WIDGET_VISIBLE
[~andy/gtk] / gtk / gtkaspectframe.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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
6  *
7  *     Copyright Owen Taylor                          4/9/97
8  *
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.
13  *
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.
18  *
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.
23  */
24
25 /*
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/. 
30  */
31
32 #include "config.h"
33 #include "gtkaspectframe.h"
34 #include "gtkprivate.h"
35 #include "gtkintl.h"
36 #include "gtkalias.h"
37
38 enum {
39   PROP_0,
40   PROP_XALIGN,
41   PROP_YALIGN,
42   PROP_RATIO,
43   PROP_OBEY_CHILD
44 };
45
46 static void gtk_aspect_frame_set_property (GObject         *object,
47                                            guint            prop_id,
48                                            const GValue    *value,
49                                            GParamSpec      *pspec);
50 static void gtk_aspect_frame_get_property (GObject         *object,
51                                            guint            prop_id,
52                                            GValue          *value,
53                                            GParamSpec      *pspec);
54 static void gtk_aspect_frame_compute_child_allocation (GtkFrame            *frame,
55                                                        GtkAllocation       *child_allocation);
56
57 #define MAX_RATIO 10000.0
58 #define MIN_RATIO 0.0001
59
60 G_DEFINE_TYPE (GtkAspectFrame, gtk_aspect_frame, GTK_TYPE_FRAME)
61
62 static void
63 gtk_aspect_frame_class_init (GtkAspectFrameClass *class)
64 {
65   GObjectClass *gobject_class;
66   GtkFrameClass *frame_class;
67   
68   gobject_class = (GObjectClass*) class;
69   frame_class = (GtkFrameClass*) class;
70   
71   gobject_class->set_property = gtk_aspect_frame_set_property;
72   gobject_class->get_property = gtk_aspect_frame_get_property;
73
74   frame_class->compute_child_allocation = gtk_aspect_frame_compute_child_allocation;
75
76   g_object_class_install_property (gobject_class,
77                                    PROP_XALIGN,
78                                    g_param_spec_float ("xalign",
79                                                        P_("Horizontal Alignment"),
80                                                        P_("X alignment of the child"),
81                                                        0.0, 1.0, 0.5,
82                                                        GTK_PARAM_READWRITE));
83   g_object_class_install_property (gobject_class,
84                                    PROP_YALIGN,
85                                    g_param_spec_float ("yalign",
86                                                        P_("Vertical Alignment"),
87                                                        P_("Y alignment of the child"),
88                                                        0.0, 1.0, 0.5,
89                                                        GTK_PARAM_READWRITE));
90   g_object_class_install_property (gobject_class,
91                                    PROP_RATIO,
92                                    g_param_spec_float ("ratio",
93                                                        P_("Ratio"),
94                                                        P_("Aspect ratio if obey_child is FALSE"),
95                                                        MIN_RATIO, MAX_RATIO, 1.0,
96                                                        GTK_PARAM_READWRITE));
97   g_object_class_install_property (gobject_class,
98                                    PROP_OBEY_CHILD,
99                                    g_param_spec_boolean ("obey-child",
100                                                          P_("Obey child"),
101                                                          P_("Force aspect ratio to match that of the frame's child"),
102                                                          TRUE,
103                                                          GTK_PARAM_READWRITE));
104 }
105
106 static void
107 gtk_aspect_frame_init (GtkAspectFrame *aspect_frame)
108 {
109   aspect_frame->xalign = 0.5;
110   aspect_frame->yalign = 0.5;
111   aspect_frame->ratio = 1.0;
112   aspect_frame->obey_child = TRUE;
113 }
114
115 static void
116 gtk_aspect_frame_set_property (GObject         *object,
117                                guint            prop_id,
118                                const GValue    *value,
119                                GParamSpec      *pspec)
120 {
121   GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (object);
122   
123   switch (prop_id)
124     {
125       /* g_object_notify is handled by the _frame_set function */
126     case PROP_XALIGN:
127       gtk_aspect_frame_set (aspect_frame,
128                             g_value_get_float (value),
129                             aspect_frame->yalign,
130                             aspect_frame->ratio,
131                             aspect_frame->obey_child);
132       break;
133     case PROP_YALIGN:
134       gtk_aspect_frame_set (aspect_frame,
135                             aspect_frame->xalign,
136                             g_value_get_float (value),
137                             aspect_frame->ratio,
138                             aspect_frame->obey_child);
139       break;
140     case PROP_RATIO:
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);
146       break;
147     case PROP_OBEY_CHILD:
148       gtk_aspect_frame_set (aspect_frame,
149                             aspect_frame->xalign,
150                             aspect_frame->yalign,
151                             aspect_frame->ratio,
152                             g_value_get_boolean (value));
153       break;
154     default:
155        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
156       break;
157     }
158 }
159
160 static void
161 gtk_aspect_frame_get_property (GObject         *object,
162                                guint            prop_id,
163                                GValue          *value,
164                                GParamSpec      *pspec)
165 {
166   GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (object);
167   
168   switch (prop_id)
169     {
170     case PROP_XALIGN:
171       g_value_set_float (value, aspect_frame->xalign);
172       break;
173     case PROP_YALIGN:
174       g_value_set_float (value, aspect_frame->yalign);
175       break;
176     case PROP_RATIO:
177       g_value_set_float (value, aspect_frame->ratio);
178       break;
179     case PROP_OBEY_CHILD:
180       g_value_set_boolean (value, aspect_frame->obey_child);
181       break;
182     default:
183        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
184       break;
185     }
186 }
187
188 GtkWidget*
189 gtk_aspect_frame_new (const gchar *label,
190                       gfloat       xalign,
191                       gfloat       yalign,
192                       gfloat       ratio,
193                       gboolean     obey_child)
194 {
195   GtkAspectFrame *aspect_frame;
196
197   aspect_frame = g_object_new (GTK_TYPE_ASPECT_FRAME, NULL);
198
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;
203
204   gtk_frame_set_label (GTK_FRAME(aspect_frame), label);
205
206   return GTK_WIDGET (aspect_frame);
207 }
208
209 void
210 gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
211                       gfloat          xalign,
212                       gfloat          yalign,
213                       gfloat          ratio,
214                       gboolean        obey_child)
215 {
216   g_return_if_fail (GTK_IS_ASPECT_FRAME (aspect_frame));
217   
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;
222   
223   if (   (aspect_frame->xalign != xalign)
224       || (aspect_frame->yalign != yalign)
225       || (aspect_frame->ratio != ratio)
226       || (aspect_frame->obey_child != obey_child))
227     {
228       g_object_freeze_notify (G_OBJECT (aspect_frame));
229
230       if (aspect_frame->xalign != xalign)
231         {
232           aspect_frame->xalign = xalign;
233           g_object_notify (G_OBJECT (aspect_frame), "xalign");
234         }
235       if (aspect_frame->yalign != yalign)
236         {
237           aspect_frame->yalign = yalign;
238           g_object_notify (G_OBJECT (aspect_frame), "yalign");
239         }
240       if (aspect_frame->ratio != ratio)
241         {
242           aspect_frame->ratio = ratio;
243           g_object_notify (G_OBJECT (aspect_frame), "ratio");
244         }
245       if (aspect_frame->obey_child != obey_child)
246         {
247           aspect_frame->obey_child = obey_child;
248           g_object_notify (G_OBJECT (aspect_frame), "obey-child");
249         }
250       g_object_thaw_notify (G_OBJECT (aspect_frame));
251
252       gtk_widget_queue_resize (GTK_WIDGET (aspect_frame));
253     }
254 }
255
256 static void
257 gtk_aspect_frame_compute_child_allocation (GtkFrame      *frame,
258                                            GtkAllocation *child_allocation)
259 {
260   GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (frame);
261   GtkBin *bin = GTK_BIN (frame);
262   gdouble ratio;
263
264   if (bin->child && gtk_widget_get_visible (bin->child))
265     {
266       GtkAllocation full_allocation;
267       
268       if (aspect_frame->obey_child)
269         {
270           GtkRequisition child_requisition;
271
272           gtk_widget_get_child_requisition (bin->child, &child_requisition);
273           if (child_requisition.height != 0)
274             {
275               ratio = ((gdouble) child_requisition.width /
276                        child_requisition.height);
277               if (ratio < MIN_RATIO)
278                 ratio = MIN_RATIO;
279             }
280           else if (child_requisition.width != 0)
281             ratio = MAX_RATIO;
282           else
283             ratio = 1.0;
284         }
285       else
286         ratio = aspect_frame->ratio;
287
288       GTK_FRAME_CLASS (gtk_aspect_frame_parent_class)->compute_child_allocation (frame, &full_allocation);
289       
290       if (ratio * full_allocation.height > full_allocation.width)
291         {
292           child_allocation->width = full_allocation.width;
293           child_allocation->height = full_allocation.width / ratio + 0.5;
294         }
295       else
296         {
297           child_allocation->width = ratio * full_allocation.height + 0.5;
298           child_allocation->height = full_allocation.height;
299         }
300       
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);
303     }
304   else
305     GTK_FRAME_CLASS (gtk_aspect_frame_parent_class)->compute_child_allocation (frame, child_allocation);
306 }
307
308 #define __GTK_ASPECT_FRAME_C__
309 #include "gtkaliasdef.c"