[demo] Added UI stuff for groove machining
[adg.git] / demo / adg-demo.c
blob50b10630565bee47f1f2f313604028a3b68ee3fb
1 #include "demo.h"
3 #include <adg-gtk.h>
4 #include <math.h>
6 #define SQRT3 1.732050808
7 #define CHAMFER 0.3
10 typedef struct _AdgPart AdgPart;
12 struct _AdgPart {
13 /* Raw data */
14 gdouble A, B, C;
15 gdouble DHOLE, LHOLE;
16 gdouble D1, D2, D3, D4, D5, D6, D7;
17 gdouble RD34, RD56;
18 gdouble LD2, LD3, LD5, LD6, LD7;
20 gboolean GROOVE;
21 gdouble ZGROOVE, DGROOVE, LGROOVE;
23 /* User interface widgets */
24 AdgGtkArea *area;
25 GHashTable *widgets;
26 GtkButton *apply, *reset;
28 /* Models */
29 AdgPath *shape, *hatch;
30 AdgEdges *edges;
34 static void
35 _adg_version(void)
37 g_print("adg-demo " PACKAGE_VERSION "\n");
38 exit(0);
41 static void
42 _adg_parse_args(gint *p_argc, gchar **p_argv[], gboolean *show_extents)
44 GError *error = NULL;
45 GOptionEntry entries[] = {
46 {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
47 _adg_version, "Display version information", NULL},
48 {"show-extents", 'E', 0, G_OPTION_ARG_NONE,
49 NULL, "Show the boundary boxes of every entity", NULL},
50 {NULL}
53 entries[1].arg_data = show_extents;
54 *show_extents = FALSE;
55 gtk_init_with_args(p_argc, p_argv, "- ADG demonstration program",
56 entries, GETTEXT_PACKAGE, &error);
58 if (error != NULL) {
59 gint error_code = error->code;
61 g_printerr("%s\n", error->message);
63 g_error_free(error);
64 exit(error_code);
68 static void
69 _adg_define_hole(AdgPath *path, const AdgPart *part, gdouble height)
71 AdgModel *model;
72 AdgPair pair;
74 model = ADG_MODEL(path);
76 pair.x = part->LHOLE;
77 pair.y = 0;
78 adg_path_move_to(path, &pair);
79 adg_model_set_named_pair(model, "LHOLE", &pair);
81 pair.y = part->DHOLE / 2;
82 pair.x -= pair.y / SQRT3;
83 adg_path_line_to(path, &pair);
85 pair.x = 0;
86 adg_path_line_to(path, &pair);
87 adg_model_set_named_pair(model, "DHOLE", &pair);
89 pair.y = part->D1 / 2;
90 adg_path_line_to(path, &pair);
91 adg_model_set_named_pair(model, "D1I", &pair);
93 pair.x = height;
94 adg_path_line_to(path, &pair);
95 adg_model_set_named_pair(model, "D1F", &pair);
98 static void
99 _adg_define_hatch(AdgPath *path, const AdgPart *part)
101 _adg_define_hole(path, part, part->LHOLE + 2);
102 adg_path_reflect(path, NULL);
103 adg_path_close(path);
106 static void
107 _adg_define_shape(AdgPath *path, const AdgPart *part)
109 AdgModel *model;
110 AdgPair pair, tmp;
111 const AdgPrimitive *primitive;
113 pair.x = part->A - part->B - part->LD2;
114 _adg_define_hole(path, part, pair.x);
115 model = ADG_MODEL(path);
117 pair.x += (part->D1 - part->D2) / 2;
118 pair.y = part->D2 / 2;
119 adg_path_line_to(path, &pair);
120 adg_model_set_named_pair(model, "D2I", &pair);
122 pair.x = part->A - part->B;
123 adg_path_line_to(path, &pair);
124 adg_path_fillet(path, 0.4);
126 pair.x = part->A - part->B;
127 pair.y = part->D3 / 2;
128 adg_path_line_to(path, &pair);
129 adg_model_set_named_pair(model, "D3I", &pair);
131 pair.x = part->A;
132 adg_model_set_named_pair(model, "East", &pair);
134 pair.x = 0;
135 adg_model_set_named_pair(model, "West", &pair);
137 adg_path_chamfer(path, CHAMFER, CHAMFER);
139 pair.x = part->A - part->B + part->LD3;
140 pair.y = part->D3 / 2;
141 adg_path_line_to(path, &pair);
143 primitive = adg_path_over_primitive(path);
144 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
145 adg_model_set_named_pair(model, "D3I_X", &tmp);
147 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
148 adg_model_set_named_pair(model, "D3I_Y", &tmp);
150 adg_path_chamfer(path, CHAMFER, CHAMFER);
152 pair.y = part->D4 / 2;
153 adg_path_line_to(path, &pair);
155 primitive = adg_path_over_primitive(path);
156 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
157 adg_model_set_named_pair(model, "D3F_Y", &tmp);
158 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
159 adg_model_set_named_pair(model, "D3F_X", &tmp);
161 adg_path_fillet(path, part->RD34);
163 pair.x += part->RD34;
164 adg_model_set_named_pair(model, "D4I", &pair);
166 pair.x = part->A - part->C - part->LD5;
167 adg_path_line_to(path, &pair);
168 adg_model_set_named_pair(model, "D4F", &pair);
170 pair.y = part->D3 / 2;
171 adg_model_set_named_pair(model, "D4_POS", &pair);
173 primitive = adg_path_over_primitive(path);
174 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
175 tmp.x += part->RD34;
176 adg_model_set_named_pair(model, "RD34", &tmp);
178 tmp.x -= cos(G_PI_4) * part->RD34,
179 tmp.y -= sin(G_PI_4) * part->RD34,
180 adg_model_set_named_pair(model, "RD34_R", &tmp);
182 tmp.x += part->RD34,
183 tmp.y += part->RD34,
184 adg_model_set_named_pair(model, "RD34_XY", &tmp);
186 pair.x += (part->D4 - part->D5) / 2;
187 pair.y = part->D5 / 2;
188 adg_path_line_to(path, &pair);
189 adg_model_set_named_pair(model, "D5I", &pair);
191 pair.x = part->A - part->C;
192 adg_path_line_to(path, &pair);
194 adg_path_fillet(path, 0.2);
196 pair.y = part->D6 / 2;
197 adg_path_line_to(path, &pair);
199 primitive = adg_path_over_primitive(path);
200 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
201 adg_model_set_named_pair(model, "D5F", &tmp);
203 adg_path_fillet(path, 0.1);
205 pair.x += part->LD6;
206 adg_path_line_to(path, &pair);
207 adg_model_set_named_pair(model, "D6F", &pair);
209 primitive = adg_path_over_primitive(path);
210 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
211 adg_model_set_named_pair(model, "D6I_X", &tmp);
213 primitive = adg_path_over_primitive(path);
214 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
215 adg_model_set_named_pair(model, "D6I_Y", &tmp);
217 pair.x = part->A - part->LD7;
218 pair.y -= (part->C - part->LD7 - part->LD6) / SQRT3;
219 adg_path_line_to(path, &pair);
220 adg_model_set_named_pair(model, "D67", &pair);
222 pair.y = part->D7 / 2;
223 adg_path_line_to(path, &pair);
225 pair.x = part->A;
226 adg_path_line_to(path, &pair);
227 adg_model_set_named_pair(model, "D7F", &pair);
229 adg_path_reflect(path, NULL);
230 adg_path_close(path);
231 adg_path_move_to_explicit(path, part->LHOLE + 2, part->D1 / 2);
232 adg_path_line_to_explicit(path, part->LHOLE + 2, -part->D1 / 2);
235 static void
236 _adg_part_lock(AdgPart *part)
238 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), FALSE);
239 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), FALSE);
242 static void
243 _adg_part_unlock(AdgPart *part)
245 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), TRUE);
246 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), TRUE);
249 static void
250 _adg_part_link(AdgPart *part, gpointer data, GObject *widget)
252 const gchar *edit_signal;
254 g_assert(GTK_IS_WIDGET(widget));
255 g_object_ref(widget);
256 g_hash_table_insert(part->widgets, data, widget);
258 if (GTK_IS_SPIN_BUTTON(widget)) {
259 GtkSpinButton *spin_button = GTK_SPIN_BUTTON(widget);
260 gtk_adjustment_value_changed(gtk_spin_button_get_adjustment(spin_button));
263 edit_signal = GTK_IS_TOGGLE_BUTTON(widget) ? "toggled" : "changed";
264 g_signal_connect_swapped(widget, edit_signal,
265 G_CALLBACK(_adg_part_unlock), part);
268 static void
269 _adg_part_ui_to_boolean(AdgPart *part, gboolean *data)
271 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
273 g_assert(GTK_IS_TOGGLE_BUTTON(widget));
275 *data = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
278 static void
279 _adg_part_ui_to_double(AdgPart *part, gdouble *data)
281 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
283 g_assert(GTK_IS_SPIN_BUTTON(widget));
285 *data = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
288 static void
289 _adg_part_boolean_to_ui(AdgPart *part, gboolean *data)
291 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
293 g_assert(GTK_IS_TOGGLE_BUTTON(widget));
295 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *data);
298 static void
299 _adg_part_double_to_ui(AdgPart *part, gdouble *data)
301 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
303 g_assert(GTK_IS_WIDGET(widget));
305 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), *data);
308 static void
309 _adg_demo_canvas_add_sheet(AdgCanvas *canvas)
311 AdgTitleBlock *title_block = adg_title_block_new();
313 g_object_set(title_block,
314 "title", "SAMPLE DRAWING",
315 "author", "NtD",
316 "date", NULL,
317 "drawing", "TEST123",
318 "logo", adg_logo_new(),
319 "projection", adg_projection_new(ADG_PROJECTION_FIRST_ANGLE),
320 "scale", "NONE",
321 "size", "A4",
322 NULL);
324 adg_canvas_set_title_block(canvas, title_block);
327 static void
328 _adg_demo_canvas_add_dimensions(AdgCanvas *canvas, AdgModel *model)
330 AdgLDim *ldim;
331 AdgADim *adim;
332 AdgRDim *rdim;
334 /* NORTH */
335 adim = adg_adim_new_full_from_model(model, "-D1I", "-D1F",
336 "-D1F", "-D2I", "-D1F");
337 adg_dim_set_level(ADG_DIM(adim), 2);
338 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
340 ldim = adg_ldim_new_full_from_model(model, "-D1F", "-D3I_X", "-D3F_Y",
341 ADG_DIR_UP);
342 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
343 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
345 ldim = adg_ldim_new_full_from_model(model, "-D3I_X", "-D3F_X", "-D3F_Y",
346 ADG_DIR_UP);
347 adg_ldim_switch_extension1(ldim, FALSE);
348 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
349 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
351 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D67", "-East",
352 ADG_DIR_UP);
353 adg_dim_set_level(ADG_DIM(ldim), 0);
354 adg_ldim_switch_extension1(ldim, FALSE);
355 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
357 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D7F", "-East",
358 ADG_DIR_UP);
359 adg_dim_set_limits(ADG_DIM(ldim), "-0.06", NULL);
360 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
362 adim = adg_adim_new_full_from_model(model, "-D6I_Y", "-D6F",
363 "-D6F", "-D67", "-D6F");
364 adg_dim_set_level(ADG_DIM(adim), 2);
365 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
367 rdim = adg_rdim_new_full_from_model(model, "-RD34", "-RD34_R", "-RD34_XY");
368 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(rdim));
371 /* SOUTH */
372 ldim = adg_ldim_new_full_from_model(model, "D1I", "LHOLE", "D3F_Y",
373 ADG_DIR_DOWN);
374 adg_ldim_switch_extension1(ldim, FALSE);
375 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
377 ldim = adg_ldim_new_full_from_model(model, "D4F", "D6I_X", "D4_POS",
378 ADG_DIR_DOWN);
379 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.2");
380 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
381 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
383 ldim = adg_ldim_new_full_from_model(model, "D3I_X", "D7F", "D3F_Y",
384 ADG_DIR_DOWN);
385 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.1");
386 adg_dim_set_level(ADG_DIM(ldim), 2);
387 adg_ldim_switch_extension2(ldim, FALSE);
388 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
390 ldim = adg_ldim_new_full_from_model(model, "D1I", "D7F", "D3F_Y",
391 ADG_DIR_DOWN);
392 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
393 adg_dim_set_level(ADG_DIM(ldim), 3);
394 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
396 adim = adg_adim_new_full_from_model(model, "D4F", "D4I",
397 "D5I", "D4F", "D4F");
398 adg_dim_set_level(ADG_DIM(adim), 1.5);
399 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
401 /* EAST */
402 ldim = adg_ldim_new_full_from_model(model, "D6F", "-D6F", "East",
403 ADG_DIR_RIGHT);
404 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
405 adg_dim_set_level(ADG_DIM(ldim), 4);
406 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
407 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
409 ldim = adg_ldim_new_full_from_model(model, "D4F", "-D4F", "East",
410 ADG_DIR_RIGHT);
411 adg_dim_set_level(ADG_DIM(ldim), 3);
412 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
413 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
415 ldim = adg_ldim_new_full_from_model(model, "D5F", "-D5F", "East",
416 ADG_DIR_RIGHT);
417 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
418 adg_dim_set_level(ADG_DIM(ldim), 2);
419 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
420 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
422 ldim = adg_ldim_new_full_from_model(model, "D7F", "-D7F", "East",
423 ADG_DIR_RIGHT);
424 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
425 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
428 /* WEST */
429 ldim = adg_ldim_new_full_from_model(model, "D3I_Y", "-D3I_Y", "-West",
430 ADG_DIR_LEFT);
431 adg_dim_set_limits(ADG_DIM(ldim), "-0.25", NULL);
432 adg_dim_set_level(ADG_DIM(ldim), 4);
433 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
434 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
436 ldim = adg_ldim_new_full_from_model(model, "D1I", "-D1I", "-West",
437 ADG_DIR_LEFT);
438 adg_dim_set_limits(ADG_DIM(ldim), "+0.05", "-0.05");
439 adg_dim_set_level(ADG_DIM(ldim), 3);
440 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
441 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
443 ldim = adg_ldim_new_full_from_model(model, "D2I", "-D2I", "-West",
444 ADG_DIR_LEFT);
445 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
446 adg_dim_set_level(ADG_DIM(ldim), 2);
447 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
448 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
450 ldim = adg_ldim_new_full_from_model(model, "DHOLE", "-DHOLE", "-West",
451 ADG_DIR_LEFT);
452 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
453 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
456 static void
457 _adg_demo_canvas_add_stuff(AdgCanvas *canvas, AdgModel *model)
459 AdgToyText *toy_text;
460 AdgMatrix map;
462 toy_text = adg_toy_text_new("Rotate the mouse wheel to zoom in and out");
463 adg_entity_set_local_method(ADG_ENTITY(toy_text), ADG_MIX_DISABLED);
464 cairo_matrix_init_translate(&map, 15, 500);
465 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
466 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
468 toy_text = adg_toy_text_new("Drag with the wheel pressed to pan");
469 adg_entity_set_local_method(ADG_ENTITY(toy_text), ADG_MIX_DISABLED);
470 cairo_matrix_init_translate(&map, 15, 515);
471 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
472 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
475 static AdgCanvas *
476 _adg_canvas_init(AdgCanvas *canvas, AdgPart *part)
478 AdgContainer *container;
479 AdgEntity *entity;
480 AdgMatrix map;
482 container = (AdgContainer *) canvas;
484 adg_canvas_set_paper(canvas, GTK_PAPER_NAME_A4,
485 GTK_PAGE_ORIENTATION_LANDSCAPE);
487 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->shape)));
488 adg_container_add(container, entity);
490 entity = ADG_ENTITY(adg_hatch_new(ADG_TRAIL(part->hatch)));
491 adg_container_add(container, entity);
493 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->edges)));
494 adg_container_add(container, entity);
496 _adg_demo_canvas_add_sheet(canvas);
497 _adg_demo_canvas_add_dimensions(canvas, ADG_MODEL(part->shape));
498 _adg_demo_canvas_add_stuff(canvas, ADG_MODEL(part->shape));
500 cairo_matrix_init_translate(&map, 160, 160);
501 cairo_matrix_scale(&map, 8, 8);
502 adg_entity_set_local_map(ADG_ENTITY(container), &map);
504 return canvas;
507 static GtkRadioButton *
508 _adg_group_get_active(GtkRadioButton *radio_group)
510 GSList *list = gtk_radio_button_get_group(radio_group);
512 while (list) {
513 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(list->data)))
514 return list->data;
516 list = list->next;
519 return NULL;
522 static void
523 _adg_do_edit(AdgPart *part)
525 _adg_part_ui_to_double(part, &part->A);
526 _adg_part_ui_to_double(part, &part->B);
527 _adg_part_ui_to_double(part, &part->C);
528 _adg_part_ui_to_double(part, &part->DHOLE);
529 _adg_part_ui_to_double(part, &part->LHOLE);
530 _adg_part_ui_to_double(part, &part->D1);
531 _adg_part_ui_to_double(part, &part->D2);
532 _adg_part_ui_to_double(part, &part->LD2);
533 _adg_part_ui_to_double(part, &part->D3);
534 _adg_part_ui_to_double(part, &part->LD3);
535 _adg_part_ui_to_double(part, &part->D4);
536 //_adg_part_ui_to_double(part, &part->D5);
537 _adg_part_ui_to_double(part, &part->D6);
538 //_adg_part_ui_to_double(part, &part->LD6);
539 _adg_part_ui_to_double(part, &part->D7);
540 //_adg_part_ui_to_double(part, &part->LD7);
542 _adg_part_ui_to_boolean(part, &part->GROOVE);
543 _adg_part_ui_to_double(part, &part->ZGROOVE);
544 _adg_part_ui_to_double(part, &part->DGROOVE);
545 _adg_part_ui_to_double(part, &part->LGROOVE);
547 _adg_part_lock(part);
549 adg_model_clear(ADG_MODEL(part->shape));
550 _adg_define_shape(part->shape, part);
551 adg_model_changed(ADG_MODEL(part->shape));
553 adg_model_clear(ADG_MODEL(part->hatch));
554 _adg_define_hatch(part->hatch, part);
555 adg_model_changed(ADG_MODEL(part->hatch));
557 adg_model_clear(ADG_MODEL(part->edges));
558 adg_model_changed(ADG_MODEL(part->edges));
560 gtk_widget_queue_draw(GTK_WIDGET(part->area));
563 static void
564 _adg_do_reset(AdgPart *part)
566 _adg_part_double_to_ui(part, &part->A);
567 _adg_part_double_to_ui(part, &part->B);
568 _adg_part_double_to_ui(part, &part->C);
569 _adg_part_double_to_ui(part, &part->DHOLE);
570 _adg_part_double_to_ui(part, &part->LHOLE);
571 _adg_part_double_to_ui(part, &part->D1);
572 _adg_part_double_to_ui(part, &part->D2);
573 _adg_part_double_to_ui(part, &part->LD2);
574 _adg_part_double_to_ui(part, &part->D3);
575 _adg_part_double_to_ui(part, &part->LD3);
576 _adg_part_double_to_ui(part, &part->D4);
577 //_adg_part_double_to_ui(part, &part->D5);
578 _adg_part_double_to_ui(part, &part->D6);
579 //_adg_part_double_to_ui(part, &part->LD6);
580 _adg_part_double_to_ui(part, &part->D7);
581 //_adg_part_double_to_ui(part, &part->LD7);
583 _adg_part_boolean_to_ui(part, &part->GROOVE);
584 _adg_part_double_to_ui(part, &part->ZGROOVE);
585 _adg_part_double_to_ui(part, &part->DGROOVE);
586 _adg_part_double_to_ui(part, &part->LGROOVE);
588 _adg_part_lock(part);
591 static void
592 _adg_do_save_as(GtkWindow *window, GtkResponseType response, AdgCanvas *canvas)
594 GtkRadioButton *type_radio;
595 gchar *file, *suffix;
596 cairo_surface_t *surface;
598 if (response != GTK_RESPONSE_OK) {
599 gtk_widget_hide(GTK_WIDGET(window));
600 return;
603 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(window));
604 if (file == NULL)
605 return;
607 type_radio = _adg_group_get_active(g_object_get_data(G_OBJECT(window),
608 "type-group"));
609 g_assert(GTK_IS_RADIO_BUTTON(type_radio));
610 suffix = gtk_widget_get_tooltip_markup(GTK_WIDGET(type_radio));
611 g_assert(suffix != NULL);
613 if (!g_str_has_suffix(file, suffix)) {
614 gchar *tmp = file;
615 file = g_strconcat(file, suffix, NULL);
616 g_free(tmp);
619 #ifdef CAIRO_HAS_PNG_FUNCTIONS
620 if (strcmp(suffix, ".png") == 0) {
621 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 800, 600);
622 } else
623 #endif
624 #ifdef CAIRO_HAS_SVG_SURFACE
625 if (strcmp(suffix, ".svg") == 0) {
626 #include <cairo-svg.h>
627 surface = cairo_svg_surface_create(file, 841, 595);
628 } else
629 #endif
630 #ifdef CAIRO_HAS_PDF_SURFACE
631 if (strcmp(suffix, ".pdf") == 0) {
632 #include <cairo-pdf.h>
633 surface = cairo_pdf_surface_create(file, 841, 595);
634 } else
635 #endif
636 #ifdef CAIRO_HAS_PS_SURFACE
637 if (strcmp(suffix, ".ps") == 0) {
638 #include <cairo-ps.h>
639 surface = cairo_ps_surface_create(file, 841, 595);
640 cairo_ps_surface_dsc_comment(surface, "%%Title: " PACKAGE_STRING);
641 cairo_ps_surface_dsc_comment(surface, "%%Copyright: Copyleft (C) 2006-2010 Fontana Nicola");
642 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Landscape");
643 cairo_ps_surface_dsc_begin_setup(surface);
644 cairo_ps_surface_dsc_begin_page_setup(surface);
645 cairo_ps_surface_dsc_comment(surface, "%%IncludeFeature: *PageSize A4");
646 } else
647 #endif
649 demo_notify_error(_("Requested format not supported"), window);
650 surface = NULL;
653 if (surface) {
654 cairo_t *cr;
655 cairo_status_t status;
657 cr = cairo_create(surface);
658 cairo_surface_destroy(surface);
659 adg_entity_render(ADG_ENTITY(canvas), cr);
661 if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) {
662 status = cairo_surface_write_to_png(surface, file);
663 } else {
664 cairo_show_page(cr);
665 status = cairo_status(cr);
668 cairo_destroy(cr);
670 if (status != CAIRO_STATUS_SUCCESS)
671 demo_notify_error(cairo_status_to_string(status), window);
674 g_free(file);
675 g_free(suffix);
676 gtk_widget_hide(GTK_WIDGET(window));
679 static void
680 _adg_print_prepare(GtkPrintOperation *operation, GtkPrintContext *context)
682 gtk_print_operation_set_n_pages(operation, 1);
685 static void
686 _adg_print_page(GtkPrintOperation *operation, GtkPrintContext *context,
687 gint page_nr, AdgEntity *canvas)
689 cairo_t *cr = gtk_print_context_get_cairo_context(context);
690 AdgMatrix old_map;
692 adg_matrix_copy(&old_map, adg_entity_get_global_map(canvas));;
694 adg_entity_set_global_map(canvas, adg_matrix_identity());
695 adg_entity_render(canvas, cr);
697 adg_entity_set_global_map(canvas, &old_map);
700 static void
701 _adg_do_print(GtkWidget *button, AdgCanvas *canvas)
703 static GtkPrintSettings *settings = NULL;
704 GtkWindow *window;
705 GtkPrintOperation *operation;
706 GtkPageSetup *page_setup;
707 GError *error;
709 window = (GtkWindow *) gtk_widget_get_toplevel(button);
710 operation = gtk_print_operation_new();
711 page_setup = g_object_get_data(G_OBJECT(canvas), "_adg_page_setup");
712 error = NULL;
714 if (settings)
715 gtk_print_operation_set_print_settings(operation, settings);
716 if (page_setup)
717 gtk_print_operation_set_default_page_setup(operation, page_setup);
719 g_signal_connect(operation, "begin-print",
720 G_CALLBACK(_adg_print_prepare), NULL);
721 g_signal_connect(operation, "draw-page",
722 G_CALLBACK(_adg_print_page), canvas);
724 gtk_print_operation_set_use_full_page(operation, FALSE);
725 gtk_print_operation_set_unit(operation, GTK_UNIT_POINTS);
726 #if GTK_CHECK_VERSION(2, 18, 0)
727 gtk_print_operation_set_embed_page_setup(operation, TRUE);
728 #endif
730 switch (gtk_print_operation_run(operation,
731 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
732 window, &error)) {
734 case GTK_PRINT_OPERATION_RESULT_APPLY:
735 if (settings)
736 g_object_unref(settings);
737 settings = gtk_print_operation_get_print_settings(operation);
738 if (settings)
739 g_object_ref(settings);
740 break;
742 default:
743 break;
746 g_object_unref(operation);
748 if (error)
749 demo_notify_error(error->message, window);
752 static AdgPart *
753 _adg_part_new(GtkBuilder *builder)
755 AdgPart *part;
756 GObject *object, *toggle_object;
758 part = g_new0(AdgPart, 1);
759 part->widgets = g_hash_table_new_full(g_direct_hash, g_direct_equal,
760 NULL, g_object_unref);
761 part->area = (AdgGtkArea *) gtk_builder_get_object(builder, "mainCanvas");
762 part->apply = (GtkButton *) gtk_builder_get_object(builder, "editApply");
763 part->reset = (GtkButton *) gtk_builder_get_object(builder, "editReset");
764 part->shape = adg_path_new();
765 part->hatch = adg_path_new();
766 part->edges = adg_edges_new_with_source(ADG_TRAIL(part->shape));
768 g_assert(ADG_GTK_IS_AREA(part->area));
769 g_assert(GTK_IS_BUTTON(part->apply));
770 g_assert(GTK_IS_BUTTON(part->reset));
772 _adg_part_link(part, &part->A, gtk_builder_get_object(builder, "editA"));
773 _adg_part_link(part, &part->B, gtk_builder_get_object(builder, "editB"));
774 _adg_part_link(part, &part->C, gtk_builder_get_object(builder, "editC"));
775 _adg_part_link(part, &part->D1, gtk_builder_get_object(builder, "editD1"));
776 _adg_part_link(part, &part->D2, gtk_builder_get_object(builder, "editD2"));
777 _adg_part_link(part, &part->LD2, gtk_builder_get_object(builder, "editLD2"));
778 _adg_part_link(part, &part->D3, gtk_builder_get_object(builder, "editD3"));
779 _adg_part_link(part, &part->LD3, gtk_builder_get_object(builder, "editLD3"));
780 _adg_part_link(part, &part->D4, gtk_builder_get_object(builder, "editD4"));
781 //_adg_part_link(part, &part->D5, gtk_builder_get_object(builder, "editD5"));
782 _adg_part_link(part, &part->D6, gtk_builder_get_object(builder, "editD6"));
783 //_adg_part_link(part, &part->LD6, gtk_builder_get_object(builder, "editLD6"));
784 _adg_part_link(part, &part->D7, gtk_builder_get_object(builder, "editD7"));
785 //_adg_part_link(part, &part->LD7, gtk_builder_get_object(builder, "editLD7"));
786 _adg_part_link(part, &part->DHOLE, gtk_builder_get_object(builder, "editDHOLE"));
787 _adg_part_link(part, &part->LHOLE, gtk_builder_get_object(builder, "editLHOLE"));
789 toggle_object = gtk_builder_get_object(builder, "GROOVE");
790 _adg_part_link(part, &part->GROOVE, toggle_object);
792 object = gtk_builder_get_object(builder, "editZGROOVE");
793 _adg_part_link(part, &part->ZGROOVE, object);
794 g_signal_connect(toggle_object, "toggled",
795 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
796 object = gtk_builder_get_object(builder, "editZGROOVELabel");
797 g_signal_connect(toggle_object, "toggled",
798 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
800 object = gtk_builder_get_object(builder, "editDGROOVE");
801 _adg_part_link(part, &part->DGROOVE, object);
802 g_signal_connect(toggle_object, "toggled",
803 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
804 object = gtk_builder_get_object(builder, "editDGROOVELabel");
805 g_signal_connect(toggle_object, "toggled",
806 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
808 object = gtk_builder_get_object(builder, "editLGROOVE");
809 _adg_part_link(part, &part->LGROOVE, object);
810 g_signal_connect(toggle_object, "toggled",
811 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
812 object = gtk_builder_get_object(builder, "editLGROOVELabel");
813 g_signal_connect(toggle_object, "toggled",
814 G_CALLBACK(adg_gtk_toggle_button_sensitivize), object);
816 part->D5 = 4.5;
817 part->RD34 = 1;
818 part->LD5 = 5;
819 part->LD6 = 1;
820 part->LD7 = 0.5;
822 _adg_do_edit(part);
824 return part;
827 static void
828 _adg_part_destroy(AdgPart *part)
830 g_hash_table_destroy(part->widgets);
831 g_free(part);
834 static GtkWidget *
835 _adg_about_window(GtkBuilder *builder)
837 GtkWidget *window;
839 window = (GtkWidget *) gtk_builder_get_object(builder, "wndAbout");
840 g_assert(GTK_IS_ABOUT_DIALOG(window));
842 g_signal_connect(window, "response", G_CALLBACK(gtk_widget_hide), NULL);
844 return window;
847 static GtkWidget *
848 _adg_edit_window(GtkBuilder *builder, AdgPart *part)
850 GtkWidget *window;
852 window = (GtkWidget *) gtk_builder_get_object(builder, "wndEdit");
853 g_assert(GTK_IS_DIALOG(window));
855 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
857 g_signal_connect_swapped(part->apply, "clicked",
858 G_CALLBACK(_adg_do_edit), part);
859 g_signal_connect_swapped(part->reset, "clicked",
860 G_CALLBACK(_adg_do_reset), part);
861 g_signal_connect(window, "response",
862 G_CALLBACK(adg_gtk_window_hide_here), NULL);
864 return window;
867 static GtkWidget *
868 _adg_save_as_window(GtkBuilder *builder, AdgCanvas *canvas)
870 GtkWidget *window;
871 GtkWidget *type_group;
873 window = (GtkWidget *) gtk_builder_get_object(builder, "wndSaveAs");
874 g_assert(GTK_IS_WINDOW(window));
875 type_group = (GtkWidget *) gtk_builder_get_object(builder, "saveAsPng");
876 g_assert(GTK_IS_RADIO_BUTTON(type_group));
878 g_object_set_data(G_OBJECT(window), "type-group", type_group);
880 /* Set the default destination file */
881 if (GTK_IS_FILE_CHOOSER(window)) {
882 GtkFileChooser *file_chooser;
883 const gchar *dir;
885 file_chooser = (GtkFileChooser *) window;
887 #if GLIB_CHECK_VERSION(2, 14, 0)
888 dir = g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS);
889 #else
890 dir = NULL;
891 #endif
893 if (dir == NULL)
894 dir = g_get_home_dir();
896 gtk_file_chooser_set_current_folder(file_chooser, dir);
897 gtk_file_chooser_set_current_name(file_chooser, "adg-demo");
900 g_signal_connect(window, "response", G_CALLBACK(_adg_do_save_as), canvas);
902 return window;
905 static GtkWidget *
906 _adg_main_window(GtkBuilder *builder)
908 GtkWidget *window;
909 AdgPart *part;
910 AdgCanvas *canvas;
911 GtkWidget *button_edit, *button_save_as, *button_print;
912 GtkWidget *button_about, *button_quit;
914 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
915 part = _adg_part_new(builder);
916 canvas = adg_canvas_new();
918 _adg_canvas_init(canvas, part);
919 adg_gtk_area_set_canvas(part->area, canvas);
921 g_assert(GTK_IS_WINDOW(window));
922 button_edit = (GtkWidget *) gtk_builder_get_object(builder, "mainEdit");
923 g_assert(GTK_IS_BUTTON(button_edit));
924 button_save_as = (GtkWidget *) gtk_builder_get_object(builder, "mainSaveAs");
925 g_assert(GTK_IS_BUTTON(button_save_as));
926 button_print = (GtkWidget *) gtk_builder_get_object(builder, "mainPrint");
927 g_assert(GTK_IS_BUTTON(button_print));
928 button_about = (GtkWidget *) gtk_builder_get_object(builder, "mainAbout");
929 g_assert(GTK_IS_BUTTON(button_about));
930 button_quit = (GtkWidget *) gtk_builder_get_object(builder, "mainQuit");
931 g_assert(GTK_IS_BUTTON(button_quit));
933 g_signal_connect_swapped(button_about, "clicked",
934 G_CALLBACK(gtk_dialog_run),
935 _adg_about_window(builder));
936 g_signal_connect_swapped(button_edit, "clicked",
937 G_CALLBACK(gtk_dialog_run),
938 _adg_edit_window(builder, part));
939 g_signal_connect_swapped(button_save_as, "clicked",
940 G_CALLBACK(gtk_dialog_run),
941 _adg_save_as_window(builder, canvas));
942 g_signal_connect(button_print, "clicked",
943 G_CALLBACK(_adg_do_print), canvas);
944 g_signal_connect(button_quit, "clicked", G_CALLBACK(gtk_main_quit), NULL);
945 g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
946 g_signal_connect_swapped(window, "destroy",
947 G_CALLBACK(_adg_part_destroy), part);
949 return window;
954 main(gint argc, gchar **argv)
956 gboolean show_extents;
957 gchar *path;
958 GtkBuilder *builder;
959 GError *error;
960 GtkWidget *main_window;
962 _adg_parse_args(&argc, &argv, &show_extents);
963 adg_switch_extents(show_extents);
965 path = demo_find_data_file("adg-demo.ui", argv[0]);
966 if (path == NULL) {
967 g_print("adg-demo.ui not found!\n");
968 return 1;
971 builder = gtk_builder_new();
972 error = NULL;
973 gtk_builder_add_from_file(builder, path, &error);
975 if (error != NULL) {
976 g_critical("%s", error->message);
977 g_error_free(error);
978 return 2;
981 main_window = _adg_main_window(builder);
982 g_object_unref(builder);
984 gtk_widget_show_all(main_window);
985 gtk_main();
987 return 0;