adg: use G_PRIVATE_ADD and friends
[adg.git] / src / adg / adg-logo.c
bloba75fdd5c059a36db25de366935e12b7253cdffca
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2019 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_WITH_PRIVATE(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 gobject_class->get_property = _adg_get_property;
87 gobject_class->set_property = _adg_set_property;
89 entity_class->arrange = _adg_arrange;
90 entity_class->render = _adg_render;
92 param = adg_param_spec_dress("symbol-dress",
93 P_("Symbol Dress"),
94 P_("The line dress to use for rendering the symbol of the logo"),
95 ADG_DRESS_LINE,
96 G_PARAM_READWRITE);
97 g_object_class_install_property(gobject_class, PROP_SYMBOL_DRESS, param);
99 param = adg_param_spec_dress("screen-dress",
100 P_("Screen Dress"),
101 P_("The line dress to use for rendering the screen shape around the logo"),
102 ADG_DRESS_LINE,
103 G_PARAM_READWRITE);
104 g_object_class_install_property(gobject_class, PROP_SCREEN_DRESS, param);
106 param = adg_param_spec_dress("frame-dress",
107 P_("Frame Dress"),
108 P_("The line dress to use for rendering the frame"),
109 ADG_DRESS_LINE,
110 G_PARAM_READWRITE);
111 g_object_class_install_property(gobject_class, PROP_FRAME_DRESS, param);
113 /* Initialize the private class data: the allocated struct is
114 * never freed as this type is registered statically, hence
115 * never destroyed. A better approach would be to use the old
116 * type initialization (no G_TYPE_DEFINE and friends) that
117 * allows to specify a custom class finalization method */
118 data_class = g_new(AdgLogoClassPrivate, 1);
120 data_class->symbol = NULL;
121 data_class->screen = NULL;
122 data_class->frame = NULL;
123 data_class->extents.is_defined = FALSE;
125 klass->data_class = data_class;
128 static void
129 adg_logo_init(AdgLogo *logo)
131 AdgLogoPrivate *data = adg_logo_get_instance_private(logo);
132 data->symbol_dress = ADG_DRESS_LINE;
133 data->screen_dress = ADG_DRESS_LINE;
134 data->frame_dress = ADG_DRESS_LINE;
137 static void
138 _adg_get_property(GObject *object, guint prop_id,
139 GValue *value, GParamSpec *pspec)
141 AdgLogoPrivate *data = adg_logo_get_instance_private((AdgLogo *) object);
143 switch (prop_id) {
144 case PROP_SYMBOL_DRESS:
145 g_value_set_enum(value, data->symbol_dress);
146 break;
147 case PROP_SCREEN_DRESS:
148 g_value_set_enum(value, data->screen_dress);
149 break;
150 case PROP_FRAME_DRESS:
151 g_value_set_enum(value, data->frame_dress);
152 break;
153 default:
154 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
155 break;
159 static void
160 _adg_set_property(GObject *object, guint prop_id,
161 const GValue *value, GParamSpec *pspec)
163 AdgLogoPrivate *data = adg_logo_get_instance_private((AdgLogo *) object);
165 switch (prop_id) {
166 case PROP_SYMBOL_DRESS:
167 data->symbol_dress = g_value_get_enum(value);
168 break;
169 case PROP_SCREEN_DRESS:
170 data->screen_dress = g_value_get_enum(value);
171 break;
172 case PROP_FRAME_DRESS:
173 data->frame_dress = g_value_get_enum(value);
174 break;
175 default:
176 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
177 break;
183 * adg_logo_new:
185 * Creates a new logo entity.
187 * Returns: (transfer full): the newly created logo entity.
189 * Since: 1.0
191 AdgLogo *
192 adg_logo_new(void)
194 return g_object_new(ADG_TYPE_LOGO, NULL);
198 * adg_logo_set_symbol_dress:
199 * @logo: an #AdgLogo
200 * @dress: the new #AdgDress to use
202 * Sets a new line dress for rendering the symbol of @logo. The
203 * new dress must be a line dress: the check is done by calling
204 * adg_dress_are_related() with @dress and the old dress as
205 * arguments. Check out its documentation for further details.
207 * The default dress is a transparent line dress: the rendering
208 * callback will stroke the symbol using the default color with
209 * a predefined thickness.
211 * Since: 1.0
213 void
214 adg_logo_set_symbol_dress(AdgLogo *logo, AdgDress dress)
216 g_return_if_fail(ADG_IS_LOGO(logo));
217 g_object_set(logo, "symbol-dress", dress, NULL);
221 * adg_logo_get_symbol_dress:
222 * @logo: an #AdgLogo
224 * Gets the line dress to be used in stroking the symbol of @logo.
226 * Returns: (transfer none): the requested line dress.
228 * Since: 1.0
230 AdgDress
231 adg_logo_get_symbol_dress(AdgLogo *logo)
233 AdgLogoPrivate *data;
235 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
237 data = adg_logo_get_instance_private(logo);
238 return data->symbol_dress;
242 * adg_logo_set_screen_dress:
243 * @logo: an #AdgLogo
244 * @dress: the new #AdgDress to use
246 * Sets a new line dress for rendering the screen of @logo.
247 * The new dress must be a line dress: the check is done by
248 * calling adg_dress_are_related() with @dress and the old
249 * dress as arguments. Check out its documentation for
250 * further details.
252 * The default dress is a transparent line dress: the rendering
253 * callback will stroke the screen using the default color with
254 * a predefined thickness.
256 * Since: 1.0
258 void
259 adg_logo_set_screen_dress(AdgLogo *logo, AdgDress dress)
261 g_return_if_fail(ADG_IS_LOGO(logo));
262 g_object_set(logo, "screen-dress", dress, NULL);
266 * adg_logo_get_screen_dress:
267 * @logo: an #AdgLogo
269 * Gets the line dress to be used in stroking the screen shape of @logo.
271 * Returns: (transfer none): the requested line dress.
273 * Since: 1.0
275 AdgDress
276 adg_logo_get_screen_dress(AdgLogo *logo)
278 AdgLogoPrivate *data;
280 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
282 data = adg_logo_get_instance_private(logo);
283 return data->screen_dress;
287 * adg_logo_set_frame_dress:
288 * @logo: an #AdgLogo
289 * @dress: the new #AdgDress to use
291 * Sets a new line dress for rendering the frame of @logo.
292 * The new dress must be a line dress: the check is done by
293 * calling adg_dress_are_related() with @dress and the old
294 * dress as arguments. Check out its documentation for
295 * further details.
297 * The default dress is a transparent line dress: the rendering
298 * callback will stroke the frame using the default color with
299 * a predefined thickness.
301 * Since: 1.0
303 void
304 adg_logo_set_frame_dress(AdgLogo *logo, AdgDress dress)
306 g_return_if_fail(ADG_IS_LOGO(logo));
307 g_object_set(logo, "frame-dress", dress, NULL);
311 * adg_logo_get_frame_dress:
312 * @logo: an #AdgLogo
314 * Gets the line dress to be used in stroking the frame of @logo.
316 * Returns: (transfer none): the requested line dress.
318 * Since: 1.0
320 AdgDress
321 adg_logo_get_frame_dress(AdgLogo *logo)
323 AdgLogoPrivate *data;
325 g_return_val_if_fail(ADG_IS_LOGO(logo), ADG_DRESS_UNDEFINED);
327 data = adg_logo_get_instance_private(logo);
328 return data->frame_dress;
332 static void
333 _adg_arrange(AdgEntity *entity)
335 AdgLogoClass *logo_class;
336 AdgLogoClassPrivate *data_class;
337 CpmlExtents extents;
339 logo_class = ADG_LOGO_GET_CLASS(entity);
340 data_class = logo_class->data_class;
342 _adg_arrange_class(logo_class);
343 cpml_extents_copy(&extents, &data_class->extents);
345 cpml_extents_transform(&extents, adg_entity_get_local_matrix(entity));
346 cpml_extents_transform(&extents, adg_entity_get_global_matrix(entity));
347 adg_entity_set_extents(entity, &extents);
350 static void
351 _adg_arrange_class(AdgLogoClass *logo_class)
353 AdgLogoClassPrivate *data_class;
354 CpmlExtents *extents;
356 data_class = logo_class->data_class;
357 extents = &data_class->extents;
359 if (data_class->symbol == NULL) {
360 AdgPath *path = adg_path_new();
362 adg_path_move_to_explicit(path, 8, 26);
363 adg_path_line_to_explicit(path, 24, 10);
364 adg_path_arc_to_explicit(path, 32, 18, 24, 26);
365 adg_path_line_to_explicit(path, 24, 11);
367 adg_path_move_to_explicit(path, 40, 10);
368 adg_path_arc_to_explicit(path, 32, 18, 40, 26);
369 adg_path_line_to_explicit(path, 40, 22);
370 adg_path_line_to_explicit(path, 38, 22);
372 adg_path_move_to_explicit(path, 23, 22);
373 adg_path_line_to_explicit(path, 16, 22);
375 data_class->symbol = path;
376 extents->is_defined = FALSE;
379 if (data_class->screen == NULL) {
380 AdgPath *path = adg_path_new();
382 adg_path_move_to_explicit(path, 3, 3);
383 adg_path_line_to_explicit(path, 47, 3);
384 adg_path_fillet(path, 10);
385 adg_path_line_to_explicit(path, 47, 33);
386 adg_path_fillet(path, 10);
387 adg_path_line_to_explicit(path, 3, 33);
388 adg_path_fillet(path, 10);
389 adg_path_close(path);
390 adg_path_fillet(path, 10);
392 data_class->screen = path;
393 extents->is_defined = FALSE;
396 if (data_class->frame == NULL) {
397 AdgPath *path = adg_path_new();
399 adg_path_move_to_explicit(path, 0, 0);
400 adg_path_line_to_explicit(path, 50, 0);
401 adg_path_line_to_explicit(path, 50, 36);
402 adg_path_line_to_explicit(path, 0, 36);
403 adg_path_close(path);
405 data_class->frame = path;
406 extents->is_defined = FALSE;
409 if (!data_class->extents.is_defined) {
410 cpml_extents_add(extents,
411 adg_trail_get_extents((AdgTrail *) data_class->symbol));
412 cpml_extents_add(extents,
413 adg_trail_get_extents((AdgTrail *) data_class->screen));
414 cpml_extents_add(extents,
415 adg_trail_get_extents((AdgTrail *) data_class->frame));
419 static void
420 _adg_render(AdgEntity *entity, cairo_t *cr)
422 AdgLogoClassPrivate *data_class = ADG_LOGO_GET_CLASS(entity)->data_class;
423 AdgLogoPrivate *data = adg_logo_get_instance_private((AdgLogo *) entity);
424 const cairo_path_t *cairo_path;
426 cairo_transform(cr, adg_entity_get_global_matrix(entity));
427 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
429 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->symbol);
430 if (cairo_path != NULL) {
431 cairo_save(cr);
432 cairo_transform(cr, adg_entity_get_local_matrix(entity));
433 cairo_append_path(cr, cairo_path);
434 cairo_restore(cr);
436 cairo_set_line_width(cr, 3);
437 adg_entity_apply_dress(entity, data->symbol_dress, cr);
439 cairo_stroke(cr);
442 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->screen);
443 if (cairo_path != NULL) {
444 cairo_save(cr);
445 cairo_transform(cr, adg_entity_get_local_matrix(entity));
446 cairo_append_path(cr, cairo_path);
447 cairo_restore(cr);
449 cairo_set_line_width(cr, 2);
450 adg_entity_apply_dress(entity, data->screen_dress, cr);
452 cairo_stroke(cr);
455 cairo_path = adg_trail_get_cairo_path((AdgTrail *) data_class->frame);
456 if (cairo_path != NULL) {
457 cairo_save(cr);
458 cairo_transform(cr, adg_entity_get_local_matrix(entity));
459 cairo_append_path(cr, cairo_path);
460 cairo_restore(cr);
462 cairo_set_line_width(cr, 2);
463 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
464 adg_entity_apply_dress(entity, data->frame_dress, cr);
466 cairo_stroke(cr);