[CPML] Initial test unit implementation
[adg.git] / demo / adg-demo.c
blob38e705fe623d08f4112dd27d866d1dcc4da672ff
1 /* Needed for localization support */
2 #include <adg/adg-internal.h>
4 /* Force the reinclusion of adg.h */
5 #undef __ADG_H__
7 #include "demo.h"
9 #include <adg-gtk.h>
10 #include <string.h>
11 #include <math.h>
13 #define SQRT3 1.732050808
14 #define CHAMFER 0.3
17 typedef struct _DemoPart DemoPart;
19 struct _DemoPart {
20 /* Dimensions */
21 gdouble A;
22 gdouble B;
23 gdouble C;
24 gdouble DHOLE;
25 gdouble LHOLE;
26 gdouble D1;
27 gdouble D2;
28 gdouble D3;
29 gdouble D4;
30 gdouble D5;
31 gdouble D6;
32 gdouble D7;
33 gdouble RD34;
34 gdouble RD56;
35 gdouble LD2;
36 gdouble LD3;
37 gdouble LD5;
38 gdouble LD6;
39 gdouble LD7;
40 gboolean GROOVE;
41 gdouble ZGROOVE;
42 gdouble DGROOVE;
43 gdouble LGROOVE;
45 /* Metadata */
46 gchar *TITLE;
47 gchar *DRAWING;
48 gchar *AUTHOR;
49 gchar *DATE;
51 /* User interface widgets */
52 AdgGtkArea *area;
53 GHashTable *widgets;
54 GtkButton *apply;
55 GtkButton *reset;
57 /* Data models */
58 AdgPath *shape;
59 AdgPath *hatch;
60 AdgPath *hatch_edge;
62 /* Special entities */
63 AdgTitleBlock *title_block;
64 AdgEdges *edges;
68 static void
69 _adg_version(void)
71 g_print("adg-demo " PACKAGE_VERSION "\n");
72 exit(0);
75 static void
76 _adg_parse_args(gint *p_argc, gchar **p_argv[], gboolean *show_extents)
78 GError *error = NULL;
79 GOptionEntry entries[] = {
80 {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
81 (gpointer) _adg_version, _("Display version information"), NULL},
82 {"show-extents", 'E', 0, G_OPTION_ARG_NONE,
83 NULL, _("Show the boundary boxes of every entity"), NULL},
84 {NULL}
87 entries[1].arg_data = show_extents;
88 *show_extents = FALSE;
89 gtk_init_with_args(p_argc, p_argv, _("- ADG demonstration program"),
90 entries, GETTEXT_PACKAGE, &error);
92 if (error != NULL) {
93 gint error_code = error->code;
95 g_printerr("%s\n", error->message);
97 g_error_free(error);
98 exit(error_code);
104 * _adg_error:
105 * @message: a custom error message
106 * @parent_window: the parent window or %NULL
108 * Convenient function that presents an error dialog and waits the user
109 * to close this modal dialog.
111 void
112 _adg_error(const gchar *message, GtkWindow *parent_window)
114 GtkWidget *dialog = gtk_message_dialog_new(parent_window,
115 GTK_DIALOG_DESTROY_WITH_PARENT,
116 GTK_MESSAGE_ERROR,
117 GTK_BUTTONS_CLOSE,
118 "%s", message);
119 gtk_window_set_title(GTK_WINDOW(dialog), _("Error from adg-demo"));
120 gtk_dialog_run(GTK_DIALOG(dialog));
121 gtk_widget_destroy(dialog);
124 static void
125 _adg_path_add_hole(AdgPath *path, const DemoPart *part)
127 AdgModel *model;
128 AdgPair pair;
130 model = ADG_MODEL(path);
131 pair.x = part->LHOLE;
132 pair.y = 0;
134 adg_path_move_to(path, &pair);
135 adg_model_set_named_pair(model, "LHOLE", &pair);
137 pair.y = part->DHOLE / 2;
138 pair.x -= pair.y / SQRT3;
139 adg_path_line_to(path, &pair);
141 pair.x = 0;
142 adg_path_line_to(path, &pair);
143 adg_model_set_named_pair(model, "DHOLE", &pair);
146 static void
147 _adg_path_add_rail(AdgPath *path, const DemoPart *part, gdouble to_x)
149 AdgModel *model;
150 AdgPair pair;
152 model = ADG_MODEL(path);
153 pair.x = 0;
154 pair.y = part->D1 / 2;
156 adg_path_line_to(path, &pair);
157 adg_model_set_named_pair(model, "D1I", &pair);
159 if (part->GROOVE && to_x > part->ZGROOVE) {
160 pair.x = part->ZGROOVE;
161 adg_path_line_to(path, &pair);
162 adg_model_set_named_pair(model, "DGROOVEI_X", &pair);
164 pair.y = part->D3 / 2;
165 adg_model_set_named_pair(model, "DGROOVEY_POS", &pair);
167 pair.y = part->DGROOVE / 2;
168 adg_path_line_to(path, &pair);
169 adg_model_set_named_pair(model, "DGROOVEI_Y", &pair);
171 pair.x += part->LGROOVE;
172 adg_path_line_to(path, &pair);
174 pair.y = part->D3 / 2;
175 adg_model_set_named_pair(model, "DGROOVEX_POS", &pair);
177 pair.y = part->D1 / 2;
178 adg_path_line_to(path, &pair);
179 adg_model_set_named_pair(model, "DGROOVEF_X", &pair);
182 pair.x = to_x;
183 adg_path_line_to(path, &pair);
184 adg_model_set_named_pair(model, "D1F", &pair);
188 static void
189 _adg_part_define_title_block(DemoPart *part)
191 g_object_set(part->title_block,
192 "title", part->TITLE,
193 "author", part->AUTHOR,
194 "date", part->DATE,
195 "drawing", part->DRAWING,
196 "logo", adg_logo_new(),
197 "projection", adg_projection_new(ADG_PROJECTION_FIRST_ANGLE),
198 "scale", "---",
199 "size", "A4",
200 NULL);
203 static void
204 _adg_part_define_hatch(DemoPart *part)
206 AdgPath *path;
207 AdgPair pair;
209 path = part->hatch;
210 pair.x = 0;
211 pair.y = (part->D1 + part->DHOLE) / 4;
213 _adg_path_add_hole(path, part);
214 adg_path_line_to(path, &pair);
215 adg_path_curve_to_explicit(path,
216 part->LHOLE / 2, part->DHOLE / 2,
217 part->LHOLE + 2, part->D1 / 2,
218 part->LHOLE + 2, 0);
219 adg_path_reflect(path, NULL);
220 adg_path_close(path);
222 path = part->hatch_edge;
223 adg_path_move_to(path, &pair);
224 adg_path_curve_to_explicit(path,
225 part->LHOLE / 2, part->DHOLE / 2,
226 part->LHOLE + 2, part->D1 / 2,
227 part->LHOLE + 2, 0);
228 adg_path_reflect(path, NULL);
231 static void
232 _adg_part_define_shape(DemoPart *part)
234 AdgModel *model;
235 AdgPath *path;
236 AdgPair pair, tmp;
237 const AdgPrimitive *primitive;
239 path = part->shape;
240 model = ADG_MODEL(path);
241 pair.x = part->A - part->B - part->LD2;
242 pair.y = part->D3 / 2;
243 adg_model_set_named_pair(model, "D2_POS", &pair);
245 _adg_path_add_hole(path, part);
246 _adg_path_add_rail(path, part, pair.x);
248 pair.x += (part->D1 - part->D2) / 2;
249 pair.y = part->D2 / 2;
250 adg_path_line_to(path, &pair);
251 adg_model_set_named_pair(model, "D2I", &pair);
253 pair.x = part->A - part->B;
254 adg_path_line_to(path, &pair);
255 adg_path_fillet(path, 0.4);
257 pair.x = part->A - part->B;
258 pair.y = part->D3 / 2;
259 adg_path_line_to(path, &pair);
260 adg_model_set_named_pair(model, "D3I", &pair);
262 pair.x = part->A;
263 adg_model_set_named_pair(model, "East", &pair);
265 pair.x = 0;
266 adg_model_set_named_pair(model, "West", &pair);
268 adg_path_chamfer(path, CHAMFER, CHAMFER);
270 pair.x = part->A - part->B + part->LD3;
271 pair.y = part->D3 / 2;
272 adg_path_line_to(path, &pair);
274 primitive = adg_path_over_primitive(path);
275 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
276 adg_model_set_named_pair(model, "D3I_X", &tmp);
278 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
279 adg_model_set_named_pair(model, "D3I_Y", &tmp);
281 adg_path_chamfer(path, CHAMFER, CHAMFER);
283 pair.y = part->D4 / 2;
284 adg_path_line_to(path, &pair);
286 primitive = adg_path_over_primitive(path);
287 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
288 adg_model_set_named_pair(model, "D3F_Y", &tmp);
289 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
290 adg_model_set_named_pair(model, "D3F_X", &tmp);
292 adg_path_fillet(path, part->RD34);
294 pair.x += part->RD34;
295 adg_model_set_named_pair(model, "D4I", &pair);
297 pair.x = part->A - part->C - part->LD5;
298 adg_path_line_to(path, &pair);
299 adg_model_set_named_pair(model, "D4F", &pair);
301 pair.y = part->D3 / 2;
302 adg_model_set_named_pair(model, "D4_POS", &pair);
304 primitive = adg_path_over_primitive(path);
305 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
306 tmp.x += part->RD34;
307 adg_model_set_named_pair(model, "RD34", &tmp);
309 tmp.x -= cos(G_PI_4) * part->RD34,
310 tmp.y -= sin(G_PI_4) * part->RD34,
311 adg_model_set_named_pair(model, "RD34_R", &tmp);
313 tmp.x += part->RD34,
314 tmp.y += part->RD34,
315 adg_model_set_named_pair(model, "RD34_XY", &tmp);
317 pair.x += (part->D4 - part->D5) / 2;
318 pair.y = part->D5 / 2;
319 adg_path_line_to(path, &pair);
320 adg_model_set_named_pair(model, "D5I", &pair);
322 pair.x = part->A - part->C;
323 adg_path_line_to(path, &pair);
325 adg_path_fillet(path, 0.2);
327 pair.y = part->D6 / 2;
328 adg_path_line_to(path, &pair);
330 primitive = adg_path_over_primitive(path);
331 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
332 adg_model_set_named_pair(model, "D5F", &tmp);
334 adg_path_fillet(path, 0.1);
336 pair.x += part->LD6;
337 adg_path_line_to(path, &pair);
338 adg_model_set_named_pair(model, "D6F", &pair);
340 primitive = adg_path_over_primitive(path);
341 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
342 adg_model_set_named_pair(model, "D6I_X", &tmp);
344 primitive = adg_path_over_primitive(path);
345 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
346 adg_model_set_named_pair(model, "D6I_Y", &tmp);
348 pair.x = part->A - part->LD7;
349 pair.y -= (part->C - part->LD7 - part->LD6) / SQRT3;
350 adg_path_line_to(path, &pair);
351 adg_model_set_named_pair(model, "D67", &pair);
353 pair.y = part->D7 / 2;
354 adg_path_line_to(path, &pair);
356 pair.x = part->A;
357 adg_path_line_to(path, &pair);
358 adg_model_set_named_pair(model, "D7F", &pair);
360 adg_path_reflect(path, NULL);
361 adg_path_close(path);
364 static void
365 _adg_part_lock(DemoPart *part)
367 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), FALSE);
368 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), FALSE);
371 static void
372 _adg_part_unlock(DemoPart *part)
374 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), TRUE);
375 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), TRUE);
378 static void
379 _adg_part_link(DemoPart *part, gpointer data, GObject *widget)
381 const gchar *edit_signal;
383 g_assert(GTK_IS_WIDGET(widget));
384 g_object_ref(widget);
385 g_hash_table_insert(part->widgets, data, widget);
387 if (GTK_IS_SPIN_BUTTON(widget)) {
388 GtkSpinButton *spin_button = GTK_SPIN_BUTTON(widget);
389 gtk_adjustment_value_changed(gtk_spin_button_get_adjustment(spin_button));
392 edit_signal = GTK_IS_TOGGLE_BUTTON(widget) ? "toggled" : "changed";
393 g_signal_connect_swapped(widget, edit_signal,
394 G_CALLBACK(_adg_part_unlock), part);
397 static void
398 _adg_part_ui_to_boolean(DemoPart *part, gboolean *data)
400 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
402 g_assert(GTK_IS_TOGGLE_BUTTON(widget));
404 *data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
407 static void
408 _adg_part_ui_to_double(DemoPart *part, gdouble *data)
410 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
412 g_assert(GTK_IS_SPIN_BUTTON(widget));
414 *data = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
417 static void
418 _adg_part_ui_to_string(DemoPart *part, gchar **data)
420 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
422 g_assert(GTK_IS_ENTRY(widget));
424 g_free(*data);
425 *data = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
428 static void
429 _adg_part_boolean_to_ui(DemoPart *part, gboolean *data)
431 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
433 g_assert(GTK_IS_TOGGLE_BUTTON(widget));
435 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *data);
438 static void
439 _adg_part_double_to_ui(DemoPart *part, gdouble *data)
441 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
443 g_assert(GTK_IS_SPIN_BUTTON(widget));
445 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), *data);
448 static void
449 _adg_part_string_to_ui(DemoPart *part, gchar **data)
451 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
453 g_assert(GTK_IS_ENTRY(widget));
455 gtk_entry_set_text(GTK_ENTRY(widget), *data);
458 static void
459 _adg_demo_canvas_add_dimensions(AdgCanvas *canvas, AdgModel *model)
461 AdgLDim *ldim;
462 AdgADim *adim;
463 AdgRDim *rdim;
465 /* NORTH */
466 ldim = adg_ldim_new_full_from_model(model, "-D3I_X", "-D3F_X", "-D3F_Y",
467 ADG_DIR_UP);
468 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
469 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
471 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D67", "-East",
472 ADG_DIR_UP);
473 adg_dim_set_level(ADG_DIM(ldim), 0);
474 adg_ldim_switch_extension1(ldim, FALSE);
475 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
477 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D7F", "-East",
478 ADG_DIR_UP);
479 adg_dim_set_limits(ADG_DIM(ldim), "-0.06", NULL);
480 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
482 adim = adg_adim_new_full_from_model(model, "-D6I_Y", "-D6F",
483 "-D6F", "-D67", "-D6F");
484 adg_dim_set_level(ADG_DIM(adim), 2);
485 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
487 rdim = adg_rdim_new_full_from_model(model, "-RD34", "-RD34_R", "-RD34_XY");
488 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(rdim));
490 ldim = adg_ldim_new_full_from_model(model, "-DGROOVEI_X", "-DGROOVEF_X",
491 "-DGROOVEX_POS", ADG_DIR_UP);
492 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
494 ldim = adg_ldim_new_full_from_model(model, "D2I", "-D2I", "-D2_POS",
495 ADG_DIR_LEFT);
496 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
497 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
498 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
499 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
501 ldim = adg_ldim_new_full_from_model(model, "DGROOVEI_Y", "-DGROOVEI_Y",
502 "-DGROOVEY_POS", ADG_DIR_LEFT);
503 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
504 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
505 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
506 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
508 /* SOUTH */
509 adim = adg_adim_new_full_from_model(model, "D1F", "D1I", "D2I", "D1F", "D1F");
510 adg_dim_set_level(ADG_DIM(adim), 2);
511 adg_adim_switch_extension2(adim, FALSE);
512 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
514 ldim = adg_ldim_new_full_from_model(model, "D1I", "LHOLE", "West",
515 ADG_DIR_DOWN);
516 adg_ldim_switch_extension1(ldim, FALSE);
517 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
519 ldim = adg_ldim_new_full_from_model(model, "D1I", "DGROOVEI_X", "West",
520 ADG_DIR_DOWN);
521 adg_ldim_switch_extension1(ldim, FALSE);
522 adg_dim_set_level(ADG_DIM(ldim), 2);
523 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
525 ldim = adg_ldim_new_full_from_model(model, "D4F", "D6I_X", "D4_POS",
526 ADG_DIR_DOWN);
527 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.2");
528 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
529 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
531 ldim = adg_ldim_new_full_from_model(model, "D1F", "D3I_X", "D2_POS",
532 ADG_DIR_DOWN);
533 adg_dim_set_level(ADG_DIM(ldim), 2);
534 adg_ldim_switch_extension2(ldim, FALSE);
535 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
536 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
538 ldim = adg_ldim_new_full_from_model(model, "D3I_X", "D7F", "East",
539 ADG_DIR_DOWN);
540 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.1");
541 adg_dim_set_level(ADG_DIM(ldim), 2);
542 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
543 adg_ldim_switch_extension2(ldim, FALSE);
544 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
546 ldim = adg_ldim_new_full_from_model(model, "D1I", "D7F", "D3F_Y",
547 ADG_DIR_DOWN);
548 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
549 adg_dim_set_level(ADG_DIM(ldim), 3);
550 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
552 adim = adg_adim_new_full_from_model(model, "D4F", "D4I",
553 "D5I", "D4F", "D4F");
554 adg_dim_set_level(ADG_DIM(adim), 1.5);
555 adg_adim_switch_extension2(adim, FALSE);
556 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
558 /* EAST */
559 ldim = adg_ldim_new_full_from_model(model, "D6F", "-D6F", "East",
560 ADG_DIR_RIGHT);
561 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
562 adg_dim_set_level(ADG_DIM(ldim), 4);
563 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
564 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
566 ldim = adg_ldim_new_full_from_model(model, "D4F", "-D4F", "East",
567 ADG_DIR_RIGHT);
568 adg_dim_set_level(ADG_DIM(ldim), 3);
569 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
570 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
572 ldim = adg_ldim_new_full_from_model(model, "D5F", "-D5F", "East",
573 ADG_DIR_RIGHT);
574 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
575 adg_dim_set_level(ADG_DIM(ldim), 2);
576 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
577 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
579 ldim = adg_ldim_new_full_from_model(model, "D7F", "-D7F", "East",
580 ADG_DIR_RIGHT);
581 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
582 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
584 /* WEST */
585 ldim = adg_ldim_new_full_from_model(model, "DHOLE", "-DHOLE", "-West",
586 ADG_DIR_LEFT);
587 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
588 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
590 ldim = adg_ldim_new_full_from_model(model, "D1I", "-D1I", "-West",
591 ADG_DIR_LEFT);
592 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
593 adg_dim_set_level(ADG_DIM(ldim), 2);
594 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
595 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
597 ldim = adg_ldim_new_full_from_model(model, "D3I_Y", "-D3I_Y", "-West",
598 ADG_DIR_LEFT);
599 adg_dim_set_limits(ADG_DIM(ldim), "-0.25", NULL);
600 adg_dim_set_level(ADG_DIM(ldim), 3);
601 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
602 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
605 static AdgCanvas *
606 _adg_canvas_init(AdgCanvas *canvas, DemoPart *part)
608 AdgContainer *container;
609 AdgEntity *entity;
610 AdgMatrix map;
612 container = (AdgContainer *) canvas;
614 adg_canvas_set_paper(canvas, GTK_PAPER_NAME_A4,
615 GTK_PAGE_ORIENTATION_LANDSCAPE);
616 adg_canvas_set_title_block(canvas, part->title_block);
618 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->shape)));
619 adg_container_add(container, entity);
621 entity = ADG_ENTITY(adg_hatch_new(ADG_TRAIL(part->hatch)));
622 adg_container_add(container, entity);
624 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->hatch_edge)));
625 adg_container_add(container, entity);
627 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->edges)));
628 adg_container_add(container, entity);
630 _adg_demo_canvas_add_dimensions(canvas, ADG_MODEL(part->shape));
632 cairo_matrix_init_translate(&map, 140, 180);
633 cairo_matrix_scale(&map, 8, 8);
634 adg_entity_set_local_map(ADG_ENTITY(container), &map);
636 return canvas;
639 static GtkRadioButton *
640 _adg_group_get_active(GtkRadioButton *radio_group)
642 GSList *list = gtk_radio_button_get_group(radio_group);
644 while (list) {
645 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(list->data)))
646 return list->data;
648 list = list->next;
651 return NULL;
654 static void
655 _adg_do_edit(DemoPart *part)
657 _adg_part_ui_to_double(part, &part->A);
658 _adg_part_ui_to_double(part, &part->B);
659 _adg_part_ui_to_double(part, &part->C);
660 _adg_part_ui_to_double(part, &part->DHOLE);
661 _adg_part_ui_to_double(part, &part->LHOLE);
662 _adg_part_ui_to_double(part, &part->D1);
663 _adg_part_ui_to_double(part, &part->D2);
664 _adg_part_ui_to_double(part, &part->LD2);
665 _adg_part_ui_to_double(part, &part->D3);
666 _adg_part_ui_to_double(part, &part->LD3);
667 _adg_part_ui_to_double(part, &part->D4);
668 //_adg_part_ui_to_double(part, &part->D5);
669 _adg_part_ui_to_double(part, &part->D6);
670 //_adg_part_ui_to_double(part, &part->LD6);
671 _adg_part_ui_to_double(part, &part->D7);
672 //_adg_part_ui_to_double(part, &part->LD7);
674 _adg_part_ui_to_boolean(part, &part->GROOVE);
675 _adg_part_ui_to_double(part, &part->ZGROOVE);
676 _adg_part_ui_to_double(part, &part->DGROOVE);
677 _adg_part_ui_to_double(part, &part->LGROOVE);
679 _adg_part_ui_to_string(part, &part->TITLE);
680 _adg_part_ui_to_string(part, &part->DRAWING);
681 _adg_part_ui_to_string(part, &part->AUTHOR);
682 _adg_part_ui_to_string(part, &part->DATE);
684 _adg_part_lock(part);
686 adg_model_reset(ADG_MODEL(part->shape));
687 adg_model_reset(ADG_MODEL(part->hatch));
688 adg_model_reset(ADG_MODEL(part->hatch_edge));
689 adg_model_reset(ADG_MODEL(part->edges));
691 _adg_part_define_title_block(part);
692 _adg_part_define_shape(part);
693 _adg_part_define_hatch(part);
695 adg_model_changed(ADG_MODEL(part->shape));
696 adg_model_changed(ADG_MODEL(part->hatch));
697 adg_model_changed(ADG_MODEL(part->hatch_edge));
698 adg_model_changed(ADG_MODEL(part->edges));
700 gtk_widget_queue_draw(GTK_WIDGET(part->area));
703 static void
704 _adg_do_reset(DemoPart *part)
706 _adg_part_double_to_ui(part, &part->A);
707 _adg_part_double_to_ui(part, &part->B);
708 _adg_part_double_to_ui(part, &part->C);
709 _adg_part_double_to_ui(part, &part->DHOLE);
710 _adg_part_double_to_ui(part, &part->LHOLE);
711 _adg_part_double_to_ui(part, &part->D1);
712 _adg_part_double_to_ui(part, &part->D2);
713 _adg_part_double_to_ui(part, &part->LD2);
714 _adg_part_double_to_ui(part, &part->D3);
715 _adg_part_double_to_ui(part, &part->LD3);
716 _adg_part_double_to_ui(part, &part->D4);
717 //_adg_part_double_to_ui(part, &part->D5);
718 _adg_part_double_to_ui(part, &part->D6);
719 //_adg_part_double_to_ui(part, &part->LD6);
720 _adg_part_double_to_ui(part, &part->D7);
721 //_adg_part_double_to_ui(part, &part->LD7);
723 _adg_part_boolean_to_ui(part, &part->GROOVE);
724 _adg_part_double_to_ui(part, &part->ZGROOVE);
725 _adg_part_double_to_ui(part, &part->DGROOVE);
726 _adg_part_double_to_ui(part, &part->LGROOVE);
728 _adg_part_string_to_ui(part, &part->TITLE);
729 _adg_part_string_to_ui(part, &part->DRAWING);
730 _adg_part_string_to_ui(part, &part->AUTHOR);
731 _adg_part_string_to_ui(part, &part->DATE);
733 _adg_part_lock(part);
736 static void
737 _adg_do_save_as(GtkWindow *window, GtkResponseType response, AdgCanvas *canvas)
739 GtkRadioButton *type_radio;
740 gchar *file, *suffix;
741 cairo_surface_t *surface;
743 if (response != GTK_RESPONSE_OK) {
744 gtk_widget_hide(GTK_WIDGET(window));
745 return;
748 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(window));
749 if (file == NULL)
750 return;
752 type_radio = _adg_group_get_active(g_object_get_data(G_OBJECT(window),
753 "type-group"));
754 g_assert(GTK_IS_RADIO_BUTTON(type_radio));
755 suffix = gtk_widget_get_tooltip_markup(GTK_WIDGET(type_radio));
756 g_assert(suffix != NULL);
758 if (!g_str_has_suffix(file, suffix)) {
759 gchar *tmp = file;
760 file = g_strconcat(file, suffix, NULL);
761 g_free(tmp);
764 #ifdef CAIRO_HAS_PNG_FUNCTIONS
765 if (strcmp(suffix, ".png") == 0) {
766 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 800, 600);
767 } else
768 #endif
769 #ifdef CAIRO_HAS_SVG_SURFACE
770 if (strcmp(suffix, ".svg") == 0) {
771 #include <cairo-svg.h>
772 surface = cairo_svg_surface_create(file, 841, 595);
773 } else
774 #endif
775 #ifdef CAIRO_HAS_PDF_SURFACE
776 if (strcmp(suffix, ".pdf") == 0) {
777 #include <cairo-pdf.h>
778 surface = cairo_pdf_surface_create(file, 841, 595);
779 } else
780 #endif
781 #ifdef CAIRO_HAS_PS_SURFACE
782 if (strcmp(suffix, ".ps") == 0) {
783 #include <cairo-ps.h>
784 surface = cairo_ps_surface_create(file, 841, 595);
785 cairo_ps_surface_dsc_comment(surface, "%%Title: " PACKAGE_STRING);
786 cairo_ps_surface_dsc_comment(surface, "%%Copyright: Copyleft (C) 2006-2010 Fontana Nicola");
787 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Landscape");
788 cairo_ps_surface_dsc_begin_setup(surface);
789 cairo_ps_surface_dsc_begin_page_setup(surface);
790 cairo_ps_surface_dsc_comment(surface, "%%IncludeFeature: *PageSize A4");
791 } else
792 #endif
794 _adg_error(_("Requested format not supported"), window);
795 surface = NULL;
798 if (surface) {
799 cairo_t *cr;
800 cairo_status_t status;
802 cr = cairo_create(surface);
803 cairo_surface_destroy(surface);
804 adg_entity_render(ADG_ENTITY(canvas), cr);
806 if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) {
807 status = cairo_surface_write_to_png(surface, file);
808 } else {
809 cairo_show_page(cr);
810 status = cairo_status(cr);
813 cairo_destroy(cr);
815 if (status != CAIRO_STATUS_SUCCESS)
816 _adg_error(cairo_status_to_string(status), window);
819 g_free(file);
820 g_free(suffix);
821 gtk_widget_hide(GTK_WIDGET(window));
824 static void
825 _adg_print_prepare(GtkPrintOperation *operation, GtkPrintContext *context)
827 gtk_print_operation_set_n_pages(operation, 1);
830 static void
831 _adg_print_page(GtkPrintOperation *operation, GtkPrintContext *context,
832 gint page_nr, AdgEntity *canvas)
834 cairo_t *cr = gtk_print_context_get_cairo_context(context);
835 AdgMatrix old_map;
837 adg_matrix_copy(&old_map, adg_entity_get_global_map(canvas));;
839 adg_entity_set_global_map(canvas, adg_matrix_identity());
840 adg_entity_render(canvas, cr);
842 adg_entity_set_global_map(canvas, &old_map);
845 static void
846 _adg_do_print(GtkWidget *button, AdgCanvas *canvas)
848 static GtkPrintSettings *settings = NULL;
849 GtkWindow *window;
850 GtkPrintOperation *operation;
851 GtkPageSetup *page_setup;
852 GError *error;
854 window = (GtkWindow *) gtk_widget_get_toplevel(button);
855 operation = gtk_print_operation_new();
856 page_setup = g_object_get_data(G_OBJECT(canvas), "_adg_page_setup");
857 error = NULL;
859 if (settings)
860 gtk_print_operation_set_print_settings(operation, settings);
861 if (page_setup)
862 gtk_print_operation_set_default_page_setup(operation, page_setup);
864 g_signal_connect(operation, "begin-print",
865 G_CALLBACK(_adg_print_prepare), NULL);
866 g_signal_connect(operation, "draw-page",
867 G_CALLBACK(_adg_print_page), canvas);
869 gtk_print_operation_set_use_full_page(operation, FALSE);
870 gtk_print_operation_set_unit(operation, GTK_UNIT_POINTS);
871 #if GTK_CHECK_VERSION(2, 18, 0)
872 gtk_print_operation_set_embed_page_setup(operation, TRUE);
873 #endif
875 switch (gtk_print_operation_run(operation,
876 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
877 window, &error)) {
879 case GTK_PRINT_OPERATION_RESULT_APPLY:
880 if (settings)
881 g_object_unref(settings);
882 settings = gtk_print_operation_get_print_settings(operation);
883 if (settings)
884 g_object_ref(settings);
885 break;
887 default:
888 break;
891 g_object_unref(operation);
893 if (error)
894 _adg_error(error->message, window);
897 static DemoPart *
898 _adg_part_new(GtkBuilder *builder)
900 DemoPart *part;
901 GObject *object, *toggle_object;
903 part = g_new0(DemoPart, 1);
904 part->widgets = g_hash_table_new_full(g_direct_hash, g_direct_equal,
905 NULL, g_object_unref);
906 part->area = (AdgGtkArea *) gtk_builder_get_object(builder, "mainCanvas");
907 part->apply = (GtkButton *) gtk_builder_get_object(builder, "btnApply");
908 part->reset = (GtkButton *) gtk_builder_get_object(builder, "btnReset");
909 part->shape = adg_path_new();
910 part->hatch = adg_path_new();
911 part->hatch_edge = adg_path_new();
912 part->title_block = adg_title_block_new();
913 part->edges = adg_edges_new_with_source(ADG_TRAIL(part->shape));
915 g_assert(ADG_GTK_IS_AREA(part->area));
916 g_assert(GTK_IS_BUTTON(part->apply));
917 g_assert(GTK_IS_BUTTON(part->reset));
919 _adg_part_link(part, &part->A, gtk_builder_get_object(builder, "editA"));
920 _adg_part_link(part, &part->B, gtk_builder_get_object(builder, "editB"));
921 _adg_part_link(part, &part->C, gtk_builder_get_object(builder, "editC"));
922 _adg_part_link(part, &part->D1, gtk_builder_get_object(builder, "editD1"));
923 _adg_part_link(part, &part->D2, gtk_builder_get_object(builder, "editD2"));
924 _adg_part_link(part, &part->LD2, gtk_builder_get_object(builder, "editLD2"));
925 _adg_part_link(part, &part->D3, gtk_builder_get_object(builder, "editD3"));
926 _adg_part_link(part, &part->LD3, gtk_builder_get_object(builder, "editLD3"));
927 _adg_part_link(part, &part->D4, gtk_builder_get_object(builder, "editD4"));
928 //_adg_part_link(part, &part->D5, gtk_builder_get_object(builder, "editD5"));
929 _adg_part_link(part, &part->D6, gtk_builder_get_object(builder, "editD6"));
930 //_adg_part_link(part, &part->LD6, gtk_builder_get_object(builder, "editLD6"));
931 _adg_part_link(part, &part->D7, gtk_builder_get_object(builder, "editD7"));
932 //_adg_part_link(part, &part->LD7, gtk_builder_get_object(builder, "editLD7"));
933 _adg_part_link(part, &part->DHOLE, gtk_builder_get_object(builder, "editDHOLE"));
934 _adg_part_link(part, &part->LHOLE, gtk_builder_get_object(builder, "editLHOLE"));
936 toggle_object = gtk_builder_get_object(builder, "GROOVE");
937 _adg_part_link(part, &part->GROOVE, toggle_object);
939 object = gtk_builder_get_object(builder, "editZGROOVE");
940 _adg_part_link(part, &part->ZGROOVE, object);
941 g_signal_connect(toggle_object, "toggled",
942 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
943 object = gtk_builder_get_object(builder, "editZGROOVELabel");
944 g_signal_connect(toggle_object, "toggled",
945 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
947 object = gtk_builder_get_object(builder, "editDGROOVE");
948 _adg_part_link(part, &part->DGROOVE, object);
949 g_signal_connect(toggle_object, "toggled",
950 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
951 object = gtk_builder_get_object(builder, "editDGROOVELabel");
952 g_signal_connect(toggle_object, "toggled",
953 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
955 object = gtk_builder_get_object(builder, "editLGROOVE");
956 _adg_part_link(part, &part->LGROOVE, object);
957 g_signal_connect(toggle_object, "toggled",
958 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
959 object = gtk_builder_get_object(builder, "editLGROOVELabel");
960 g_signal_connect(toggle_object, "toggled",
961 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
963 _adg_part_link(part, &part->TITLE, gtk_builder_get_object(builder, "txtTitle"));
964 _adg_part_link(part, &part->DRAWING, gtk_builder_get_object(builder, "txtDrawing"));
965 _adg_part_link(part, &part->AUTHOR, gtk_builder_get_object(builder, "txtAuthor"));
966 _adg_part_link(part, &part->DATE, gtk_builder_get_object(builder, "txtDate"));
968 part->D5 = 4.5;
969 part->RD34 = 1;
970 part->LD5 = 5;
971 part->LD6 = 1;
972 part->LD7 = 0.5;
974 _adg_do_edit(part);
976 return part;
979 static void
980 _adg_part_destroy(DemoPart *part)
982 g_hash_table_destroy(part->widgets);
983 g_free(part);
986 static GtkWidget *
987 _adg_about_window(GtkBuilder *builder)
989 GtkWidget *window;
991 window = (GtkWidget *) gtk_builder_get_object(builder, "wndAbout");
992 g_assert(GTK_IS_ABOUT_DIALOG(window));
994 g_signal_connect(window, "response", G_CALLBACK(gtk_widget_hide), NULL);
996 return window;
999 static GtkWidget *
1000 _adg_edit_window(GtkBuilder *builder, DemoPart *part)
1002 GtkWidget *window;
1004 window = (GtkWidget *) gtk_builder_get_object(builder, "wndEdit");
1005 g_assert(GTK_IS_DIALOG(window));
1007 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
1009 g_signal_connect_swapped(part->apply, "clicked",
1010 G_CALLBACK(_adg_do_edit), part);
1011 g_signal_connect_swapped(part->reset, "clicked",
1012 G_CALLBACK(_adg_do_reset), part);
1013 g_signal_connect(window, "response",
1014 G_CALLBACK(adg_gtk_window_hide_here), NULL);
1016 return window;
1019 static GtkWidget *
1020 _adg_save_as_window(GtkBuilder *builder, AdgCanvas *canvas)
1022 GtkWidget *window;
1023 GtkWidget *type_group;
1025 window = (GtkWidget *) gtk_builder_get_object(builder, "wndSaveAs");
1026 g_assert(GTK_IS_WINDOW(window));
1027 type_group = (GtkWidget *) gtk_builder_get_object(builder, "saveAsPng");
1028 g_assert(GTK_IS_RADIO_BUTTON(type_group));
1030 g_object_set_data(G_OBJECT(window), "type-group", type_group);
1032 /* Set the default destination file */
1033 if (GTK_IS_FILE_CHOOSER(window)) {
1034 GtkFileChooser *file_chooser;
1035 const gchar *dir;
1037 file_chooser = (GtkFileChooser *) window;
1039 #if GLIB_CHECK_VERSION(2, 14, 0)
1040 dir = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
1041 #else
1042 dir = NULL;
1043 #endif
1045 if (dir == NULL)
1046 dir = g_get_home_dir();
1048 gtk_file_chooser_set_current_folder(file_chooser, dir);
1049 gtk_file_chooser_set_current_name(file_chooser, "adg-demo");
1052 g_signal_connect(window, "response", G_CALLBACK(_adg_do_save_as), canvas);
1054 return window;
1057 static GtkWidget *
1058 _adg_main_window(GtkBuilder *builder)
1060 GtkWidget *window;
1061 DemoPart *part;
1062 AdgCanvas *canvas;
1063 GtkWidget *button_edit, *button_save_as, *button_print;
1064 GtkWidget *button_about, *button_quit;
1066 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
1067 part = _adg_part_new(builder);
1068 canvas = adg_canvas_new();
1070 _adg_canvas_init(canvas, part);
1071 adg_gtk_area_set_canvas(part->area, canvas);
1073 g_assert(GTK_IS_WINDOW(window));
1074 button_edit = (GtkWidget *) gtk_builder_get_object(builder, "mainEdit");
1075 g_assert(GTK_IS_BUTTON(button_edit));
1076 button_save_as = (GtkWidget *) gtk_builder_get_object(builder, "mainSaveAs");
1077 g_assert(GTK_IS_BUTTON(button_save_as));
1078 button_print = (GtkWidget *) gtk_builder_get_object(builder, "mainPrint");
1079 g_assert(GTK_IS_BUTTON(button_print));
1080 button_about = (GtkWidget *) gtk_builder_get_object(builder, "mainAbout");
1081 g_assert(GTK_IS_BUTTON(button_about));
1082 button_quit = (GtkWidget *) gtk_builder_get_object(builder, "mainQuit");
1083 g_assert(GTK_IS_BUTTON(button_quit));
1085 g_signal_connect_swapped(button_about, "clicked",
1086 G_CALLBACK(gtk_dialog_run),
1087 _adg_about_window(builder));
1088 g_signal_connect_swapped(button_edit, "clicked",
1089 G_CALLBACK(gtk_dialog_run),
1090 _adg_edit_window(builder, part));
1091 g_signal_connect_swapped(button_save_as, "clicked",
1092 G_CALLBACK(gtk_dialog_run),
1093 _adg_save_as_window(builder, canvas));
1094 g_signal_connect(button_print, "clicked",
1095 G_CALLBACK(_adg_do_print), canvas);
1096 g_signal_connect(button_quit, "clicked", G_CALLBACK(gtk_main_quit), NULL);
1097 g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
1098 g_signal_connect_swapped(window, "destroy",
1099 G_CALLBACK(_adg_part_destroy), part);
1101 return window;
1106 main(gint argc, gchar **argv)
1108 gboolean show_extents;
1109 gchar *path;
1110 GtkBuilder *builder;
1111 GError *error;
1112 GtkWidget *main_window;
1114 _adg_parse_args(&argc, &argv, &show_extents);
1115 adg_switch_extents(show_extents);
1117 path = demo_find_data_file("adg-demo.ui", argv[0]);
1118 if (path == NULL) {
1119 g_print(_("adg-demo.ui not found!\n"));
1120 return 1;
1123 builder = gtk_builder_new();
1124 error = NULL;
1126 gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE);
1127 gtk_builder_add_from_file(builder, path, &error);
1129 if (error != NULL) {
1130 g_critical("%s", error->message);
1131 g_error_free(error);
1132 return 2;
1135 main_window = _adg_main_window(builder);
1136 g_object_unref(builder);
1138 gtk_widget_show_all(main_window);
1139 gtk_main();
1141 return 0;