demo: lookup icons on uninstalled demo
[adg.git] / demo / adg-demo.c
blobfafc4950bffb3eaa03213411651f5d023cad8c71
1 /* Needed for localization support */
2 #include <adg/adg-internal.h>
4 /* Force the reinclusion of adg.h */
5 #undef __ADG_H__
7 #include <adg.h>
8 #include <string.h>
9 #include <math.h>
11 #define SQRT3 1.732050808
12 #define CHAMFER 0.3
15 typedef struct _DemoPart DemoPart;
17 struct _DemoPart {
18 /* Dimensions */
19 gdouble A;
20 gdouble B;
21 gdouble C;
22 gdouble DHOLE;
23 gdouble LHOLE;
24 gdouble D1;
25 gdouble D2;
26 gdouble D3;
27 gdouble D4;
28 gdouble D5;
29 gdouble D6;
30 gdouble D7;
31 gdouble RD34;
32 gdouble RD56;
33 gdouble LD2;
34 gdouble LD3;
35 gdouble LD5;
36 gdouble LD6;
37 gdouble LD7;
38 gboolean GROOVE;
39 gdouble ZGROOVE;
40 gdouble DGROOVE;
41 gdouble LGROOVE;
43 /* Metadata */
44 gchar *TITLE;
45 gchar *DRAWING;
46 gchar *AUTHOR;
47 gchar *DATE;
49 /* User interface widgets */
50 AdgGtkArea *area;
51 GHashTable *widgets;
52 GtkButton *apply;
53 GtkButton *reset;
55 /* Data models */
56 AdgPath *shape;
57 AdgPath *hatch;
58 AdgPath *hatch_contour;
60 /* Special entities */
61 AdgTitleBlock *title_block;
62 AdgEdges *edges;
66 static void
67 _adg_version(void)
69 g_print("adg-demo " PACKAGE_VERSION "\n");
70 exit(0);
73 static void
74 _adg_parse_args(gint *p_argc, gchar **p_argv[], gboolean *show_extents)
76 GError *error = NULL;
77 GOptionEntry entries[] = {
78 {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
79 (gpointer) _adg_version, _("Display version information"), NULL},
80 {"show-extents", 'E', 0, G_OPTION_ARG_NONE,
81 NULL, _("Show the boundary boxes of every entity"), NULL},
82 {NULL}
85 entries[1].arg_data = show_extents;
86 *show_extents = FALSE;
87 gtk_init_with_args(p_argc, p_argv, _("- ADG demonstration program"),
88 entries, GETTEXT_PACKAGE, &error);
90 if (error != NULL) {
91 gint error_code = error->code;
93 g_printerr("%s\n", error->message);
95 g_error_free(error);
96 exit(error_code);
102 * _adg_error:
103 * @message: a custom error message
104 * @parent_window: the parent window or %NULL
106 * Convenient function that presents an error dialog and waits the user
107 * to close this modal dialog.
109 void
110 _adg_error(const gchar *message, GtkWindow *parent_window)
112 GtkWidget *dialog = gtk_message_dialog_new(parent_window,
113 GTK_DIALOG_DESTROY_WITH_PARENT,
114 GTK_MESSAGE_ERROR,
115 GTK_BUTTONS_CLOSE,
116 "%s", message);
117 gtk_window_set_title(GTK_WINDOW(dialog), _("Error from adg-demo"));
118 gtk_dialog_run(GTK_DIALOG(dialog));
119 gtk_widget_destroy(dialog);
122 static void
123 _adg_path_add_hole(AdgPath *path, const DemoPart *part)
125 AdgModel *model;
126 AdgPair pair;
128 model = ADG_MODEL(path);
129 pair.x = part->LHOLE;
130 pair.y = 0;
132 adg_path_move_to(path, &pair);
133 adg_model_set_named_pair(model, "LHOLE", &pair);
135 pair.y = part->DHOLE / 2;
136 pair.x -= pair.y / SQRT3;
137 adg_path_line_to(path, &pair);
139 pair.x = 0;
140 adg_path_line_to(path, &pair);
141 adg_model_set_named_pair(model, "DHOLE", &pair);
144 static void
145 _adg_path_add_rail(AdgPath *path, const DemoPart *part, gdouble to_x)
147 AdgModel *model;
148 AdgPair pair;
150 model = ADG_MODEL(path);
151 pair.x = 0;
152 pair.y = part->D1 / 2;
154 adg_path_line_to(path, &pair);
155 adg_model_set_named_pair(model, "D1I", &pair);
157 if (part->GROOVE && to_x > part->ZGROOVE) {
158 pair.x = part->ZGROOVE;
159 adg_path_line_to(path, &pair);
160 adg_model_set_named_pair(model, "DGROOVEI_X", &pair);
162 pair.y = part->D3 / 2;
163 adg_model_set_named_pair(model, "DGROOVEY_POS", &pair);
165 pair.y = part->DGROOVE / 2;
166 adg_path_line_to(path, &pair);
167 adg_model_set_named_pair(model, "DGROOVEI_Y", &pair);
169 pair.x += part->LGROOVE;
170 adg_path_line_to(path, &pair);
172 pair.y = part->D3 / 2;
173 adg_model_set_named_pair(model, "DGROOVEX_POS", &pair);
175 pair.y = part->D1 / 2;
176 adg_path_line_to(path, &pair);
177 adg_model_set_named_pair(model, "DGROOVEF_X", &pair);
180 pair.x = to_x;
181 adg_path_line_to(path, &pair);
182 adg_model_set_named_pair(model, "D1F", &pair);
186 static void
187 _adg_part_define_title_block(DemoPart *part)
189 g_object_set(part->title_block,
190 "title", part->TITLE,
191 "author", part->AUTHOR,
192 "date", part->DATE,
193 "drawing", part->DRAWING,
194 "logo", adg_logo_new(),
195 "projection", adg_projection_new(ADG_PROJECTION_FIRST_ANGLE),
196 "scale", "---",
197 "size", "A4",
198 NULL);
201 static void
202 _adg_part_define_hatch(DemoPart *part)
204 AdgPath *path;
205 AdgPair pair;
207 path = part->hatch;
208 pair.x = 0;
209 pair.y = (part->D1 + part->DHOLE) / 4;
211 _adg_path_add_hole(path, part);
212 adg_path_line_to(path, &pair);
213 adg_path_curve_to_explicit(path,
214 part->LHOLE / 2, part->DHOLE / 2,
215 part->LHOLE + 2, part->D1 / 2,
216 part->LHOLE + 2, 0);
217 adg_path_reflect(path, NULL);
218 adg_path_close(path);
220 path = part->hatch_contour;
221 adg_path_move_to(path, &pair);
222 adg_path_curve_to_explicit(path,
223 part->LHOLE / 2, part->DHOLE / 2,
224 part->LHOLE + 2, part->D1 / 2,
225 part->LHOLE + 2, 0);
226 adg_path_reflect(path, NULL);
229 static void
230 _adg_part_define_shape(DemoPart *part)
232 AdgModel *model;
233 AdgPath *path;
234 AdgPair pair, tmp;
235 const AdgPrimitive *primitive;
237 path = part->shape;
238 model = ADG_MODEL(path);
239 pair.x = part->A - part->B - part->LD2;
240 pair.y = part->D3 / 2;
241 adg_model_set_named_pair(model, "D2_POS", &pair);
243 _adg_path_add_hole(path, part);
244 _adg_path_add_rail(path, part, pair.x);
246 pair.x += (part->D1 - part->D2) / 2;
247 pair.y = part->D2 / 2;
248 adg_path_line_to(path, &pair);
249 adg_model_set_named_pair(model, "D2I", &pair);
251 pair.x = part->A - part->B;
252 adg_path_line_to(path, &pair);
253 adg_path_fillet(path, 0.4);
255 pair.x = part->A - part->B;
256 pair.y = part->D3 / 2;
257 adg_path_line_to(path, &pair);
258 adg_model_set_named_pair(model, "D3I", &pair);
260 pair.x = part->A;
261 adg_model_set_named_pair(model, "East", &pair);
263 pair.x = 0;
264 adg_model_set_named_pair(model, "West", &pair);
266 adg_path_chamfer(path, CHAMFER, CHAMFER);
268 pair.x = part->A - part->B + part->LD3;
269 pair.y = part->D3 / 2;
270 adg_path_line_to(path, &pair);
272 primitive = adg_path_over_primitive(path);
273 cpml_primitive_put_point(primitive, 0, &tmp);
274 adg_model_set_named_pair(model, "D3I_X", &tmp);
276 cpml_primitive_put_point(primitive, -1, &tmp);
277 adg_model_set_named_pair(model, "D3I_Y", &tmp);
279 adg_path_chamfer(path, CHAMFER, CHAMFER);
281 pair.y = part->D4 / 2;
282 adg_path_line_to(path, &pair);
284 primitive = adg_path_over_primitive(path);
285 cpml_primitive_put_point(primitive, 0, &tmp);
286 adg_model_set_named_pair(model, "D3F_Y", &tmp);
287 cpml_primitive_put_point(primitive, -1, &tmp);
288 adg_model_set_named_pair(model, "D3F_X", &tmp);
290 adg_path_fillet(path, part->RD34);
292 pair.x += part->RD34;
293 adg_model_set_named_pair(model, "D4I", &pair);
295 pair.x = part->A - part->C - part->LD5;
296 adg_path_line_to(path, &pair);
297 adg_model_set_named_pair(model, "D4F", &pair);
299 pair.y = part->D3 / 2;
300 adg_model_set_named_pair(model, "D4_POS", &pair);
302 primitive = adg_path_over_primitive(path);
303 cpml_primitive_put_point(primitive, 0, &tmp);
304 tmp.x += part->RD34;
305 adg_model_set_named_pair(model, "RD34", &tmp);
307 tmp.x -= cos(G_PI_4) * part->RD34,
308 tmp.y -= sin(G_PI_4) * part->RD34,
309 adg_model_set_named_pair(model, "RD34_R", &tmp);
311 tmp.x += part->RD34,
312 tmp.y += part->RD34,
313 adg_model_set_named_pair(model, "RD34_XY", &tmp);
315 pair.x += (part->D4 - part->D5) / 2;
316 pair.y = part->D5 / 2;
317 adg_path_line_to(path, &pair);
318 adg_model_set_named_pair(model, "D5I", &pair);
320 pair.x = part->A - part->C;
321 adg_path_line_to(path, &pair);
323 adg_path_fillet(path, 0.2);
325 pair.y = part->D6 / 2;
326 adg_path_line_to(path, &pair);
328 primitive = adg_path_over_primitive(path);
329 cpml_primitive_put_point(primitive, 0, &tmp);
330 adg_model_set_named_pair(model, "D5F", &tmp);
332 adg_path_fillet(path, 0.1);
334 pair.x += part->LD6;
335 adg_path_line_to(path, &pair);
336 adg_model_set_named_pair(model, "D6F", &pair);
338 primitive = adg_path_over_primitive(path);
339 cpml_primitive_put_point(primitive, 0, &tmp);
340 adg_model_set_named_pair(model, "D6I_X", &tmp);
342 primitive = adg_path_over_primitive(path);
343 cpml_primitive_put_point(primitive, -1, &tmp);
344 adg_model_set_named_pair(model, "D6I_Y", &tmp);
346 pair.x = part->A - part->LD7;
347 pair.y -= (part->C - part->LD7 - part->LD6) / SQRT3;
348 adg_path_line_to(path, &pair);
349 adg_model_set_named_pair(model, "D67", &pair);
351 pair.y = part->D7 / 2;
352 adg_path_line_to(path, &pair);
354 pair.x = part->A;
355 adg_path_line_to(path, &pair);
356 adg_model_set_named_pair(model, "D7F", &pair);
358 adg_path_reflect(path, NULL);
359 adg_path_close(path);
362 static void
363 _adg_part_lock(DemoPart *part)
365 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), FALSE);
366 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), FALSE);
369 static void
370 _adg_part_unlock(DemoPart *part)
372 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), TRUE);
373 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), TRUE);
376 static void
377 _adg_part_link(DemoPart *part, gpointer data, GObject *widget)
379 const gchar *edit_signal;
381 g_assert(GTK_IS_WIDGET(widget));
382 g_object_ref(widget);
383 g_hash_table_insert(part->widgets, data, widget);
385 if (GTK_IS_SPIN_BUTTON(widget)) {
386 GtkSpinButton *spin_button = GTK_SPIN_BUTTON(widget);
387 gtk_adjustment_value_changed(gtk_spin_button_get_adjustment(spin_button));
390 edit_signal = GTK_IS_TOGGLE_BUTTON(widget) ? "toggled" : "changed";
391 g_signal_connect_swapped(widget, edit_signal,
392 G_CALLBACK(_adg_part_unlock), part);
395 static void
396 _adg_part_ui_to_boolean(DemoPart *part, gboolean *data)
398 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
400 g_assert(GTK_IS_TOGGLE_BUTTON(widget));
402 *data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
405 static void
406 _adg_part_ui_to_double(DemoPart *part, gdouble *data)
408 GtkWidget *widget;
409 GtkSpinButton *spin_button;
411 widget = g_hash_table_lookup(part->widgets, data);
412 g_assert(GTK_IS_SPIN_BUTTON(widget));
414 spin_button = GTK_SPIN_BUTTON(widget);
415 gtk_spin_button_update(spin_button);
416 *data = gtk_spin_button_get_value(spin_button);
419 static void
420 _adg_part_ui_to_string(DemoPart *part, gchar **data)
422 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
424 g_assert(GTK_IS_ENTRY(widget));
426 g_free(*data);
427 *data = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
430 static void
431 _adg_part_boolean_to_ui(DemoPart *part, gboolean *data)
433 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
435 g_assert(GTK_IS_TOGGLE_BUTTON(widget));
437 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *data);
440 static void
441 _adg_part_double_to_ui(DemoPart *part, gdouble *data)
443 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
445 g_assert(GTK_IS_SPIN_BUTTON(widget));
447 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), *data);
450 static void
451 _adg_part_string_to_ui(DemoPart *part, gchar **data)
453 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
455 g_assert(GTK_IS_ENTRY(widget));
457 gtk_entry_set_text(GTK_ENTRY(widget), *data);
460 static void
461 _adg_demo_canvas_add_dimensions(AdgCanvas *canvas, AdgModel *model)
463 AdgLDim *ldim;
464 AdgADim *adim;
465 AdgRDim *rdim;
467 /* NORTH */
468 ldim = adg_ldim_new_full_from_model(model, "-D3I_X", "-D3F_X", "-D3F_Y",
469 ADG_DIR_UP);
470 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
471 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
473 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D67", "-East",
474 ADG_DIR_UP);
475 adg_dim_set_level(ADG_DIM(ldim), 0);
476 adg_ldim_switch_extension1(ldim, FALSE);
477 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
479 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D7F", "-East",
480 ADG_DIR_UP);
481 adg_dim_set_limits(ADG_DIM(ldim), "-0.06", NULL);
482 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
484 adim = adg_adim_new_full_from_model(model, "-D6I_Y", "-D6F",
485 "-D6F", "-D67", "-D6F");
486 adg_dim_set_level(ADG_DIM(adim), 2);
487 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
489 rdim = adg_rdim_new_full_from_model(model, "-RD34", "-RD34_R", "-RD34_XY");
490 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(rdim));
492 ldim = adg_ldim_new_full_from_model(model, "-DGROOVEI_X", "-DGROOVEF_X",
493 "-DGROOVEX_POS", ADG_DIR_UP);
494 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
496 ldim = adg_ldim_new_full_from_model(model, "D2I", "-D2I", "-D2_POS",
497 ADG_DIR_LEFT);
498 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
499 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
500 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
501 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
503 ldim = adg_ldim_new_full_from_model(model, "DGROOVEI_Y", "-DGROOVEI_Y",
504 "-DGROOVEY_POS", ADG_DIR_LEFT);
505 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
506 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
507 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
508 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
510 /* SOUTH */
511 adim = adg_adim_new_full_from_model(model, "D1F", "D1I", "D2I", "D1F", "D1F");
512 adg_dim_set_level(ADG_DIM(adim), 2);
513 adg_adim_switch_extension2(adim, FALSE);
514 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
516 ldim = adg_ldim_new_full_from_model(model, "D1I", "LHOLE", "West",
517 ADG_DIR_DOWN);
518 adg_ldim_switch_extension1(ldim, FALSE);
519 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
521 ldim = adg_ldim_new_full_from_model(model, "D1I", "DGROOVEI_X", "West",
522 ADG_DIR_DOWN);
523 adg_ldim_switch_extension1(ldim, FALSE);
524 adg_dim_set_level(ADG_DIM(ldim), 2);
525 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
527 ldim = adg_ldim_new_full_from_model(model, "D4F", "D6I_X", "D4_POS",
528 ADG_DIR_DOWN);
529 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.2");
530 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
531 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
533 ldim = adg_ldim_new_full_from_model(model, "D1F", "D3I_X", "D2_POS",
534 ADG_DIR_DOWN);
535 adg_dim_set_level(ADG_DIM(ldim), 2);
536 adg_ldim_switch_extension2(ldim, FALSE);
537 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
538 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
540 ldim = adg_ldim_new_full_from_model(model, "D3I_X", "D7F", "East",
541 ADG_DIR_DOWN);
542 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.1");
543 adg_dim_set_level(ADG_DIM(ldim), 2);
544 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
545 adg_ldim_switch_extension2(ldim, FALSE);
546 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
548 ldim = adg_ldim_new_full_from_model(model, "D1I", "D7F", "D3F_Y",
549 ADG_DIR_DOWN);
550 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
551 adg_dim_set_level(ADG_DIM(ldim), 3);
552 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
554 adim = adg_adim_new_full_from_model(model, "D4F", "D4I",
555 "D5I", "D4F", "D4F");
556 adg_dim_set_level(ADG_DIM(adim), 1.5);
557 adg_adim_switch_extension2(adim, FALSE);
558 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
560 /* EAST */
561 ldim = adg_ldim_new_full_from_model(model, "D6F", "-D6F", "East",
562 ADG_DIR_RIGHT);
563 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
564 adg_dim_set_level(ADG_DIM(ldim), 4);
565 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
566 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
568 ldim = adg_ldim_new_full_from_model(model, "D4F", "-D4F", "East",
569 ADG_DIR_RIGHT);
570 adg_dim_set_level(ADG_DIM(ldim), 3);
571 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
572 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
574 ldim = adg_ldim_new_full_from_model(model, "D5F", "-D5F", "East",
575 ADG_DIR_RIGHT);
576 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
577 adg_dim_set_level(ADG_DIM(ldim), 2);
578 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
579 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
581 ldim = adg_ldim_new_full_from_model(model, "D7F", "-D7F", "East",
582 ADG_DIR_RIGHT);
583 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
584 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
586 /* WEST */
587 ldim = adg_ldim_new_full_from_model(model, "DHOLE", "-DHOLE", "-West",
588 ADG_DIR_LEFT);
589 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
590 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
592 ldim = adg_ldim_new_full_from_model(model, "D1I", "-D1I", "-West",
593 ADG_DIR_LEFT);
594 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
595 adg_dim_set_level(ADG_DIM(ldim), 2);
596 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
597 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
599 ldim = adg_ldim_new_full_from_model(model, "D3I_Y", "-D3I_Y", "-West",
600 ADG_DIR_LEFT);
601 adg_dim_set_limits(ADG_DIM(ldim), "-0.25", NULL);
602 adg_dim_set_level(ADG_DIM(ldim), 3);
603 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
604 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
607 static AdgCanvas *
608 _adg_canvas_init(AdgCanvas *canvas, DemoPart *part)
610 AdgContainer *container;
611 AdgEntity *entity;
612 AdgMatrix map;
614 container = (AdgContainer *) canvas;
616 adg_canvas_set_paper(canvas, GTK_PAPER_NAME_A4,
617 GTK_PAGE_ORIENTATION_LANDSCAPE);
618 adg_canvas_set_title_block(canvas, part->title_block);
620 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->shape)));
621 adg_container_add(container, entity);
623 entity = ADG_ENTITY(adg_hatch_new(ADG_TRAIL(part->hatch)));
624 adg_container_add(container, entity);
626 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->hatch_contour)));
627 adg_container_add(container, entity);
629 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->edges)));
630 adg_container_add(container, entity);
632 _adg_demo_canvas_add_dimensions(canvas, ADG_MODEL(part->shape));
634 cairo_matrix_init_translate(&map, 140, 180);
635 cairo_matrix_scale(&map, 8, 8);
636 adg_entity_set_local_map(ADG_ENTITY(container), &map);
638 return canvas;
641 static GtkRadioButton *
642 _adg_group_get_active(GtkRadioButton *radio_group)
644 GSList *list = gtk_radio_button_get_group(radio_group);
646 while (list) {
647 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(list->data)))
648 return list->data;
650 list = list->next;
653 return NULL;
656 static void
657 _adg_do_edit(DemoPart *part)
659 _adg_part_ui_to_double(part, &part->A);
660 _adg_part_ui_to_double(part, &part->B);
661 _adg_part_ui_to_double(part, &part->C);
662 _adg_part_ui_to_double(part, &part->DHOLE);
663 _adg_part_ui_to_double(part, &part->LHOLE);
664 _adg_part_ui_to_double(part, &part->D1);
665 _adg_part_ui_to_double(part, &part->D2);
666 _adg_part_ui_to_double(part, &part->LD2);
667 _adg_part_ui_to_double(part, &part->D3);
668 _adg_part_ui_to_double(part, &part->LD3);
669 _adg_part_ui_to_double(part, &part->D4);
670 //_adg_part_ui_to_double(part, &part->D5);
671 _adg_part_ui_to_double(part, &part->D6);
672 //_adg_part_ui_to_double(part, &part->LD6);
673 _adg_part_ui_to_double(part, &part->D7);
674 //_adg_part_ui_to_double(part, &part->LD7);
676 _adg_part_ui_to_boolean(part, &part->GROOVE);
677 _adg_part_ui_to_double(part, &part->ZGROOVE);
678 _adg_part_ui_to_double(part, &part->DGROOVE);
679 _adg_part_ui_to_double(part, &part->LGROOVE);
681 _adg_part_ui_to_string(part, &part->TITLE);
682 _adg_part_ui_to_string(part, &part->DRAWING);
683 _adg_part_ui_to_string(part, &part->AUTHOR);
684 _adg_part_ui_to_string(part, &part->DATE);
686 _adg_part_lock(part);
688 adg_model_reset(ADG_MODEL(part->shape));
689 adg_model_reset(ADG_MODEL(part->hatch));
690 adg_model_reset(ADG_MODEL(part->hatch_contour));
691 adg_model_reset(ADG_MODEL(part->edges));
693 _adg_part_define_title_block(part);
694 _adg_part_define_shape(part);
695 _adg_part_define_hatch(part);
697 adg_model_changed(ADG_MODEL(part->shape));
698 adg_model_changed(ADG_MODEL(part->hatch));
699 adg_model_changed(ADG_MODEL(part->hatch_contour));
700 adg_model_changed(ADG_MODEL(part->edges));
702 gtk_widget_queue_draw(GTK_WIDGET(part->area));
705 static void
706 _adg_do_reset(DemoPart *part)
708 _adg_part_double_to_ui(part, &part->A);
709 _adg_part_double_to_ui(part, &part->B);
710 _adg_part_double_to_ui(part, &part->C);
711 _adg_part_double_to_ui(part, &part->DHOLE);
712 _adg_part_double_to_ui(part, &part->LHOLE);
713 _adg_part_double_to_ui(part, &part->D1);
714 _adg_part_double_to_ui(part, &part->D2);
715 _adg_part_double_to_ui(part, &part->LD2);
716 _adg_part_double_to_ui(part, &part->D3);
717 _adg_part_double_to_ui(part, &part->LD3);
718 _adg_part_double_to_ui(part, &part->D4);
719 //_adg_part_double_to_ui(part, &part->D5);
720 _adg_part_double_to_ui(part, &part->D6);
721 //_adg_part_double_to_ui(part, &part->LD6);
722 _adg_part_double_to_ui(part, &part->D7);
723 //_adg_part_double_to_ui(part, &part->LD7);
725 _adg_part_boolean_to_ui(part, &part->GROOVE);
726 _adg_part_double_to_ui(part, &part->ZGROOVE);
727 _adg_part_double_to_ui(part, &part->DGROOVE);
728 _adg_part_double_to_ui(part, &part->LGROOVE);
730 _adg_part_string_to_ui(part, &part->TITLE);
731 _adg_part_string_to_ui(part, &part->DRAWING);
732 _adg_part_string_to_ui(part, &part->AUTHOR);
733 _adg_part_string_to_ui(part, &part->DATE);
735 _adg_part_lock(part);
738 static void
739 _adg_do_save_as(GtkWindow *window, GtkResponseType response, AdgCanvas *canvas)
741 GtkRadioButton *type_radio;
742 gchar *file, *suffix;
743 cairo_surface_t *surface;
745 if (response != GTK_RESPONSE_OK) {
746 gtk_widget_hide(GTK_WIDGET(window));
747 return;
750 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(window));
751 if (file == NULL)
752 return;
754 type_radio = _adg_group_get_active(g_object_get_data(G_OBJECT(window),
755 "type-group"));
756 g_assert(GTK_IS_RADIO_BUTTON(type_radio));
757 suffix = gtk_widget_get_tooltip_markup(GTK_WIDGET(type_radio));
758 g_assert(suffix != NULL);
760 if (!g_str_has_suffix(file, suffix)) {
761 gchar *tmp = file;
762 file = g_strconcat(file, suffix, NULL);
763 g_free(tmp);
766 #ifdef CAIRO_HAS_PNG_FUNCTIONS
767 if (strcmp(suffix, ".png") == 0) {
768 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 800, 600);
769 } else
770 #endif
771 #ifdef CAIRO_HAS_SVG_SURFACE
772 if (strcmp(suffix, ".svg") == 0) {
773 #include <cairo-svg.h>
774 surface = cairo_svg_surface_create(file, 841, 595);
775 } else
776 #endif
777 #ifdef CAIRO_HAS_PDF_SURFACE
778 if (strcmp(suffix, ".pdf") == 0) {
779 #include <cairo-pdf.h>
780 surface = cairo_pdf_surface_create(file, 841, 595);
781 } else
782 #endif
783 #ifdef CAIRO_HAS_PS_SURFACE
784 if (strcmp(suffix, ".ps") == 0) {
785 #include <cairo-ps.h>
786 surface = cairo_ps_surface_create(file, 841, 595);
787 cairo_ps_surface_dsc_comment(surface, "%%Title: " PACKAGE_STRING);
788 cairo_ps_surface_dsc_comment(surface, "%%Copyright: Copyleft (C) 2006-2010 Fontana Nicola");
789 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Landscape");
790 cairo_ps_surface_dsc_begin_setup(surface);
791 cairo_ps_surface_dsc_begin_page_setup(surface);
792 cairo_ps_surface_dsc_comment(surface, "%%IncludeFeature: *PageSize A4");
793 } else
794 #endif
796 _adg_error(_("Requested format not supported"), window);
797 surface = NULL;
800 if (surface) {
801 cairo_t *cr;
802 cairo_status_t status;
804 cr = cairo_create(surface);
805 cairo_surface_destroy(surface);
806 adg_entity_render(ADG_ENTITY(canvas), cr);
808 if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) {
809 status = cairo_surface_write_to_png(surface, file);
810 } else {
811 cairo_show_page(cr);
812 status = cairo_status(cr);
815 cairo_destroy(cr);
817 if (status != CAIRO_STATUS_SUCCESS)
818 _adg_error(cairo_status_to_string(status), window);
821 g_free(file);
822 g_free(suffix);
823 gtk_widget_hide(GTK_WIDGET(window));
826 static void
827 _adg_print_prepare(GtkPrintOperation *operation, GtkPrintContext *context)
829 gtk_print_operation_set_n_pages(operation, 1);
832 static void
833 _adg_print_page(GtkPrintOperation *operation, GtkPrintContext *context,
834 gint page_nr, AdgEntity *canvas)
836 cairo_t *cr = gtk_print_context_get_cairo_context(context);
837 AdgMatrix old_map;
839 adg_matrix_copy(&old_map, adg_entity_get_global_map(canvas));;
841 adg_entity_set_global_map(canvas, adg_matrix_identity());
842 adg_entity_render(canvas, cr);
844 adg_entity_set_global_map(canvas, &old_map);
847 static void
848 _adg_do_print(GtkWidget *button, AdgCanvas *canvas)
850 static GtkPrintSettings *settings = NULL;
851 GtkWindow *window;
852 GtkPrintOperation *operation;
853 GtkPageSetup *page_setup;
854 GError *error;
856 window = (GtkWindow *) gtk_widget_get_toplevel(button);
857 operation = gtk_print_operation_new();
858 page_setup = g_object_get_data(G_OBJECT(canvas), "_adg_page_setup");
859 error = NULL;
861 if (settings)
862 gtk_print_operation_set_print_settings(operation, settings);
863 if (page_setup)
864 gtk_print_operation_set_default_page_setup(operation, page_setup);
866 g_signal_connect(operation, "begin-print",
867 G_CALLBACK(_adg_print_prepare), NULL);
868 g_signal_connect(operation, "draw-page",
869 G_CALLBACK(_adg_print_page), canvas);
871 gtk_print_operation_set_use_full_page(operation, FALSE);
872 gtk_print_operation_set_unit(operation, GTK_UNIT_POINTS);
873 #if GTK_CHECK_VERSION(2, 18, 0)
874 gtk_print_operation_set_embed_page_setup(operation, TRUE);
875 #endif
877 switch (gtk_print_operation_run(operation,
878 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
879 window, &error)) {
881 case GTK_PRINT_OPERATION_RESULT_APPLY:
882 if (settings)
883 g_object_unref(settings);
884 settings = gtk_print_operation_get_print_settings(operation);
885 if (settings)
886 g_object_ref(settings);
887 break;
889 default:
890 break;
893 g_object_unref(operation);
895 if (error)
896 _adg_error(error->message, window);
899 static DemoPart *
900 _adg_part_new(GtkBuilder *builder)
902 DemoPart *part;
903 GObject *object, *toggle_object;
905 part = g_new0(DemoPart, 1);
906 part->widgets = g_hash_table_new_full(g_direct_hash, g_direct_equal,
907 NULL, g_object_unref);
908 part->area = (AdgGtkArea *) gtk_builder_get_object(builder, "mainCanvas");
909 part->apply = (GtkButton *) gtk_builder_get_object(builder, "btnApply");
910 part->reset = (GtkButton *) gtk_builder_get_object(builder, "btnReset");
911 part->shape = adg_path_new();
912 part->hatch = adg_path_new();
913 part->hatch_contour = adg_path_new();
914 part->title_block = adg_title_block_new();
915 part->edges = adg_edges_new_with_source(ADG_TRAIL(part->shape));
917 g_assert(ADG_GTK_IS_AREA(part->area));
918 g_assert(GTK_IS_BUTTON(part->apply));
919 g_assert(GTK_IS_BUTTON(part->reset));
921 _adg_part_link(part, &part->A, gtk_builder_get_object(builder, "editA"));
922 _adg_part_link(part, &part->B, gtk_builder_get_object(builder, "editB"));
923 _adg_part_link(part, &part->C, gtk_builder_get_object(builder, "editC"));
924 _adg_part_link(part, &part->D1, gtk_builder_get_object(builder, "editD1"));
925 _adg_part_link(part, &part->D2, gtk_builder_get_object(builder, "editD2"));
926 _adg_part_link(part, &part->LD2, gtk_builder_get_object(builder, "editLD2"));
927 _adg_part_link(part, &part->D3, gtk_builder_get_object(builder, "editD3"));
928 _adg_part_link(part, &part->LD3, gtk_builder_get_object(builder, "editLD3"));
929 _adg_part_link(part, &part->D4, gtk_builder_get_object(builder, "editD4"));
930 //_adg_part_link(part, &part->D5, gtk_builder_get_object(builder, "editD5"));
931 _adg_part_link(part, &part->D6, gtk_builder_get_object(builder, "editD6"));
932 //_adg_part_link(part, &part->LD6, gtk_builder_get_object(builder, "editLD6"));
933 _adg_part_link(part, &part->D7, gtk_builder_get_object(builder, "editD7"));
934 //_adg_part_link(part, &part->LD7, gtk_builder_get_object(builder, "editLD7"));
935 _adg_part_link(part, &part->DHOLE, gtk_builder_get_object(builder, "editDHOLE"));
936 _adg_part_link(part, &part->LHOLE, gtk_builder_get_object(builder, "editLHOLE"));
938 toggle_object = gtk_builder_get_object(builder, "GROOVE");
939 _adg_part_link(part, &part->GROOVE, toggle_object);
941 object = gtk_builder_get_object(builder, "editZGROOVE");
942 _adg_part_link(part, &part->ZGROOVE, object);
943 g_signal_connect(toggle_object, "toggled",
944 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
945 object = gtk_builder_get_object(builder, "editZGROOVELabel");
946 g_signal_connect(toggle_object, "toggled",
947 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
949 object = gtk_builder_get_object(builder, "editDGROOVE");
950 _adg_part_link(part, &part->DGROOVE, object);
951 g_signal_connect(toggle_object, "toggled",
952 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
953 object = gtk_builder_get_object(builder, "editDGROOVELabel");
954 g_signal_connect(toggle_object, "toggled",
955 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
957 object = gtk_builder_get_object(builder, "editLGROOVE");
958 _adg_part_link(part, &part->LGROOVE, object);
959 g_signal_connect(toggle_object, "toggled",
960 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
961 object = gtk_builder_get_object(builder, "editLGROOVELabel");
962 g_signal_connect(toggle_object, "toggled",
963 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
965 _adg_part_link(part, &part->TITLE, gtk_builder_get_object(builder, "txtTitle"));
966 _adg_part_link(part, &part->DRAWING, gtk_builder_get_object(builder, "txtDrawing"));
967 _adg_part_link(part, &part->AUTHOR, gtk_builder_get_object(builder, "txtAuthor"));
968 _adg_part_link(part, &part->DATE, gtk_builder_get_object(builder, "txtDate"));
970 part->D5 = 4.5;
971 part->RD34 = 1;
972 part->LD5 = 5;
973 part->LD6 = 1;
974 part->LD7 = 0.5;
976 _adg_do_edit(part);
978 return part;
981 static void
982 _adg_part_destroy(DemoPart *part)
984 g_hash_table_destroy(part->widgets);
985 g_free(part);
988 static GtkWidget *
989 _adg_about_window(GtkBuilder *builder)
991 GtkWidget *window;
992 GList *icon_list, *last_node;
994 window = (GtkWidget *) gtk_builder_get_object(builder, "wndAbout");
995 g_assert(GTK_IS_ABOUT_DIALOG(window));
996 g_signal_connect(window, "response", G_CALLBACK(gtk_widget_hide), NULL);
998 icon_list = gtk_window_get_default_icon_list();
999 last_node = g_list_last(icon_list);
1000 if (last_node != NULL) {
1001 /* The last icon is supposed to be the largest one:
1002 * check adg_gtk_use_default_icons() implementation. */
1003 GdkPixbuf *last_icon = last_node->data;
1004 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(window), last_icon);
1006 g_list_free(icon_list);
1008 return window;
1011 static GtkWidget *
1012 _adg_edit_window(GtkBuilder *builder, DemoPart *part)
1014 GtkWidget *window;
1016 window = (GtkWidget *) gtk_builder_get_object(builder, "wndEdit");
1017 g_assert(GTK_IS_DIALOG(window));
1019 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
1021 g_signal_connect_swapped(part->apply, "clicked",
1022 G_CALLBACK(_adg_do_edit), part);
1023 g_signal_connect_swapped(part->reset, "clicked",
1024 G_CALLBACK(_adg_do_reset), part);
1025 g_signal_connect(window, "response",
1026 G_CALLBACK(adg_gtk_window_hide_here), NULL);
1028 return window;
1031 static GtkWidget *
1032 _adg_save_as_window(GtkBuilder *builder, AdgCanvas *canvas)
1034 GtkWidget *window;
1035 GtkWidget *type_group;
1037 window = (GtkWidget *) gtk_builder_get_object(builder, "wndSaveAs");
1038 g_assert(GTK_IS_WINDOW(window));
1039 type_group = (GtkWidget *) gtk_builder_get_object(builder, "saveAsPng");
1040 g_assert(GTK_IS_RADIO_BUTTON(type_group));
1042 g_object_set_data(G_OBJECT(window), "type-group", type_group);
1044 /* Set the default destination file */
1045 if (GTK_IS_FILE_CHOOSER(window)) {
1046 GtkFileChooser *file_chooser;
1047 const gchar *dir;
1049 file_chooser = (GtkFileChooser *) window;
1051 #if GLIB_CHECK_VERSION(2, 14, 0)
1052 dir = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
1053 #else
1054 dir = NULL;
1055 #endif
1057 if (dir == NULL)
1058 dir = g_get_home_dir();
1060 gtk_file_chooser_set_current_folder(file_chooser, dir);
1061 gtk_file_chooser_set_current_name(file_chooser, "adg-demo");
1064 g_signal_connect(window, "response", G_CALLBACK(_adg_do_save_as), canvas);
1066 return window;
1069 static GtkWidget *
1070 _adg_main_window(GtkBuilder *builder)
1072 GtkWidget *window;
1073 DemoPart *part;
1074 AdgCanvas *canvas;
1075 GtkWidget *button_edit, *button_save_as, *button_print;
1076 GtkWidget *button_about, *button_quit;
1078 adg_gtk_use_default_icons(SRCDIR);
1080 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
1081 part = _adg_part_new(builder);
1082 canvas = adg_canvas_new();
1084 _adg_canvas_init(canvas, part);
1085 adg_gtk_area_set_canvas(part->area, canvas);
1087 g_assert(GTK_IS_WINDOW(window));
1088 button_edit = (GtkWidget *) gtk_builder_get_object(builder, "mainEdit");
1089 g_assert(GTK_IS_BUTTON(button_edit));
1090 button_save_as = (GtkWidget *) gtk_builder_get_object(builder, "mainSaveAs");
1091 g_assert(GTK_IS_BUTTON(button_save_as));
1092 button_print = (GtkWidget *) gtk_builder_get_object(builder, "mainPrint");
1093 g_assert(GTK_IS_BUTTON(button_print));
1094 button_about = (GtkWidget *) gtk_builder_get_object(builder, "mainAbout");
1095 g_assert(GTK_IS_BUTTON(button_about));
1096 button_quit = (GtkWidget *) gtk_builder_get_object(builder, "mainQuit");
1097 g_assert(GTK_IS_BUTTON(button_quit));
1099 g_signal_connect_swapped(button_about, "clicked",
1100 G_CALLBACK(gtk_dialog_run),
1101 _adg_about_window(builder));
1102 g_signal_connect_swapped(button_edit, "clicked",
1103 G_CALLBACK(gtk_dialog_run),
1104 _adg_edit_window(builder, part));
1105 g_signal_connect_swapped(button_save_as, "clicked",
1106 G_CALLBACK(gtk_dialog_run),
1107 _adg_save_as_window(builder, canvas));
1108 g_signal_connect(button_print, "clicked",
1109 G_CALLBACK(_adg_do_print), canvas);
1110 g_signal_connect(button_quit, "clicked", G_CALLBACK(gtk_main_quit), NULL);
1111 g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
1112 g_signal_connect_swapped(window, "destroy",
1113 G_CALLBACK(_adg_part_destroy), part);
1115 return window;
1120 main(gint argc, gchar **argv)
1122 gboolean show_extents;
1123 gchar *path;
1124 GtkBuilder *builder;
1125 GError *error;
1126 GtkWidget *main_window;
1128 _adg_parse_args(&argc, &argv, &show_extents);
1129 adg_switch_extents(show_extents);
1131 path = adg_find_file("adg-demo.ui", adg_datadir(), BUILDDIR, NULL);
1132 if (path == NULL) {
1133 g_print(_("adg-demo.ui not found!\n"));
1134 return 1;
1137 builder = gtk_builder_new();
1138 error = NULL;
1140 gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE);
1141 gtk_builder_add_from_file(builder, path, &error);
1142 g_free(path);
1144 if (error != NULL) {
1145 g_critical("%s", error->message);
1146 g_error_free(error);
1147 return 2;
1150 main_window = _adg_main_window(builder);
1151 g_object_unref(builder);
1153 gtk_widget_show_all(main_window);
1154 gtk_main();
1156 return 0;