1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2008, Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library 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.
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 * Library General Public License for more details.
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.
23 * @title: AdgArrowStyle
24 * @short_description: Arrow rendering related stuff
26 * Contains parameters on how to draw arrows, providing a way to register a
27 * custom rendering callback.
30 #include "adg-arrow-style.h"
31 #include "adg-arrow-style-private.h"
37 #define PARENT_CLASS ((AdgStyleClass *) adg_arrow_style_parent_class)
50 static void get_property (GObject
*object
,
54 static void set_property (GObject
*object
,
58 static void arrow_renderer (AdgArrowStyle
*arrow_style
,
61 static void triangle_renderer (AdgArrowStyle
*arrow_style
,
64 static void dot_renderer (AdgArrowStyle
*arrow_style
,
67 static void circle_renderer (AdgArrowStyle
*arrow_style
,
70 static void block_renderer (AdgArrowStyle
*arrow_style
,
73 static void square_renderer (AdgArrowStyle
*arrow_style
,
76 static void tick_renderer (AdgArrowStyle
*arrow_style
,
79 static void draw_triangle (cairo_t
*cr
,
80 AdgArrowStyle
*arrow_style
,
82 static void draw_circle (cairo_t
*cr
,
83 AdgArrowStyle
*arrow_style
,
87 G_DEFINE_TYPE (AdgArrowStyle
, adg_arrow_style
, ADG_TYPE_STYLE
)
91 adg_arrow_style_class_init (AdgArrowStyleClass
*klass
)
93 GObjectClass
*gobject_class
;
96 gobject_class
= (GObjectClass
*) klass
;
98 g_type_class_add_private (klass
, sizeof (AdgArrowStylePrivate
));
100 gobject_class
->get_property
= get_property
;
101 gobject_class
->set_property
= set_property
;
103 param
= g_param_spec_double ("size",
105 P_("The size of the arrow, a renderer dependent parameter"),
106 -G_MAXDOUBLE
, G_MAXDOUBLE
, 14.,
108 g_object_class_install_property (gobject_class
, PROP_SIZE
, param
);
110 param
= g_param_spec_double ("angle",
112 P_("The angle of the arrow, a renderer dependent parameter"),
113 -G_MAXDOUBLE
, G_MAXDOUBLE
, G_PI
/ 6.,
115 g_object_class_install_property (gobject_class
, PROP_ANGLE
, param
);
117 param
= g_param_spec_double ("margin",
119 P_("The margin of the arrow, a renderer dependent parameter"),
120 -G_MAXDOUBLE
, G_MAXDOUBLE
, 14.,
122 g_object_class_install_property (gobject_class
, PROP_MARGIN
, param
);
124 param
= g_param_spec_pointer ("renderer",
125 P_("Renderer Callback"),
126 P_("The callback to call to renderer this arrow type"),
128 g_object_class_install_property (gobject_class
, PROP_RENDERER
, param
);
132 adg_arrow_style_init (AdgArrowStyle
*arrow_style
)
134 AdgArrowStylePrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (arrow_style
,
135 ADG_TYPE_ARROW_STYLE
,
136 AdgArrowStylePrivate
);
139 priv
->angle
= G_PI
/ 6.;
141 priv
->renderer
= NULL
;
143 arrow_style
->priv
= priv
;
147 get_property (GObject
*object
,
152 AdgArrowStyle
*arrow_style
= (AdgArrowStyle
*) object
;
157 g_value_set_double (value
, arrow_style
->priv
->size
);
160 g_value_set_double (value
, arrow_style
->priv
->angle
);
163 g_value_set_double (value
, arrow_style
->priv
->margin
);
166 g_value_set_pointer (value
, arrow_style
->priv
->renderer
);
169 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
175 set_property (GObject
*object
,
180 AdgArrowStyle
*arrow_style
= (AdgArrowStyle
*) object
;
185 arrow_style
->priv
->size
= g_value_get_double (value
);
188 arrow_style
->priv
->angle
= g_value_get_double (value
);
191 arrow_style
->priv
->margin
= g_value_get_double (value
);
194 arrow_style
->priv
->renderer
= g_value_get_pointer (value
);
197 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
204 adg_arrow_style_from_id (AdgArrowStyleId id
)
206 static AdgStyle
**builtins
= NULL
;
208 if G_UNLIKELY (builtins
== NULL
)
210 builtins
= g_new (AdgStyle
*, ADG_ARROW_STYLE_LAST
);
212 builtins
[ADG_ARROW_STYLE_ARROW
] = g_object_new (ADG_TYPE_ARROW_STYLE
,
213 "renderer", arrow_renderer
,
215 builtins
[ADG_ARROW_STYLE_TRIANGLE
] = g_object_new (ADG_TYPE_ARROW_STYLE
,
216 "renderer", triangle_renderer
,
218 builtins
[ADG_ARROW_STYLE_DOT
] = g_object_new (ADG_TYPE_ARROW_STYLE
,
222 "renderer", dot_renderer
,
224 builtins
[ADG_ARROW_STYLE_CIRCLE
] = g_object_new (ADG_TYPE_ARROW_STYLE
,
228 "renderer", circle_renderer
,
230 builtins
[ADG_ARROW_STYLE_BLOCK
] = g_object_new (ADG_TYPE_ARROW_STYLE
,
234 "renderer", block_renderer
,
236 builtins
[ADG_ARROW_STYLE_SQUARE
] = g_object_new (ADG_TYPE_ARROW_STYLE
,
240 "renderer", square_renderer
,
242 builtins
[ADG_ARROW_STYLE_TICK
] = g_object_new (ADG_TYPE_ARROW_STYLE
,
246 "renderer", tick_renderer
,
250 g_return_val_if_fail (id
< ADG_ARROW_STYLE_LAST
, NULL
);
255 adg_arrow_style_render (AdgArrowStyle
*arrow_style
,
259 g_return_if_fail (arrow_style
!= NULL
);
260 g_return_if_fail (cr
!= NULL
);
261 g_return_if_fail (segment
!= NULL
);
264 if (arrow_style
->priv
->renderer
== NULL
)
267 arrow_style
->priv
->renderer (arrow_style
, cr
, segment
);
271 arrow_renderer (AdgArrowStyle
*arrow_style
,
275 draw_triangle (cr
, arrow_style
, segment
);
280 triangle_renderer (AdgArrowStyle
*arrow_style
,
284 draw_triangle (cr
, arrow_style
, segment
);
289 dot_renderer (AdgArrowStyle
*arrow_style
,
293 draw_circle (cr
, arrow_style
, segment
);
298 circle_renderer (AdgArrowStyle
*arrow_style
,
302 draw_circle (cr
, arrow_style
, segment
);
307 block_renderer (AdgArrowStyle
*arrow_style
,
315 square_renderer (AdgArrowStyle
*arrow_style
,
323 tick_renderer (AdgArrowStyle
*arrow_style
,
331 draw_triangle (cairo_t
*cr
,
332 AdgArrowStyle
*arrow_style
,
335 double length
, height_2
;
337 CpmlPair tail
, tail1
, tail2
;
340 length
= arrow_style
->priv
->size
;
341 height_2
= tan (arrow_style
->priv
->angle
/ 2.0) * length
;
342 cairo_device_to_user_distance (cr
, &length
, &height_2
);
344 switch (segment
->cairo_path
.data
[0].header
.type
)
346 case CAIRO_PATH_LINE_TO
:
347 cpml_primitive_get_pair (segment
, &vector
, CPML_FIRST
);
348 vector
.x
-= segment
->org
.x
;
349 vector
.y
-= segment
->org
.y
;
350 cpml_vector_from_pair (&vector
, &vector
);
352 tail
.x
= vector
.x
*length
+ segment
->org
.x
;
353 tail
.y
= vector
.y
*length
+ segment
->org
.y
;
356 vector
.x
= -vector
.y
*height_2
;
357 vector
.y
= tmp
*height_2
;
359 tail1
.x
= tail
.x
+vector
.x
;
360 tail1
.y
= tail
.y
+vector
.y
;
362 tail2
.x
= tail
.x
-vector
.x
;
363 tail2
.y
= tail
.y
-vector
.y
;
365 cairo_move_to (cr
, segment
->org
.x
, segment
->org
.y
);
366 cairo_line_to (cr
, tail1
.x
, tail1
.y
);
367 cairo_line_to (cr
, tail2
.x
, tail2
.y
);
368 cairo_close_path (cr
);
371 case CAIRO_PATH_CURVE_TO
:
375 g_assert_not_reached ();
380 draw_circle (cairo_t
*cr
,
381 AdgArrowStyle
*arrow_style
,
384 double radius
= arrow_style
->priv
->size
/ 2.;
387 cairo_device_to_user_distance (cr
, &radius
, &dummy
);
389 cairo_arc (cr
, segment
->org
.x
, segment
->org
.y
, radius
, 0., M_PI
);