]> Pileus Git - ~andy/gtk/blob - gtk/gtkarrow.c
x
[~andy/gtk] / gtk / gtkarrow.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2001.  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/. 
25  */
26
27 #include <config.h>
28 #include <math.h>
29 #include "gtkalias.h"
30 #include "gtkarrow.h"
31 #include "gtkintl.h"
32
33 #define MIN_ARROW_SIZE  15
34
35 enum {
36   PROP_0,
37
38   PROP_ARROW_TYPE,
39   PROP_SHADOW_TYPE,
40   
41   PROP_LAST
42 };
43
44
45 static void gtk_arrow_class_init (GtkArrowClass  *klass);
46 static void gtk_arrow_init       (GtkArrow       *arrow);
47 static gint gtk_arrow_expose     (GtkWidget      *widget,
48                                   GdkEventExpose *event);
49 static void gtk_arrow_set_property (GObject         *object,
50                                     guint            prop_id,
51                                     const GValue    *value,
52                                     GParamSpec      *pspec);
53 static void gtk_arrow_get_property (GObject         *object,
54                                     guint            prop_id,
55                                     GValue          *value,
56                                     GParamSpec      *pspec);
57
58 GType
59 gtk_arrow_get_type (void)
60 {
61   static GType arrow_type = 0;
62
63   if (!arrow_type)
64     {
65       static const GTypeInfo arrow_info =
66       {
67         sizeof (GtkArrowClass),
68         NULL,           /* base_init */
69         NULL,           /* base_finalize */
70         (GClassInitFunc) gtk_arrow_class_init,
71         NULL,           /* class_finalize */
72         NULL,           /* class_data */
73         sizeof (GtkArrow),
74         0,              /* n_preallocs */
75         (GInstanceInitFunc) gtk_arrow_init,
76       };
77
78       arrow_type = g_type_register_static (GTK_TYPE_MISC, "GtkArrow",
79                                            &arrow_info, 0);
80     }
81
82   return arrow_type;
83 }
84
85 static void
86 gtk_arrow_class_init (GtkArrowClass *class)
87 {
88   GObjectClass *gobject_class;
89   GtkWidgetClass *widget_class;
90
91   gobject_class = (GObjectClass*) class;
92   widget_class = (GtkWidgetClass*) class;
93
94   gobject_class->set_property = gtk_arrow_set_property;
95   gobject_class->get_property = gtk_arrow_get_property;
96   
97   g_object_class_install_property (gobject_class,
98                                    PROP_ARROW_TYPE,
99                                    g_param_spec_enum ("arrow-type",
100                                                       P_("Arrow direction"),
101                                                       P_("The direction the arrow should point"),
102                                                       GTK_TYPE_ARROW_TYPE,
103                                                       GTK_ARROW_RIGHT,
104                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
105   g_object_class_install_property (gobject_class,
106                                    PROP_SHADOW_TYPE,
107                                    g_param_spec_enum ("shadow-type",
108                                                       P_("Arrow shadow"),
109                                                       P_("Appearance of the shadow surrounding the arrow"),
110                                                       GTK_TYPE_SHADOW_TYPE,
111                                                       GTK_SHADOW_OUT,
112                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
113   
114   widget_class->expose_event = gtk_arrow_expose;
115 }
116
117 static void
118 gtk_arrow_set_property (GObject         *object,
119                         guint            prop_id,
120                         const GValue    *value,
121                         GParamSpec      *pspec)
122 {
123   GtkArrow *arrow;
124   
125   arrow = GTK_ARROW (object);
126
127   switch (prop_id)
128     {
129     case PROP_ARROW_TYPE:
130       gtk_arrow_set (arrow,
131                      g_value_get_enum (value),
132                      arrow->shadow_type);
133       break;
134     case PROP_SHADOW_TYPE:
135       gtk_arrow_set (arrow,
136                      arrow->arrow_type,
137                      g_value_get_enum (value));
138       break;
139     default:
140       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
141       break;
142     }
143 }
144
145
146 static void
147 gtk_arrow_get_property (GObject         *object,
148                         guint            prop_id,
149                         GValue          *value,
150                         GParamSpec      *pspec)
151 {
152   GtkArrow *arrow;
153   
154   arrow = GTK_ARROW (object);
155   switch (prop_id)
156     {
157     case PROP_ARROW_TYPE:
158       g_value_set_enum (value, arrow->arrow_type);
159       break;
160     case PROP_SHADOW_TYPE:
161       g_value_set_enum (value, arrow->shadow_type);
162       break;
163     default:
164       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
165       break;
166     }
167 }
168
169 static void
170 gtk_arrow_init (GtkArrow *arrow)
171 {
172   GTK_WIDGET_SET_FLAGS (arrow, GTK_NO_WINDOW);
173
174   GTK_WIDGET (arrow)->requisition.width = MIN_ARROW_SIZE + GTK_MISC (arrow)->xpad * 2;
175   GTK_WIDGET (arrow)->requisition.height = MIN_ARROW_SIZE + GTK_MISC (arrow)->ypad * 2;
176
177   arrow->arrow_type = GTK_ARROW_RIGHT;
178   arrow->shadow_type = GTK_SHADOW_OUT;
179 }
180
181 GtkWidget*
182 gtk_arrow_new (GtkArrowType  arrow_type,
183                GtkShadowType shadow_type)
184 {
185   GtkArrow *arrow;
186
187   arrow = g_object_new (GTK_TYPE_ARROW, NULL);
188
189   arrow->arrow_type = arrow_type;
190   arrow->shadow_type = shadow_type;
191
192   return GTK_WIDGET (arrow);
193 }
194
195 void
196 gtk_arrow_set (GtkArrow      *arrow,
197                GtkArrowType   arrow_type,
198                GtkShadowType  shadow_type)
199 {
200   g_return_if_fail (GTK_IS_ARROW (arrow));
201
202   if (   ((GtkArrowType) arrow->arrow_type != arrow_type)
203       || ((GtkShadowType) arrow->shadow_type != shadow_type))
204     {
205       g_object_freeze_notify (G_OBJECT (arrow));
206
207       if ((GtkArrowType) arrow->arrow_type != arrow_type)
208         {
209           arrow->arrow_type = arrow_type;
210           g_object_notify (G_OBJECT (arrow), "arrow_type");
211         }
212
213       if ((GtkShadowType) arrow->shadow_type != shadow_type)
214         {
215           arrow->shadow_type = shadow_type;
216           g_object_notify (G_OBJECT (arrow), "shadow_type");
217         }
218
219       g_object_thaw_notify (G_OBJECT (arrow));
220
221       if (GTK_WIDGET_DRAWABLE (arrow))
222         gtk_widget_queue_draw (GTK_WIDGET (arrow));
223     }
224 }
225
226
227 static gboolean 
228 gtk_arrow_expose (GtkWidget      *widget,
229                   GdkEventExpose *event)
230 {
231   GtkArrow *arrow;
232   GtkMisc *misc;
233   GtkShadowType shadow_type;
234   gint width, height;
235   gint x, y;
236   gint extent;
237   gfloat xalign;
238   GtkArrowType effective_arrow_type;
239
240   if (GTK_WIDGET_DRAWABLE (widget))
241     {
242       arrow = GTK_ARROW (widget);
243       misc = GTK_MISC (widget);
244
245       width = widget->allocation.width - misc->xpad * 2;
246       height = widget->allocation.height - misc->ypad * 2;
247       extent = MIN (width, height) * 0.7;
248       effective_arrow_type = arrow->arrow_type;
249
250       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
251         xalign = misc->xalign;
252       else
253         {
254           xalign = 1.0 - misc->xalign;
255           if (arrow->arrow_type == GTK_ARROW_LEFT)
256             effective_arrow_type = GTK_ARROW_RIGHT;
257           else if (arrow->arrow_type == GTK_ARROW_RIGHT)
258             effective_arrow_type = GTK_ARROW_LEFT;
259         }
260
261       x = floor (widget->allocation.x + misc->xpad
262                  + ((widget->allocation.width - extent) * xalign)
263                  + 0.5);
264       y = floor (widget->allocation.y + misc->ypad 
265                  + ((widget->allocation.height - extent) * misc->yalign)
266                  + 0.5);
267       
268       shadow_type = arrow->shadow_type;
269
270       if (widget->state == GTK_STATE_ACTIVE)
271         {
272           if (shadow_type == GTK_SHADOW_IN)
273             shadow_type = GTK_SHADOW_OUT;
274           else if (shadow_type == GTK_SHADOW_OUT)
275             shadow_type = GTK_SHADOW_IN;
276           else if (shadow_type == GTK_SHADOW_ETCHED_IN)
277             shadow_type = GTK_SHADOW_ETCHED_OUT;
278           else if (shadow_type == GTK_SHADOW_ETCHED_OUT)
279             shadow_type = GTK_SHADOW_ETCHED_IN;
280         }
281
282       gtk_paint_arrow (widget->style, widget->window,
283                        widget->state, shadow_type,
284                        &event->area, widget, "arrow",
285                        effective_arrow_type, TRUE,
286                        x, y, extent, extent);
287     }
288
289   return FALSE;
290 }