X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkarrow.c;h=fedf544b5e9e59fc6c2297ae12f7d1b7cd3f1d8b;hb=32bd10bf74cd2b7f2d16432d4198dca82c386133;hp=e70f649368cc860a8bc89353866c3c7dd962cad4;hpb=e2a521922085c8010028e227f61bba59ea6b8242;p=~andy%2Fgtk diff --git a/gtk/gtkarrow.c b/gtk/gtkarrow.c index e70f64936..fedf544b5 100644 --- a/gtk/gtkarrow.c +++ b/gtk/gtkarrow.c @@ -2,131 +2,184 @@ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library 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. + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . */ + +/* + * 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:gtkarrow + * @Short_description: Displays an arrow + * @Title: GtkArrow + * @See_also: gtk_render_arrow() + * + * GtkArrow should be used to draw simple arrows that need to point in + * one of the four cardinal directions (up, down, left, or right). The + * style of the arrow can be one of shadow in, shadow out, etched in, or + * etched out. Note that these directions and style types may be + * ammended in versions of GTK+ to come. + * + * GtkArrow will fill any space alloted to it, but since it is inherited + * from #GtkMisc, it can be padded and/or aligned, to fill exactly the + * space the programmer desires. + * + * Arrows are created with a call to gtk_arrow_new(). The direction or + * style of an arrow can be changed after creation by using gtk_arrow_set(). + */ + +#include "config.h" +#include #include "gtkarrow.h" +#include "gtksizerequest.h" +#include "gtktypebuiltins.h" +#include "gtkprivate.h" +#include "gtkintl.h" +#include "a11y/gtkarrowaccessible.h" -#define MIN_ARROW_SIZE 11 +#define MIN_ARROW_SIZE 15 -enum { - ARG_0, - ARG_ARROW_TYPE, - ARG_SHADOW_TYPE +struct _GtkArrowPrivate +{ + gint16 arrow_type; + gint16 shadow_type; }; +enum { + PROP_0, + PROP_ARROW_TYPE, + PROP_SHADOW_TYPE +}; -static void gtk_arrow_class_init (GtkArrowClass *klass); -static void gtk_arrow_init (GtkArrow *arrow); -static gint gtk_arrow_expose (GtkWidget *widget, - GdkEventExpose *event); -static void gtk_arrow_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); -static void gtk_arrow_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); +static void gtk_arrow_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_arrow_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static gboolean gtk_arrow_draw (GtkWidget *widget, + cairo_t *cr); -GtkType -gtk_arrow_get_type (void) -{ - static GtkType arrow_type = 0; +static void gtk_arrow_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_arrow_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); - if (!arrow_type) - { - GtkTypeInfo arrow_info = - { - "GtkArrow", - sizeof (GtkArrow), - sizeof (GtkArrowClass), - (GtkClassInitFunc) gtk_arrow_class_init, - (GtkObjectInitFunc) gtk_arrow_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - arrow_type = gtk_type_unique (GTK_TYPE_MISC, &arrow_info); - } +G_DEFINE_TYPE (GtkArrow, gtk_arrow, GTK_TYPE_MISC) - return arrow_type; -} static void gtk_arrow_class_init (GtkArrowClass *class) { - GtkObjectClass *object_class; + GObjectClass *gobject_class; GtkWidgetClass *widget_class; - object_class = (GtkObjectClass*) class; + gobject_class = (GObjectClass*) class; widget_class = (GtkWidgetClass*) class; - gtk_object_add_arg_type ("GtkArrow::arrow_type", GTK_TYPE_ARROW_TYPE, GTK_ARG_READWRITE, ARG_ARROW_TYPE); - gtk_object_add_arg_type ("GtkArrow::shadow_type", GTK_TYPE_SHADOW_TYPE, GTK_ARG_READWRITE, ARG_SHADOW_TYPE); - - object_class->set_arg = gtk_arrow_set_arg; - object_class->get_arg = gtk_arrow_get_arg; - - widget_class->expose_event = gtk_arrow_expose; + gobject_class->set_property = gtk_arrow_set_property; + gobject_class->get_property = gtk_arrow_get_property; + + widget_class->draw = gtk_arrow_draw; + widget_class->get_preferred_width = gtk_arrow_get_preferred_width; + widget_class->get_preferred_height = gtk_arrow_get_preferred_height; + + g_object_class_install_property (gobject_class, + PROP_ARROW_TYPE, + g_param_spec_enum ("arrow-type", + P_("Arrow direction"), + P_("The direction the arrow should point"), + GTK_TYPE_ARROW_TYPE, + GTK_ARROW_RIGHT, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_SHADOW_TYPE, + g_param_spec_enum ("shadow-type", + P_("Arrow shadow"), + P_("Appearance of the shadow surrounding the arrow"), + GTK_TYPE_SHADOW_TYPE, + GTK_SHADOW_OUT, + GTK_PARAM_READWRITE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_float ("arrow-scaling", + P_("Arrow Scaling"), + P_("Amount of space used up by arrow"), + 0.0, 1.0, 0.7, + GTK_PARAM_READABLE)); + + g_type_class_add_private (class, sizeof (GtkArrowPrivate)); + + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ARROW_ACCESSIBLE); } static void -gtk_arrow_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) +gtk_arrow_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - GtkArrow *arrow; - - arrow = GTK_ARROW (object); + GtkArrow *arrow = GTK_ARROW (object); + GtkArrowPrivate *priv = arrow->priv; - switch (arg_id) + switch (prop_id) { - case ARG_ARROW_TYPE: + case PROP_ARROW_TYPE: gtk_arrow_set (arrow, - GTK_VALUE_ENUM (*arg), - arrow->shadow_type); + g_value_get_enum (value), + priv->shadow_type); break; - case ARG_SHADOW_TYPE: + case PROP_SHADOW_TYPE: gtk_arrow_set (arrow, - arrow->arrow_type, - GTK_VALUE_ENUM (*arg)); + priv->arrow_type, + g_value_get_enum (value)); break; default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void -gtk_arrow_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) +gtk_arrow_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - GtkArrow *arrow; + GtkArrow *arrow = GTK_ARROW (object); + GtkArrowPrivate *priv = arrow->priv; - arrow = GTK_ARROW (object); - switch (arg_id) + switch (prop_id) { - case ARG_ARROW_TYPE: - GTK_VALUE_ENUM (*arg) = arrow->arrow_type; + case PROP_ARROW_TYPE: + g_value_set_enum (value, priv->arrow_type); break; - case ARG_SHADOW_TYPE: - GTK_VALUE_ENUM (*arg) = arrow->shadow_type; + case PROP_SHADOW_TYPE: + g_value_set_enum (value, priv->shadow_type); break; default: - arg->type = GTK_TYPE_INVALID; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } @@ -134,98 +187,183 @@ gtk_arrow_get_arg (GtkObject *object, static void gtk_arrow_init (GtkArrow *arrow) { - GTK_WIDGET_SET_FLAGS (arrow, GTK_NO_WINDOW); + GtkArrowPrivate *priv; + + arrow->priv = G_TYPE_INSTANCE_GET_PRIVATE (arrow, + GTK_TYPE_ARROW, + GtkArrowPrivate); + priv = arrow->priv; + + gtk_widget_set_has_window (GTK_WIDGET (arrow), FALSE); + + priv->arrow_type = GTK_ARROW_RIGHT; + priv->shadow_type = GTK_SHADOW_OUT; +} + +static void +gtk_arrow_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + GtkBorder border; - GTK_WIDGET (arrow)->requisition.width = MIN_ARROW_SIZE + GTK_MISC (arrow)->xpad * 2; - GTK_WIDGET (arrow)->requisition.height = MIN_ARROW_SIZE + GTK_MISC (arrow)->ypad * 2; + _gtk_misc_get_padding_and_border (GTK_MISC (widget), &border); - arrow->arrow_type = GTK_ARROW_RIGHT; - arrow->shadow_type = GTK_SHADOW_OUT; + if (minimum_size) + *minimum_size = MIN_ARROW_SIZE + border.left + border.right; + + if (natural_size) + *natural_size = MIN_ARROW_SIZE + border.left + border.right; } +static void +gtk_arrow_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + GtkBorder border; + + _gtk_misc_get_padding_and_border (GTK_MISC (widget), &border); + + if (minimum_size) + *minimum_size = MIN_ARROW_SIZE + border.top + border.bottom; + + if (natural_size) + *natural_size = MIN_ARROW_SIZE + border.top + border.bottom; +} + +/** + * gtk_arrow_new: + * @arrow_type: a valid #GtkArrowType. + * @shadow_type: a valid #GtkShadowType. + * + * Creates a new #GtkArrow widget. + * + * Returns: the new #GtkArrow widget. + */ GtkWidget* gtk_arrow_new (GtkArrowType arrow_type, GtkShadowType shadow_type) { + GtkArrowPrivate *priv; GtkArrow *arrow; - arrow = gtk_type_new (GTK_TYPE_ARROW); + arrow = g_object_new (GTK_TYPE_ARROW, NULL); + + priv = arrow->priv; - arrow->arrow_type = arrow_type; - arrow->shadow_type = shadow_type; + priv->arrow_type = arrow_type; + priv->shadow_type = shadow_type; return GTK_WIDGET (arrow); } +/** + * gtk_arrow_set: + * @arrow: a widget of type #GtkArrow. + * @arrow_type: a valid #GtkArrowType. + * @shadow_type: a valid #GtkShadowType. + * + * Sets the direction and style of the #GtkArrow, @arrow. + */ void gtk_arrow_set (GtkArrow *arrow, GtkArrowType arrow_type, GtkShadowType shadow_type) { - g_return_if_fail (arrow != NULL); + GtkArrowPrivate *priv; + GtkWidget *widget; + g_return_if_fail (GTK_IS_ARROW (arrow)); - if (((GtkArrowType) arrow->arrow_type != arrow_type) || - ((GtkShadowType) arrow->shadow_type != shadow_type)) + priv = arrow->priv; + + if (priv->arrow_type != arrow_type + || priv->shadow_type != shadow_type) { - arrow->arrow_type = arrow_type; - arrow->shadow_type = shadow_type; + g_object_freeze_notify (G_OBJECT (arrow)); - if (GTK_WIDGET_DRAWABLE (arrow)) - gtk_widget_queue_clear (GTK_WIDGET (arrow)); + if ((GtkArrowType) priv->arrow_type != arrow_type) + { + priv->arrow_type = arrow_type; + g_object_notify (G_OBJECT (arrow), "arrow-type"); + } + + if (priv->shadow_type != shadow_type) + { + priv->shadow_type = shadow_type; + g_object_notify (G_OBJECT (arrow), "shadow-type"); + } + + g_object_thaw_notify (G_OBJECT (arrow)); + + widget = GTK_WIDGET (arrow); + if (gtk_widget_is_drawable (widget)) + gtk_widget_queue_draw (widget); } } - -static gint -gtk_arrow_expose (GtkWidget *widget, - GdkEventExpose *event) +static gboolean +gtk_arrow_draw (GtkWidget *widget, + cairo_t *cr) { - GtkArrow *arrow; - GtkMisc *misc; - GtkShadowType shadow_type; + GtkArrow *arrow = GTK_ARROW (widget); + GtkArrowPrivate *priv = arrow->priv; + GtkStyleContext *context; + gdouble x, y; gint width, height; - gint x, y; gint extent; + GtkBorder border; + gfloat xalign, yalign; + GtkArrowType effective_arrow_type; + gfloat arrow_scaling; + gdouble angle; + + if (priv->arrow_type == GTK_ARROW_NONE) + return FALSE; + + context = gtk_widget_get_style_context (widget); + gtk_widget_style_get (widget, "arrow-scaling", &arrow_scaling, NULL); + + _gtk_misc_get_padding_and_border (GTK_MISC (widget), &border); + gtk_misc_get_alignment (GTK_MISC (widget), &xalign, &yalign); - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_ARROW (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); + width = gtk_widget_get_allocated_width (widget) - border.left - border.right; + height = gtk_widget_get_allocated_height (widget) - border.top - border.bottom; - if (GTK_WIDGET_DRAWABLE (widget)) + extent = MIN (width, height) * arrow_scaling; + effective_arrow_type = priv->arrow_type; + + if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR) { - arrow = GTK_ARROW (widget); - misc = GTK_MISC (widget); - - width = widget->allocation.width - misc->xpad * 2; - height = widget->allocation.height - misc->ypad * 2; - extent = MIN (width, height); - - x = ((widget->allocation.x + misc->xpad) * (1.0 - misc->xalign) + - (widget->allocation.x + widget->allocation.width - extent - misc->xpad) * misc->xalign); - y = ((widget->allocation.y + misc->ypad) * (1.0 - misc->yalign) + - (widget->allocation.y + widget->allocation.height - extent - misc->ypad) * misc->yalign); - - shadow_type = arrow->shadow_type; - - if (widget->state == GTK_STATE_ACTIVE) - { - if (shadow_type == GTK_SHADOW_IN) - shadow_type = GTK_SHADOW_OUT; - else if (shadow_type == GTK_SHADOW_OUT) - shadow_type = GTK_SHADOW_IN; - else if (shadow_type == GTK_SHADOW_ETCHED_IN) - shadow_type = GTK_SHADOW_ETCHED_OUT; - else if (shadow_type == GTK_SHADOW_ETCHED_OUT) - shadow_type = GTK_SHADOW_ETCHED_IN; - } - - gtk_paint_arrow (widget->style, widget->window, - widget->state, shadow_type, - &event->area, widget, "arrow", - arrow->arrow_type, TRUE, - x, y, extent, extent); + xalign = 1.0 - xalign; + if (priv->arrow_type == GTK_ARROW_LEFT) + effective_arrow_type = GTK_ARROW_RIGHT; + else if (priv->arrow_type == GTK_ARROW_RIGHT) + effective_arrow_type = GTK_ARROW_LEFT; } - return TRUE; + x = border.left + ((width - extent) * xalign); + y = border.top + ((height - extent) * yalign); + + switch (effective_arrow_type) + { + case GTK_ARROW_UP: + angle = 0; + break; + case GTK_ARROW_RIGHT: + angle = G_PI / 2; + break; + case GTK_ARROW_DOWN: + angle = G_PI; + break; + case GTK_ARROW_LEFT: + default: + angle = (3 * G_PI) / 2; + break; + } + + gtk_render_arrow (context, cr, angle, x, y, extent); + + return FALSE; }