[AdgProjection] Prefixed internal symbols
[adg.git] / src / adg / adg-projection.c
blobc0fc086893e12391041680882ac2e8f49da9af97
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010 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 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.
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.
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., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:adg-projection
23 * @short_description: The standard symbol for specifying the projection scheme
25 * The #AdgProjection is an entity representing the standard symbol
26 * of the projection scheme.
27 **/
29 /**
30 * AdgProjection:
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
34 **/
37 #include "adg-internal.h"
38 #include "adg-projection.h"
39 #include "adg-projection-private.h"
40 #include "adg-line-style.h"
41 #include "adg-dress-builtins.h"
44 G_DEFINE_TYPE(AdgProjection, adg_projection, ADG_TYPE_ENTITY);
46 enum {
47 PROP_0,
48 PROP_SYMBOL_DRESS,
49 PROP_AXIS_DRESS,
50 PROP_SCHEME
54 static void _adg_get_property (GObject *object,
55 guint param_id,
56 GValue *value,
57 GParamSpec *pspec);
58 static void _adg_set_property (GObject *object,
59 guint param_id,
60 const GValue *value,
61 GParamSpec *pspec);
62 static void _adg_arrange (AdgEntity *entity);
63 static void _adg_render (AdgEntity *entity,
64 cairo_t *cr);
65 static void _adg_arrange_class (AdgProjectionClass *projection_class,
66 AdgProjectionScheme scheme);
69 static void
70 adg_projection_class_init(AdgProjectionClass *klass)
72 GObjectClass *gobject_class;
73 AdgEntityClass *entity_class;
74 GParamSpec *param;
75 AdgProjectionClassPrivate *data_class;
77 gobject_class = (GObjectClass *) klass;
78 entity_class = (AdgEntityClass *) klass;
80 g_type_class_add_private(klass, sizeof(AdgProjectionPrivate));
82 gobject_class->get_property = _adg_get_property;
83 gobject_class->set_property = _adg_set_property;
85 entity_class->arrange = _adg_arrange;
86 entity_class->render = _adg_render;
88 param = adg_param_spec_dress("symbol-dress",
89 P_("Symbol Dress"),
90 P_("The line dress to use for rendering the views of the projection"),
91 ADG_DRESS_LINE,
92 G_PARAM_READWRITE);
93 g_object_class_install_property(gobject_class, PROP_SYMBOL_DRESS, param);
95 param = adg_param_spec_dress("axis-dress",
96 P_("Axis Dress"),
97 P_("The line dress to use for rendering the axis of the projection scheme"),
98 ADG_DRESS_LINE,
99 G_PARAM_READWRITE);
100 g_object_class_install_property(gobject_class, PROP_AXIS_DRESS, param);
102 param = g_param_spec_enum("scheme",
103 P_("Projection Scheme"),
104 P_("The projection scheme to be represented"),
105 ADG_TYPE_PROJECTION_SCHEME,
106 ADG_PROJECTION_UNDEFINED,
107 G_PARAM_READWRITE);
108 g_object_class_install_property(gobject_class, PROP_SCHEME, param);
110 /* Initialize the private class data: the allocated struct is
111 * never freed as this type is registered statically, hence
112 * never destroyed. A better approach would be to use the old
113 * type initialization (no G_TYPE_DEFINE and friends) that
114 * allows to specify a custom class finalization method */
115 data_class = g_new(AdgProjectionClassPrivate, 1);
117 data_class->scheme = ADG_PROJECTION_UNDEFINED;
118 data_class->symbol = NULL;
119 data_class->axis = NULL;
120 data_class->extents.is_defined = FALSE;
122 klass->data_class = data_class;
125 static void
126 adg_projection_init(AdgProjection *projection)
128 AdgProjectionPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(projection, ADG_TYPE_PROJECTION,
129 AdgProjectionPrivate);
131 data->symbol_dress = ADG_DRESS_LINE;
132 data->axis_dress = ADG_DRESS_LINE;
133 data->scheme = ADG_PROJECTION_UNDEFINED;
135 projection->data = data;
138 static void
139 _adg_get_property(GObject *object, guint prop_id,
140 GValue *value, GParamSpec *pspec)
142 AdgProjectionPrivate *data = ((AdgProjection *) object)->data;
144 switch (prop_id) {
145 case PROP_SYMBOL_DRESS:
146 g_value_set_int(value, data->symbol_dress);
147 break;
148 case PROP_AXIS_DRESS:
149 g_value_set_int(value, data->axis_dress);
150 break;
151 case PROP_SCHEME:
152 g_value_set_enum(value, data->scheme);
153 break;
154 default:
155 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
156 break;
160 static void
161 _adg_set_property(GObject *object, guint prop_id,
162 const GValue *value, GParamSpec *pspec)
164 AdgProjection *projection;
165 AdgProjectionPrivate *data;
167 projection = (AdgProjection *) object;
168 data = projection->data;
170 switch (prop_id) {
171 case PROP_SYMBOL_DRESS:
172 data->symbol_dress = g_value_get_int(value);
173 break;
174 case PROP_AXIS_DRESS:
175 data->axis_dress = g_value_get_int(value);
176 break;
177 case PROP_SCHEME:
178 data->scheme = g_value_get_enum(value);
179 adg_entity_invalidate((AdgEntity *) object);
180 break;
181 default:
182 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
183 break;
189 * adg_projection_new:
190 * @scheme: the scheme represented by this projection
192 * Creates a new projection entity representing the selected @scheme.
193 * If @scheme is invalid, a projection symbol without a scheme is
194 * returned, that is #AdgProjection:scheme is set to
195 * #ADG_PROJECTION_UNDEFINED, and a warning is raised.
197 * Returns: the newly created projection entity
199 AdgProjection *
200 adg_projection_new(AdgProjectionScheme scheme)
202 return g_object_new(ADG_TYPE_PROJECTION, "scheme", scheme, NULL);
206 * adg_projection_set_symbol_dress:
207 * @projection: an #AdgProjection
208 * @dress: the new #AdgDress to use
210 * Sets a new line dress for rendering the symbol of @projection. The
211 * new dress must be a line dress: the check is done by calling
212 * adg_dress_are_related() with @dress and the old dress as
213 * arguments. Check out its documentation for further details.
215 * The default dress is a transparent line dress: the rendering
216 * callback will stroke the symbol using the default color with
217 * a predefined thickness.
219 void
220 adg_projection_set_symbol_dress(AdgProjection *projection, AdgDress dress)
222 g_return_if_fail(ADG_IS_PROJECTION(projection));
223 g_object_set((GObject *) projection, "symbol-dress", dress, NULL);
227 * adg_projection_get_symbol_dress:
228 * @projection: an #AdgProjection
230 * Gets the line dress to be used in stroking the symbol of @projection.
232 * Returns: the requested line dress
234 AdgDress
235 adg_projection_get_symbol_dress(AdgProjection *projection)
237 AdgProjectionPrivate *data;
239 g_return_val_if_fail(ADG_IS_PROJECTION(projection), ADG_DRESS_UNDEFINED);
241 data = projection->data;
243 return data->symbol_dress;
247 * adg_projection_set_axis_dress:
248 * @projection: an #AdgProjection
249 * @dress: the new #AdgDress to use
251 * Sets a new line dress for rendering the axis of @projection.
252 * The new dress must be a line dress: the check is done by
253 * calling adg_dress_are_related() with @dress and the old
254 * dress as arguments. Check out its documentation for
255 * further details.
257 * The default dress is a transparent line dress: the rendering
258 * callback will stroke the axis using the default line style.
260 void
261 adg_projection_set_axis_dress(AdgProjection *projection, AdgDress dress)
263 g_return_if_fail(ADG_IS_PROJECTION(projection));
264 g_object_set((GObject *) projection, "axis-dress", dress, NULL);
268 * adg_projection_get_axis_dress:
269 * @projection: an #AdgProjection
271 * Gets the line dress to be used in stroking the axis of @projection.
273 * Returns: the requested line dress
275 AdgDress
276 adg_projection_get_axis_dress(AdgProjection *projection)
278 AdgProjectionPrivate *data;
280 g_return_val_if_fail(ADG_IS_PROJECTION(projection), ADG_DRESS_UNDEFINED);
282 data = projection->data;
284 return data->axis_dress;
288 * adg_projection_set_scheme:
289 * @projection: an #AdgProjection
290 * @scheme: the new projection scheme
292 * Sets a new scheme on @projection. If @scheme is different
293 * from the old one, @projection is invalidated.
295 void
296 adg_projection_set_scheme(AdgProjection *projection,
297 AdgProjectionScheme scheme)
299 g_return_if_fail(ADG_IS_PROJECTION(projection));
300 g_object_set(projection, "scheme", scheme, NULL);
304 * adg_projection_get_scheme:
305 * @projection: an #AdgProjection
307 * Gets the scheme represented by @projection.
309 * Returns: the scheme of @projection
311 AdgProjectionScheme
312 adg_projection_get_scheme(AdgProjection *projection)
314 AdgProjectionPrivate *data;
316 g_return_val_if_fail(ADG_IS_PROJECTION(projection),
317 ADG_PROJECTION_UNDEFINED);
319 data = projection->data;
321 return data->scheme;
325 static void
326 _adg_arrange(AdgEntity *entity)
328 AdgProjectionPrivate *data;
329 AdgProjectionClass *projection_class;
330 AdgProjectionClassPrivate *data_class;
331 CpmlExtents extents;
333 data = ((AdgProjection *) entity)->data;
334 projection_class = ADG_PROJECTION_GET_CLASS(entity);
335 data_class = projection_class->data_class;
337 _adg_arrange_class(projection_class, data->scheme);
338 cpml_extents_copy(&extents, &data_class->extents);
340 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
341 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
342 adg_entity_set_extents(entity, &extents);
345 static void
346 _adg_arrange_class(AdgProjectionClass *projection_class,
347 AdgProjectionScheme scheme)
349 AdgProjectionClassPrivate *data_class;
350 AdgPath *symbol, *axis;
352 data_class = projection_class->data_class;
354 if (data_class->scheme == scheme)
355 return;
357 if (data_class->symbol != NULL)
358 g_object_unref(data_class->symbol);
360 if (data_class->axis != NULL)
361 g_object_unref(data_class->axis);
363 data_class->scheme = scheme;
365 switch(scheme) {
366 case ADG_PROJECTION_UNDEFINED:
367 symbol = NULL;
368 axis = NULL;
369 break;
370 case ADG_PROJECTION_FIRST_ANGLE:
371 symbol = adg_path_new();
372 adg_path_move_to_explicit(symbol, 4, 19);
373 adg_path_line_to_explicit(symbol, 24, 24);
374 adg_path_line_to_explicit(symbol, 24, 4);
375 adg_path_line_to_explicit(symbol, 4, 9);
376 adg_path_close(symbol);
377 adg_path_move_to_explicit(symbol, 49, 14);
378 adg_path_arc_to_explicit(symbol, 29, 14, 49, 14);
379 adg_path_move_to_explicit(symbol, 44, 14);
380 adg_path_arc_to_explicit(symbol, 34, 14, 44, 14);
382 axis = adg_path_new();
383 adg_path_move_to_explicit(axis, 0, 14);
384 adg_path_line_to_explicit(axis, 53, 14);
385 adg_path_move_to_explicit(axis, 39, 0);
386 adg_path_line_to_explicit(axis, 39, 28);
387 break;
388 case ADG_PROJECTION_THIRD_ANGLE:
389 symbol = adg_path_new();
390 adg_path_move_to_explicit(symbol, 29, 19);
391 adg_path_line_to_explicit(symbol, 49, 24);
392 adg_path_line_to_explicit(symbol, 49, 4);
393 adg_path_line_to_explicit(symbol, 29, 9);
394 adg_path_close(symbol);
395 adg_path_move_to_explicit(symbol, 24, 14);
396 adg_path_arc_to_explicit(symbol, 4, 14, 24, 14);
397 adg_path_move_to_explicit(symbol, 19, 14);
398 adg_path_arc_to_explicit(symbol, 9, 14, 19, 14);
400 axis = adg_path_new();
401 adg_path_move_to_explicit(axis, 0, 14);
402 adg_path_line_to_explicit(axis, 53, 14);
403 adg_path_move_to_explicit(axis, 14, 0);
404 adg_path_line_to_explicit(axis, 14, 28);
405 break;
406 default:
407 g_return_if_reached();
408 break;
411 data_class->symbol = symbol;
412 data_class->axis = axis;
413 data_class->extents.is_defined = FALSE;
415 if (axis != NULL)
416 cpml_extents_add(&data_class->extents,
417 adg_trail_get_extents((AdgTrail *) axis));
419 if (symbol != NULL)
420 cpml_extents_add(&data_class->extents,
421 adg_trail_get_extents((AdgTrail *) symbol));
424 static void
425 _adg_render(AdgEntity *entity, cairo_t *cr)
427 AdgProjectionClassPrivate *data_class;
428 AdgProjectionPrivate *data;
429 const cairo_path_t *cairo_path;
431 data_class = ADG_PROJECTION_GET_CLASS(entity)->data_class;
432 data = ((AdgProjection *) entity)->data;
434 if (data_class->symbol != NULL) {
435 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->symbol);
437 cairo_save(cr);
438 cairo_transform(cr, adg_entity_get_local_matrix(entity));
439 cairo_append_path(cr, cairo_path);
440 cairo_restore(cr);
442 cairo_set_line_width(cr, 2);
443 adg_entity_apply_dress(entity, data->symbol_dress, cr);
445 cairo_stroke(cr);
448 if (data_class->axis != NULL) {
449 const gdouble dashes[] = { 5, 2, 1, 2 };
451 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->axis);
453 cairo_save(cr);
454 cairo_transform(cr, adg_entity_get_local_matrix(entity));
455 cairo_append_path(cr, cairo_path);
456 cairo_restore(cr);
458 cairo_set_line_width(cr, 1);
459 cairo_set_dash(cr, dashes, G_N_ELEMENTS(dashes), -1.5);
460 adg_entity_apply_dress(entity, data->axis_dress, cr);
462 cairo_stroke(cr);