X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkaspectframe.c;h=4b77af282a021f8f5911b3243d3de0a61f772bf5;hb=ad723bd9a9eff4fbf9f828bbecbfe51c88bbf09e;hp=ced7c63116522614e51b66e60b06f9e1f49e5e61;hpb=afee2c67c5091539cbe6270b14e7e74b2a7b60a7;p=~andy%2Fgtk diff --git a/gtk/gtkaspectframe.c b/gtk/gtkaspectframe.c index ced7c6311..4b77af282 100644 --- a/gtk/gtkaspectframe.c +++ b/gtk/gtkaspectframe.c @@ -17,171 +17,230 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ /* - * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +/** + * SECTION:gtkaspectframe + * @Short_description: A frame that constrains its child to a particular aspect ratio + * @Title: GtkAspectFrame + * + * The #GtkAspectFrame is useful when you want + * pack a widget so that it can resize but always retains + * the same aspect ratio. For instance, one might be + * drawing a small preview of a larger image. #GtkAspectFrame + * derives from #GtkFrame, so it can draw a label and + * a frame around the child. The frame will be + * "shrink-wrapped" to the size of the child. + */ + +#include "config.h" + #include "gtkaspectframe.h" +#include "gtksizerequest.h" + +#include "gtkprivate.h" +#include "gtkintl.h" + + + +struct _GtkAspectFramePrivate +{ + GtkAllocation center_allocation; + + gboolean obey_child; + gfloat xalign; + gfloat yalign; + gfloat ratio; +}; + + enum { - ARG_0, - ARG_XALIGN, - ARG_YALIGN, - ARG_RATIO, - ARG_OBEY_CHILD + PROP_0, + PROP_XALIGN, + PROP_YALIGN, + PROP_RATIO, + PROP_OBEY_CHILD }; -static void gtk_aspect_frame_class_init (GtkAspectFrameClass *klass); -static void gtk_aspect_frame_init (GtkAspectFrame *aspect_frame); -static void gtk_aspect_frame_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); -static void gtk_aspect_frame_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); +static void gtk_aspect_frame_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_aspect_frame_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); static void gtk_aspect_frame_compute_child_allocation (GtkFrame *frame, GtkAllocation *child_allocation); #define MAX_RATIO 10000.0 #define MIN_RATIO 0.0001 -static GtkFrameClass *parent_class = NULL; - -GtkType -gtk_aspect_frame_get_type (void) -{ - static GtkType aspect_frame_type = 0; - - if (!aspect_frame_type) - { - static const GtkTypeInfo aspect_frame_info = - { - "GtkAspectFrame", - sizeof (GtkAspectFrame), - sizeof (GtkAspectFrameClass), - (GtkClassInitFunc) gtk_aspect_frame_class_init, - (GtkObjectInitFunc) gtk_aspect_frame_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - aspect_frame_type = gtk_type_unique (GTK_TYPE_FRAME, &aspect_frame_info); - } - - return aspect_frame_type; -} +G_DEFINE_TYPE (GtkAspectFrame, gtk_aspect_frame, GTK_TYPE_FRAME) static void gtk_aspect_frame_class_init (GtkAspectFrameClass *class) { - GtkObjectClass *object_class; + GObjectClass *gobject_class; GtkFrameClass *frame_class; - parent_class = gtk_type_class (GTK_TYPE_FRAME); - - object_class = GTK_OBJECT_CLASS (class); - frame_class = GTK_FRAME_CLASS (class); + gobject_class = (GObjectClass*) class; + frame_class = (GtkFrameClass*) class; - object_class->set_arg = gtk_aspect_frame_set_arg; - object_class->get_arg = gtk_aspect_frame_get_arg; + gobject_class->set_property = gtk_aspect_frame_set_property; + gobject_class->get_property = gtk_aspect_frame_get_property; frame_class->compute_child_allocation = gtk_aspect_frame_compute_child_allocation; - gtk_object_add_arg_type ("GtkAspectFrame::xalign", GTK_TYPE_FLOAT, - GTK_ARG_READWRITE, ARG_XALIGN); - gtk_object_add_arg_type ("GtkAspectFrame::yalign", GTK_TYPE_FLOAT, - GTK_ARG_READWRITE, ARG_YALIGN); - gtk_object_add_arg_type ("GtkAspectFrame::ratio", GTK_TYPE_FLOAT, - GTK_ARG_READWRITE, ARG_RATIO); - gtk_object_add_arg_type ("GtkAspectFrame::obey_child", GTK_TYPE_BOOL, - GTK_ARG_READWRITE, ARG_OBEY_CHILD); + g_object_class_install_property (gobject_class, + PROP_XALIGN, + g_param_spec_float ("xalign", + P_("Horizontal Alignment"), + P_("X alignment of the child"), + 0.0, 1.0, 0.5, + GTK_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_YALIGN, + g_param_spec_float ("yalign", + P_("Vertical Alignment"), + P_("Y alignment of the child"), + 0.0, 1.0, 0.5, + GTK_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_RATIO, + g_param_spec_float ("ratio", + P_("Ratio"), + P_("Aspect ratio if obey_child is FALSE"), + MIN_RATIO, MAX_RATIO, 1.0, + GTK_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_OBEY_CHILD, + g_param_spec_boolean ("obey-child", + P_("Obey child"), + P_("Force aspect ratio to match that of the frame's child"), + TRUE, + GTK_PARAM_READWRITE)); + + g_type_class_add_private (class, sizeof (GtkAspectFramePrivate)); } static void gtk_aspect_frame_init (GtkAspectFrame *aspect_frame) { - aspect_frame->xalign = 0.5; - aspect_frame->yalign = 0.5; - aspect_frame->ratio = 1.0; - aspect_frame->obey_child = TRUE; + GtkAspectFramePrivate *priv; + + aspect_frame->priv = G_TYPE_INSTANCE_GET_PRIVATE (aspect_frame, + GTK_TYPE_ASPECT_FRAME, + GtkAspectFramePrivate); + priv = aspect_frame->priv; + + priv->xalign = 0.5; + priv->yalign = 0.5; + priv->ratio = 1.0; + priv->obey_child = TRUE; } static void -gtk_aspect_frame_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) +gtk_aspect_frame_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (object); + GtkAspectFramePrivate *priv = aspect_frame->priv; - switch (arg_id) + switch (prop_id) { - case ARG_XALIGN: + /* g_object_notify is handled by the _frame_set function */ + case PROP_XALIGN: gtk_aspect_frame_set (aspect_frame, - GTK_VALUE_FLOAT (*arg), - aspect_frame->yalign, - aspect_frame->ratio, - aspect_frame->obey_child); + g_value_get_float (value), + priv->yalign, + priv->ratio, + priv->obey_child); break; - case ARG_YALIGN: + case PROP_YALIGN: gtk_aspect_frame_set (aspect_frame, - aspect_frame->xalign, - GTK_VALUE_FLOAT (*arg), - aspect_frame->ratio, - aspect_frame->obey_child); + priv->xalign, + g_value_get_float (value), + priv->ratio, + priv->obey_child); break; - case ARG_RATIO: + case PROP_RATIO: gtk_aspect_frame_set (aspect_frame, - aspect_frame->xalign, - aspect_frame->yalign, - GTK_VALUE_FLOAT (*arg), - aspect_frame->obey_child); + priv->xalign, + priv->yalign, + g_value_get_float (value), + priv->obey_child); break; - case ARG_OBEY_CHILD: + case PROP_OBEY_CHILD: gtk_aspect_frame_set (aspect_frame, - aspect_frame->xalign, - aspect_frame->yalign, - aspect_frame->ratio, - GTK_VALUE_BOOL (*arg)); + priv->xalign, + priv->yalign, + priv->ratio, + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void -gtk_aspect_frame_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) +gtk_aspect_frame_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (object); + GtkAspectFramePrivate *priv = aspect_frame->priv; - switch (arg_id) + switch (prop_id) { - case ARG_XALIGN: - GTK_VALUE_FLOAT (*arg) = aspect_frame->xalign; + case PROP_XALIGN: + g_value_set_float (value, priv->xalign); break; - case ARG_YALIGN: - GTK_VALUE_FLOAT (*arg) = aspect_frame->yalign; + case PROP_YALIGN: + g_value_set_float (value, priv->yalign); break; - case ARG_RATIO: - GTK_VALUE_FLOAT (*arg) = aspect_frame->ratio; + case PROP_RATIO: + g_value_set_float (value, priv->ratio); break; - case ARG_OBEY_CHILD: - GTK_VALUE_BOOL (*arg) = aspect_frame->obey_child; + case PROP_OBEY_CHILD: + g_value_set_boolean (value, priv->obey_child); break; default: - arg->type = GTK_TYPE_INVALID; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +/** + * gtk_aspect_frame_new: + * @label: Label text. + * @xalign: Horizontal alignment of the child within the allocation of + * the #GtkAspectFrame. This ranges from 0.0 (left aligned) + * to 1.0 (right aligned) + * @yalign: Vertical alignment of the child within the allocation of + * the #GtkAspectFrame. This ranges from 0.0 (top aligned) + * to 1.0 (bottom aligned) + * @ratio: The desired aspect ratio. + * @obey_child: If %TRUE, @ratio is ignored, and the aspect + * ratio is taken from the requistion of the child. + * + * Create a new #GtkAspectFrame. + * + * Returns: the new #GtkAspectFrame. + */ GtkWidget* gtk_aspect_frame_new (const gchar *label, gfloat xalign, @@ -190,19 +249,37 @@ gtk_aspect_frame_new (const gchar *label, gboolean obey_child) { GtkAspectFrame *aspect_frame; + GtkAspectFramePrivate *priv; - aspect_frame = gtk_type_new (gtk_aspect_frame_get_type ()); + aspect_frame = g_object_new (GTK_TYPE_ASPECT_FRAME, NULL); - aspect_frame->xalign = CLAMP (xalign, 0.0, 1.0); - aspect_frame->yalign = CLAMP (yalign, 0.0, 1.0); - aspect_frame->ratio = CLAMP (ratio, MIN_RATIO, MAX_RATIO); - aspect_frame->obey_child = obey_child != FALSE; + priv = aspect_frame->priv; + + priv->xalign = CLAMP (xalign, 0.0, 1.0); + priv->yalign = CLAMP (yalign, 0.0, 1.0); + priv->ratio = CLAMP (ratio, MIN_RATIO, MAX_RATIO); + priv->obey_child = obey_child != FALSE; gtk_frame_set_label (GTK_FRAME(aspect_frame), label); return GTK_WIDGET (aspect_frame); } +/** + * gtk_aspect_frame_set: + * @aspect_frame: a #GtkAspectFrame + * @xalign: Horizontal alignment of the child within the allocation of + * the #GtkAspectFrame. This ranges from 0.0 (left aligned) + * to 1.0 (right aligned) + * @yalign: Vertical alignment of the child within the allocation of + * the #GtkAspectFrame. This ranges from 0.0 (top aligned) + * to 1.0 (bottom aligned) + * @ratio: The desired aspect ratio. + * @obey_child: If %TRUE, @ratio is ignored, and the aspect + * ratio is taken from the requistion of the child. + * + * Set parameters for an existing #GtkAspectFrame. + */ void gtk_aspect_frame_set (GtkAspectFrame *aspect_frame, gfloat xalign, @@ -210,27 +287,47 @@ gtk_aspect_frame_set (GtkAspectFrame *aspect_frame, gfloat ratio, gboolean obey_child) { - g_return_if_fail (aspect_frame != NULL); + GtkAspectFramePrivate *priv; + g_return_if_fail (GTK_IS_ASPECT_FRAME (aspect_frame)); + + priv = aspect_frame->priv; xalign = CLAMP (xalign, 0.0, 1.0); yalign = CLAMP (yalign, 0.0, 1.0); ratio = CLAMP (ratio, MIN_RATIO, MAX_RATIO); obey_child = obey_child != FALSE; - if ((aspect_frame->xalign != xalign) || - (aspect_frame->yalign != yalign) || - (aspect_frame->ratio != ratio) || - (aspect_frame->obey_child != obey_child)) + if (priv->xalign != xalign + || priv->yalign != yalign + || priv->ratio != ratio + || priv->obey_child != obey_child) { - GtkWidget *widget = GTK_WIDGET(aspect_frame); - - aspect_frame->xalign = xalign; - aspect_frame->yalign = yalign; - aspect_frame->ratio = ratio; - aspect_frame->obey_child = obey_child; - - gtk_widget_queue_resize (widget); + g_object_freeze_notify (G_OBJECT (aspect_frame)); + + if (priv->xalign != xalign) + { + priv->xalign = xalign; + g_object_notify (G_OBJECT (aspect_frame), "xalign"); + } + if (priv->yalign != yalign) + { + priv->yalign = yalign; + g_object_notify (G_OBJECT (aspect_frame), "yalign"); + } + if (priv->ratio != ratio) + { + priv->ratio = ratio; + g_object_notify (G_OBJECT (aspect_frame), "ratio"); + } + if (priv->obey_child != obey_child) + { + priv->obey_child = obey_child; + g_object_notify (G_OBJECT (aspect_frame), "obey-child"); + } + g_object_thaw_notify (G_OBJECT (aspect_frame)); + + gtk_widget_queue_resize (GTK_WIDGET (aspect_frame)); } } @@ -239,18 +336,21 @@ gtk_aspect_frame_compute_child_allocation (GtkFrame *frame, GtkAllocation *child_allocation) { GtkAspectFrame *aspect_frame = GTK_ASPECT_FRAME (frame); + GtkAspectFramePrivate *priv = aspect_frame->priv; GtkBin *bin = GTK_BIN (frame); + GtkWidget *child; gdouble ratio; - if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + child = gtk_bin_get_child (bin); + if (child && gtk_widget_get_visible (child)) { GtkAllocation full_allocation; - if (aspect_frame->obey_child) + if (priv->obey_child) { GtkRequisition child_requisition; - gtk_widget_get_child_requisition (bin->child, &child_requisition); + gtk_widget_get_preferred_size (child, &child_requisition, NULL); if (child_requisition.height != 0) { ratio = ((gdouble) child_requisition.width / @@ -264,9 +364,9 @@ gtk_aspect_frame_compute_child_allocation (GtkFrame *frame, ratio = 1.0; } else - ratio = aspect_frame->ratio; + ratio = priv->ratio; - parent_class->compute_child_allocation (frame, &full_allocation); + GTK_FRAME_CLASS (gtk_aspect_frame_parent_class)->compute_child_allocation (frame, &full_allocation); if (ratio * full_allocation.height > full_allocation.width) { @@ -279,9 +379,9 @@ gtk_aspect_frame_compute_child_allocation (GtkFrame *frame, child_allocation->height = full_allocation.height; } - child_allocation->x = full_allocation.x + aspect_frame->xalign * (full_allocation.width - child_allocation->width); - child_allocation->y = full_allocation.y + aspect_frame->yalign * (full_allocation.height - child_allocation->height); + child_allocation->x = full_allocation.x + priv->xalign * (full_allocation.width - child_allocation->width); + child_allocation->y = full_allocation.y + priv->yalign * (full_allocation.height - child_allocation->height); } else - parent_class->compute_child_allocation (frame, child_allocation); + GTK_FRAME_CLASS (gtk_aspect_frame_parent_class)->compute_child_allocation (frame, child_allocation); }