adg: provide example on how to customize a style
[adg.git] / src / adg / adg-logo.c
blob897ae7f1f147e60e5da4f6aab03785fee6f0b5f9
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2017 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-logo
23 * @short_description: The ADG default logo
25 * The #AdgLogo is an entity representing the default ADG logo.
27 * Since: 1.0
28 **/
30 /**
31 * AdgLogo:
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
36 * Since: 1.0
37 **/
40 #include "adg-internal.h"
41 #include "adg-model.h"
42 #include "adg-trail.h"
43 #include "adg-path.h"
44 #include "adg-dress.h"
45 #include "adg-param-dress.h"
47 #include "adg-logo.h"
48 #include "adg-logo-private.h"
51 G_DEFINE_TYPE(AdgLogo, adg_logo, ADG_TYPE_ENTITY)
53 enum {
54 PROP_0,
55 PROP_SYMBOL_DRESS,
56 PROP_SCREEN_DRESS,
57 PROP_FRAME_DRESS
61 static void _adg_get_property (GObject *object,
62 guint param_id,
63 GValue *value,
64 GParamSpec *pspec);
65 static void _adg_set_property (GObject *object,
66 guint param_id,
67 const GValue *value,
68 GParamSpec *pspec);
69 static void _adg_arrange (AdgEntity *entity);
70 static void _adg_render (AdgEntity *entity,
71 cairo_t *cr);
72 static void _adg_arrange_class (AdgLogoClass *logo_class);
75 static void
76 adg_logo_class_init(AdgLogoClass *klass)
78 GObjectClass *gobject_class;
79 AdgEntityClass *entity_class;
80 GParamSpec *param;
81 AdgLogoClassPrivate *data_class;
83 gobject_class = (GObjectClass *) klass;
84 entity_class = (AdgEntityClass *) klass;
86 g_type_class_add_private(klass, sizeof(AdgLogoPrivate));
88 gobject_class->get_property = _adg_get_property;
89 gobject_class->set_property = _adg_set_property;
91 entity_class->arrange = _adg_arrange;
92 entity_class->render = _adg_render;
94 param = adg_param_spec_dress("symbol-dress",
95 P_("Symbol Dress"),
96 P_("The line dress to use for rendering the symbol of the logo"),
97 ADG_DRESS_LINE,
98 G_PARAM_READWRITE);
99 g_object_class_install_property(gobject_class, PROP_SYMBOL_DRESS, param);
101 param = adg_param_spec_dress("screen-dress",
102 P_("Screen Dress"),
103 P_("The line dress to use for rendering the screen shape around the logo"),
104 ADG_DRESS_LINE,
105 G_PARAM_READWRITE);
106 g_object_class_install_property(gobject_class, PROP_SCREEN_DRESS, param);
108 param = adg_param_spec_dress("frame-dress",
109 P_("Frame Dress"),
110 P_("The line dress to use for rendering the frame"),
111 ADG_DRESS_LINE,
112 G_PARAM_READWRITE);
113 g_object_class_install_property(gobject_class, PROP_FRAME_DRESS, param);
115 /* Initialize the private class data: the allocated struct is
116 * never freed as this type is registered statically, hence
117 * never destroyed. A better approach would be to use the old
118 * type initialization (no G_TYPE_DEFINE and friends) that
119 * allows to specify a custom class finalization method */
120 data_class = g_new(AdgLogoClassPrivate, 1);
122 data_class->symbol = NULL;
123 data_class->screen = NULL;
124 data_class->frame = NULL;
125 data_class->extents.is_defined = FALSE;
127 klass->data_class = data_class;
130 static void
131 adg_logo_init(AdgLogo *logo)
133 AdgLogoPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(logo, ADG_TYPE_LOGO,
134 AdgLogoPrivate);
136 data->symbol_dress = ADG_DRESS_LINE;
137 data->screen_dress = ADG_DRESS_LINE;
138 data->frame_dress = ADG_DRESS_LINE;
140 logo->data = data;
143 static void
144 _adg_get_property(GObject *object, guint prop_id,
145 GValue *value, GParamSpec *pspec)
147 AdgLogoPrivate *data = ((AdgLogo *) object)->data;
149 switch (prop_id) {
150 case PROP_SYMBOL_DRESS:
151 g_value_set_enum(value, data->symbol_dress);
152 break;
153 case PROP_SCREEN_DRESS:
154 g_value_set_enum(value, data->screen_dress);
155 break;
156 case PROP_FRAME_DRESS:
157 g_value_set_enum(value, data->frame_dress);
158 break;
159 default:
160 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
161 break;
165 static void
166 _adg_set_property(GObject *object, guint prop_id,
167 const GValue *value, GParamSpec *pspec)
169 AdgLogo *logo;
170 AdgLogoPrivate *data;
172 logo = (AdgLogo *) object;
173 data = logo->data;
175 switch (prop_id) {
176 case PROP_SYMBOL_DRESS:
177 data->symbol_dress = g_value_get_enum(value);
178 break;
179 case PROP_SCREEN_DRESS:
180 data->screen_dress = g_value_get_enum(value);
181 break;
182 case PROP_FRAME_DRESS:
183 data->frame_dress = g_value_get_enum(value);
184 break;
185 default:
186 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
187 break;
193 * adg_logo_new:
195 * Creates a new logo entity.
197 * Returns: (transfer full): the newly created logo entity.
199 * Since: 1.0
201 AdgLogo *
202 adg_logo_new(void)
204 return g_object_new(ADG_TYPE_LOGO, NULL);
208 * adg_logo_set_symbol_dress:
209 * @logo: an #AdgLogo
210 * @dress: the new #AdgDress to use
212 * Sets a new line dress for rendering the symbol of @logo. The
213 * new dress must be a line dress: the check is done by calling
214 * adg_dress_are_related() with @dress and the old dress as
215 * arguments. Check out its documentation for further details.
217 * The default dress is a transparent line dress: the rendering
218 * callback will stroke the symbol using the default color with
219 * a predefined thickness.
221 * Since: 1.0
223 void
224 adg_logo_set_symbol_dress(AdgLogo *logo, AdgDress dress)
226 g_return_if_fail(ADG_IS_LOGO(logo));
227 g_object_set(logo, "symbol-dress", dress, NULL);
231 * adg_logo_get_symbol_dress:
232 * @logo: an #AdgLogo
234 * Gets the line dress to be used in stroking the symbol of @logo.
236 * Returns: (transfer none): the requested line dress.
238 * Since: 1.0
240 AdgDress
241 adg_logo_get_symbol_dress(AdgLogo *logo)
243 AdgLogoPrivate *data;
245 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
247 data = logo->data;
249 return data->symbol_dress;
253 * adg_logo_set_screen_dress:
254 * @logo: an #AdgLogo
255 * @dress: the new #AdgDress to use
257 * Sets a new line dress for rendering the screen of @logo.
258 * The new dress must be a line dress: the check is done by
259 * calling adg_dress_are_related() with @dress and the old
260 * dress as arguments. Check out its documentation for
261 * further details.
263 * The default dress is a transparent line dress: the rendering
264 * callback will stroke the screen using the default color with
265 * a predefined thickness.
267 * Since: 1.0
269 void
270 adg_logo_set_screen_dress(AdgLogo *logo, AdgDress dress)
272 g_return_if_fail(ADG_IS_LOGO(logo));
273 g_object_set(logo, "screen-dress", dress, NULL);
277 * adg_logo_get_screen_dress:
278 * @logo: an #AdgLogo
280 * Gets the line dress to be used in stroking the screen shape of @logo.
282 * Returns: (transfer none): the requested line dress.
284 * Since: 1.0
286 AdgDress
287 adg_logo_get_screen_dress(AdgLogo *logo)
289 AdgLogoPrivate *data;
291 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
293 data = logo->data;
295 return data->screen_dress;
299 * adg_logo_set_frame_dress:
300 * @logo: an #AdgLogo
301 * @dress: the new #AdgDress to use
303 * Sets a new line dress for rendering the frame of @logo.
304 * The new dress must be a line dress: the check is done by
305 * calling adg_dress_are_related() with @dress and the old
306 * dress as arguments. Check out its documentation for
307 * further details.
309 * The default dress is a transparent line dress: the rendering
310 * callback will stroke the frame using the default color with
311 * a predefined thickness.
313 * Since: 1.0
315 void
316 adg_logo_set_frame_dress(AdgLogo *logo, AdgDress dress)
318 g_return_if_fail(ADG_IS_LOGO(logo));
319 g_object_set(logo, "frame-dress", dress, NULL);
323 * adg_logo_get_frame_dress:
324 * @logo: an #AdgLogo
326 * Gets the line dress to be used in stroking the frame of @logo.
328 * Returns: (transfer none): the requested line dress.
330 * Since: 1.0
332 AdgDress
333 adg_logo_get_frame_dress(AdgLogo *logo)
335 AdgLogoPrivate *data;
337 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
339 data = logo->data;
341 return data->frame_dress;
345 static void
346 _adg_arrange(AdgEntity *entity)
348 AdgLogoClass *logo_class;
349 AdgLogoClassPrivate *data_class;
350 CpmlExtents extents;
352 logo_class = ADG_LOGO_GET_CLASS(entity);
353 data_class = logo_class->data_class;
355 _adg_arrange_class(logo_class);
356 cpml_extents_copy(&extents, &data_class->extents);
358 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
359 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
360 adg_entity_set_extents(entity, &extents);
363 static void
364 _adg_arrange_class(AdgLogoClass *logo_class)
366 AdgLogoClassPrivate *data_class;
367 CpmlExtents *extents;
369 data_class = logo_class->data_class;
370 extents = &data_class->extents;
372 if (data_class->symbol == NULL) {
373 AdgPath *path = adg_path_new();
375 adg_path_move_to_explicit(path, 8, 26);
376 adg_path_line_to_explicit(path, 24, 10);
377 adg_path_arc_to_explicit(path, 32, 18, 24, 26);
378 adg_path_line_to_explicit(path, 24, 11);
380 adg_path_move_to_explicit(path, 40, 10);
381 adg_path_arc_to_explicit(path, 32, 18, 40, 26);
382 adg_path_line_to_explicit(path, 40, 22);
383 adg_path_line_to_explicit(path, 38, 22);
385 adg_path_move_to_explicit(path, 23, 22);
386 adg_path_line_to_explicit(path, 16, 22);
388 data_class->symbol = path;
389 extents->is_defined = FALSE;
392 if (data_class->screen == NULL) {
393 AdgPath *path = adg_path_new();
395 adg_path_move_to_explicit(path, 3, 3);
396 adg_path_line_to_explicit(path, 47, 3);
397 adg_path_fillet(path, 10);
398 adg_path_line_to_explicit(path, 47, 33);
399 adg_path_fillet(path, 10);
400 adg_path_line_to_explicit(path, 3, 33);
401 adg_path_fillet(path, 10);
402 adg_path_close(path);
403 adg_path_fillet(path, 10);
405 data_class->screen = path;
406 extents->is_defined = FALSE;
409 if (data_class->frame == NULL) {
410 AdgPath *path = adg_path_new();
412 adg_path_move_to_explicit(path, 0, 0);
413 adg_path_line_to_explicit(path, 50, 0);
414 adg_path_line_to_explicit(path, 50, 36);
415 adg_path_line_to_explicit(path, 0, 36);
416 adg_path_close(path);
418 data_class->frame = path;
419 extents->is_defined = FALSE;
422 if (!data_class->extents.is_defined) {
423 cpml_extents_add(extents,
424 adg_trail_get_extents((AdgTrail *) data_class->symbol));
425 cpml_extents_add(extents,
426 adg_trail_get_extents((AdgTrail *) data_class->screen));
427 cpml_extents_add(extents,
428 adg_trail_get_extents((AdgTrail *) data_class->frame));
432 static void
433 _adg_render(AdgEntity *entity, cairo_t *cr)
435 AdgLogoClassPrivate *data_class;
436 AdgLogoPrivate *data;
437 const cairo_path_t *cairo_path;
439 data_class = ADG_LOGO_GET_CLASS(entity)->data_class;
440 data = ((AdgLogo *) entity)->data;
442 cairo_transform(cr, adg_entity_get_global_matrix(entity));
443 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
445 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->symbol);
446 if (cairo_path != NULL) {
447 cairo_save(cr);
448 cairo_transform(cr, adg_entity_get_local_matrix(entity));
449 cairo_append_path(cr, cairo_path);
450 cairo_restore(cr);
452 cairo_set_line_width(cr, 3);
453 adg_entity_apply_dress(entity, data->symbol_dress, cr);
455 cairo_stroke(cr);
458 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->screen);
459 if (cairo_path != NULL) {
460 cairo_save(cr);
461 cairo_transform(cr, adg_entity_get_local_matrix(entity));
462 cairo_append_path(cr, cairo_path);
463 cairo_restore(cr);
465 cairo_set_line_width(cr, 2);
466 adg_entity_apply_dress(entity, data->screen_dress, cr);
468 cairo_stroke(cr);
471 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->frame);
472 if (cairo_path != NULL) {
473 cairo_save(cr);
474 cairo_transform(cr, adg_entity_get_local_matrix(entity));
475 cairo_append_path(cr, cairo_path);
476 cairo_restore(cr);
478 cairo_set_line_width(cr, 2);
479 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
480 adg_entity_apply_dress(entity, data->frame_dress, cr);
482 cairo_stroke(cr);