[demo] Backup/restore global map while printing
[adg.git] / demo / adg-demo.c
blob900959ffcbc43c8c0e4aa2517b7f756b772bdd04
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 /* User interface widgets */
21 AdgGtkArea *area;
22 GHashTable *widgets;
23 GtkButton *apply, *reset;
25 /* Models */
26 AdgPath *shape, *hatch;
27 AdgEdges *edges;
31 static void
32 _adg_version(void)
34 g_print("adg-demo " PACKAGE_VERSION "\n");
35 exit(0);
38 static void
39 _adg_parse_args(gint *p_argc, gchar **p_argv[], gboolean *show_extents)
41 GError *error = NULL;
42 GOptionEntry entries[] = {
43 {"version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
44 _adg_version, "Display version information", NULL},
45 {"show-extents", 'E', 0, G_OPTION_ARG_NONE,
46 NULL, "Show the boundary boxes of every entity", NULL},
47 {NULL}
50 entries[1].arg_data = show_extents;
51 *show_extents = FALSE;
52 gtk_init_with_args(p_argc, p_argv, "- ADG demonstration program",
53 entries, GETTEXT_PACKAGE, &error);
55 if (error != NULL) {
56 gint error_code = error->code;
58 g_printerr("%s\n", error->message);
60 g_error_free(error);
61 exit(error_code);
65 static void
66 _adg_define_hole(AdgPath *path, const AdgPart *part, gdouble height)
68 AdgModel *model;
69 AdgPair pair;
71 model = ADG_MODEL(path);
73 pair.x = part->LHOLE;
74 pair.y = 0;
75 adg_path_move_to(path, &pair);
76 adg_model_set_named_pair(model, "LHOLE", &pair);
78 pair.y = part->DHOLE / 2;
79 pair.x -= pair.y / SQRT3;
80 adg_path_line_to(path, &pair);
82 pair.x = 0;
83 adg_path_line_to(path, &pair);
84 adg_model_set_named_pair(model, "DHOLE", &pair);
86 pair.y = part->D1 / 2;
87 adg_path_line_to(path, &pair);
88 adg_model_set_named_pair(model, "D1I", &pair);
90 pair.x = height;
91 adg_path_line_to(path, &pair);
92 adg_model_set_named_pair(model, "D1F", &pair);
95 static void
96 _adg_define_hatch(AdgPath *path, const AdgPart *part)
98 _adg_define_hole(path, part, part->LHOLE + 2);
99 adg_path_reflect(path, NULL);
100 adg_path_close(path);
103 static void
104 _adg_define_shape(AdgPath *path, const AdgPart *part)
106 AdgModel *model;
107 AdgPair pair, tmp;
108 const AdgPrimitive *primitive;
110 pair.x = part->A - part->B - part->LD2;
111 _adg_define_hole(path, part, pair.x);
112 model = ADG_MODEL(path);
114 pair.x += (part->D1 - part->D2) / 2;
115 pair.y = part->D2 / 2;
116 adg_path_line_to(path, &pair);
117 adg_model_set_named_pair(model, "D2I", &pair);
119 pair.x = part->A - part->B;
120 adg_path_line_to(path, &pair);
121 adg_path_fillet(path, 0.4);
123 pair.x = part->A - part->B;
124 pair.y = part->D3 / 2;
125 adg_path_line_to(path, &pair);
126 adg_model_set_named_pair(model, "D3I", &pair);
128 pair.x = part->A;
129 adg_model_set_named_pair(model, "East", &pair);
131 pair.x = 0;
132 adg_model_set_named_pair(model, "West", &pair);
134 adg_path_chamfer(path, CHAMFER, CHAMFER);
136 pair.x = part->A - part->B + part->LD3;
137 pair.y = part->D3 / 2;
138 adg_path_line_to(path, &pair);
140 primitive = adg_path_over_primitive(path);
141 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
142 adg_model_set_named_pair(model, "D3I_X", &tmp);
144 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
145 adg_model_set_named_pair(model, "D3I_Y", &tmp);
147 adg_path_chamfer(path, CHAMFER, CHAMFER);
149 pair.y = part->D4 / 2;
150 adg_path_line_to(path, &pair);
152 primitive = adg_path_over_primitive(path);
153 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
154 adg_model_set_named_pair(model, "D3F_Y", &tmp);
155 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
156 adg_model_set_named_pair(model, "D3F_X", &tmp);
158 adg_path_fillet(path, part->RD34);
160 pair.x += part->RD34;
161 adg_model_set_named_pair(model, "D4I", &pair);
163 pair.x = part->A - part->C - part->LD5;
164 adg_path_line_to(path, &pair);
165 adg_model_set_named_pair(model, "D4F", &pair);
167 pair.y = part->D3 / 2;
168 adg_model_set_named_pair(model, "D4_POS", &pair);
170 primitive = adg_path_over_primitive(path);
171 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
172 tmp.x += part->RD34;
173 adg_model_set_named_pair(model, "RD34", &tmp);
175 tmp.x -= cos(G_PI_4) * part->RD34,
176 tmp.y -= sin(G_PI_4) * part->RD34,
177 adg_model_set_named_pair(model, "RD34_R", &tmp);
179 tmp.x += part->RD34,
180 tmp.y += part->RD34,
181 adg_model_set_named_pair(model, "RD34_XY", &tmp);
183 pair.x += (part->D4 - part->D5) / 2;
184 pair.y = part->D5 / 2;
185 adg_path_line_to(path, &pair);
186 adg_model_set_named_pair(model, "D5I", &pair);
188 pair.x = part->A - part->C;
189 adg_path_line_to(path, &pair);
191 adg_path_fillet(path, 0.2);
193 pair.y = part->D6 / 2;
194 adg_path_line_to(path, &pair);
196 primitive = adg_path_over_primitive(path);
197 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
198 adg_model_set_named_pair(model, "D5F", &tmp);
200 adg_path_fillet(path, 0.1);
202 pair.x += part->LD6;
203 adg_path_line_to(path, &pair);
204 adg_model_set_named_pair(model, "D6F", &pair);
206 primitive = adg_path_over_primitive(path);
207 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, 0));
208 adg_model_set_named_pair(model, "D6I_X", &tmp);
210 primitive = adg_path_over_primitive(path);
211 cpml_pair_from_cairo(&tmp, cpml_primitive_get_point(primitive, -1));
212 adg_model_set_named_pair(model, "D6I_Y", &tmp);
214 pair.x = part->A - part->LD7;
215 pair.y -= (part->C - part->LD7 - part->LD6) / SQRT3;
216 adg_path_line_to(path, &pair);
217 adg_model_set_named_pair(model, "D67", &pair);
219 pair.y = part->D7 / 2;
220 adg_path_line_to(path, &pair);
222 pair.x = part->A;
223 adg_path_line_to(path, &pair);
224 adg_model_set_named_pair(model, "D7F", &pair);
226 adg_path_reflect(path, NULL);
227 adg_path_close(path);
228 adg_path_move_to_explicit(path, part->LHOLE + 2, part->D1 / 2);
229 adg_path_line_to_explicit(path, part->LHOLE + 2, -part->D1 / 2);
232 static void
233 _adg_part_lock(AdgPart *part)
235 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), FALSE);
236 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), FALSE);
239 static void
240 _adg_part_unlock(AdgPart *part)
242 gtk_widget_set_sensitive(GTK_WIDGET(part->apply), TRUE);
243 gtk_widget_set_sensitive(GTK_WIDGET(part->reset), TRUE);
246 static void
247 _adg_part_link(AdgPart *part, gpointer data, GObject *widget)
249 g_assert(GTK_IS_WIDGET(widget));
250 g_object_ref(widget);
251 g_hash_table_insert(part->widgets, data, widget);
253 if (GTK_IS_SPIN_BUTTON(widget)) {
254 GtkSpinButton *spin_button = GTK_SPIN_BUTTON(widget);
255 gtk_adjustment_value_changed(gtk_spin_button_get_adjustment(spin_button));
258 g_signal_connect_swapped(widget, "changed",
259 G_CALLBACK(_adg_part_unlock), part);
262 static void
263 _adg_part_ui_to_double(AdgPart *part, gdouble *data)
265 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
267 g_assert(GTK_IS_WIDGET(widget));
269 *data = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
272 static void
273 _adg_part_double_to_ui(AdgPart *part, gdouble *data)
275 GtkWidget *widget = g_hash_table_lookup(part->widgets, data);
277 g_assert(GTK_IS_WIDGET(widget));
279 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), *data);
282 static void
283 _adg_demo_canvas_add_sheet(AdgCanvas *canvas)
285 AdgTitleBlock *title_block = adg_title_block_new();
287 g_object_set(title_block,
288 "title", "SAMPLE DRAWING",
289 "author", "NtD",
290 "date", NULL,
291 "drawing", "TEST123",
292 "logo", adg_logo_new(),
293 "projection", adg_projection_new(ADG_PROJECTION_FIRST_ANGLE),
294 "scale", "NONE",
295 "size", "A4",
296 NULL);
298 adg_canvas_set_title_block(canvas, title_block);
301 static void
302 _adg_demo_canvas_add_dimensions(AdgCanvas *canvas, AdgModel *model)
304 AdgLDim *ldim;
305 AdgADim *adim;
306 AdgRDim *rdim;
308 /* NORTH */
309 adim = adg_adim_new_full_from_model(model, "-D1I", "-D1F",
310 "-D1F", "-D2I", "-D1F");
311 adg_dim_set_level(ADG_DIM(adim), 2);
312 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
314 ldim = adg_ldim_new_full_from_model(model, "-D1F", "-D3I_X", "-D3F_Y",
315 ADG_DIR_UP);
316 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
317 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
319 ldim = adg_ldim_new_full_from_model(model, "-D3I_X", "-D3F_X", "-D3F_Y",
320 ADG_DIR_UP);
321 adg_ldim_switch_extension1(ldim, FALSE);
322 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
323 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
325 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D67", "-East",
326 ADG_DIR_UP);
327 adg_dim_set_level(ADG_DIM(ldim), 0);
328 adg_ldim_switch_extension1(ldim, FALSE);
329 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
331 ldim = adg_ldim_new_full_from_model(model, "-D6I_X", "-D7F", "-East",
332 ADG_DIR_UP);
333 adg_dim_set_limits(ADG_DIM(ldim), "-0.06", NULL);
334 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
336 adim = adg_adim_new_full_from_model(model, "-D6I_Y", "-D6F",
337 "-D6F", "-D67", "-D6F");
338 adg_dim_set_level(ADG_DIM(adim), 2);
339 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
341 rdim = adg_rdim_new_full_from_model(model, "-RD34", "-RD34_R", "-RD34_XY");
342 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(rdim));
345 /* SOUTH */
346 ldim = adg_ldim_new_full_from_model(model, "D1I", "LHOLE", "D3F_Y",
347 ADG_DIR_DOWN);
348 adg_ldim_switch_extension1(ldim, FALSE);
349 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
351 ldim = adg_ldim_new_full_from_model(model, "D4F", "D6I_X", "D4_POS",
352 ADG_DIR_DOWN);
353 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.2");
354 adg_dim_set_outside(ADG_DIM(ldim), ADG_THREE_STATE_OFF);
355 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
357 ldim = adg_ldim_new_full_from_model(model, "D3I_X", "D7F", "D3F_Y",
358 ADG_DIR_DOWN);
359 adg_dim_set_limits(ADG_DIM(ldim), NULL, "+0.1");
360 adg_dim_set_level(ADG_DIM(ldim), 2);
361 adg_ldim_switch_extension2(ldim, FALSE);
362 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
364 ldim = adg_ldim_new_full_from_model(model, "D1I", "D7F", "D3F_Y",
365 ADG_DIR_DOWN);
366 adg_dim_set_limits(ADG_DIM(ldim), "-0.05", "+0.05");
367 adg_dim_set_level(ADG_DIM(ldim), 3);
368 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
370 adim = adg_adim_new_full_from_model(model, "D4F", "D4I",
371 "D5I", "D4F", "D4F");
372 adg_dim_set_level(ADG_DIM(adim), 1.5);
373 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(adim));
375 /* EAST */
376 ldim = adg_ldim_new_full_from_model(model, "D6F", "-D6F", "East",
377 ADG_DIR_RIGHT);
378 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
379 adg_dim_set_level(ADG_DIM(ldim), 4);
380 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
381 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
383 ldim = adg_ldim_new_full_from_model(model, "D4F", "-D4F", "East",
384 ADG_DIR_RIGHT);
385 adg_dim_set_level(ADG_DIM(ldim), 3);
386 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
387 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
389 ldim = adg_ldim_new_full_from_model(model, "D5F", "-D5F", "East",
390 ADG_DIR_RIGHT);
391 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
392 adg_dim_set_level(ADG_DIM(ldim), 2);
393 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
394 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
396 ldim = adg_ldim_new_full_from_model(model, "D7F", "-D7F", "East",
397 ADG_DIR_RIGHT);
398 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
399 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
402 /* WEST */
403 ldim = adg_ldim_new_full_from_model(model, "D3I_Y", "-D3I_Y", "-West",
404 ADG_DIR_LEFT);
405 adg_dim_set_limits(ADG_DIM(ldim), "-0.25", NULL);
406 adg_dim_set_level(ADG_DIM(ldim), 4);
407 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
408 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
410 ldim = adg_ldim_new_full_from_model(model, "D1I", "-D1I", "-West",
411 ADG_DIR_LEFT);
412 adg_dim_set_limits(ADG_DIM(ldim), "+0.05", "-0.05");
413 adg_dim_set_level(ADG_DIM(ldim), 3);
414 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
415 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
417 ldim = adg_ldim_new_full_from_model(model, "D2I", "-D2I", "-West",
418 ADG_DIR_LEFT);
419 adg_dim_set_limits(ADG_DIM(ldim), "-0.1", NULL);
420 adg_dim_set_level(ADG_DIM(ldim), 2);
421 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
422 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
424 ldim = adg_ldim_new_full_from_model(model, "DHOLE", "-DHOLE", "-West",
425 ADG_DIR_LEFT);
426 adg_dim_set_value(ADG_DIM(ldim), ADG_UTF8_DIAMETER "<>");
427 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(ldim));
430 static void
431 _adg_demo_canvas_add_stuff(AdgCanvas *canvas, AdgModel *model)
433 AdgToyText *toy_text;
434 AdgMatrix map;
436 toy_text = adg_toy_text_new("Rotate the mouse wheel to zoom in and out");
437 adg_entity_set_local_method(ADG_ENTITY(toy_text), ADG_MIX_DISABLED);
438 cairo_matrix_init_translate(&map, 15, 500);
439 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
440 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
442 toy_text = adg_toy_text_new("Drag with the wheel pressed to pan");
443 adg_entity_set_local_method(ADG_ENTITY(toy_text), ADG_MIX_DISABLED);
444 cairo_matrix_init_translate(&map, 15, 515);
445 adg_entity_set_global_map(ADG_ENTITY(toy_text), &map);
446 adg_container_add(ADG_CONTAINER(canvas), ADG_ENTITY(toy_text));
449 static AdgCanvas *
450 _adg_canvas_init(AdgCanvas *canvas, AdgPart *part)
452 AdgContainer *container;
453 AdgEntity *entity;
454 AdgMatrix map;
456 container = (AdgContainer *) canvas;
458 adg_canvas_set_paper(canvas, GTK_PAPER_NAME_A4,
459 GTK_PAGE_ORIENTATION_LANDSCAPE);
461 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->shape)));
462 adg_container_add(container, entity);
464 entity = ADG_ENTITY(adg_hatch_new(ADG_TRAIL(part->hatch)));
465 adg_container_add(container, entity);
467 entity = ADG_ENTITY(adg_stroke_new(ADG_TRAIL(part->edges)));
468 adg_container_add(container, entity);
470 _adg_demo_canvas_add_sheet(canvas);
471 _adg_demo_canvas_add_dimensions(canvas, ADG_MODEL(part->shape));
472 _adg_demo_canvas_add_stuff(canvas, ADG_MODEL(part->shape));
474 cairo_matrix_init_translate(&map, 150, 250);
475 cairo_matrix_scale(&map, 8, 8);
476 adg_entity_set_local_map(ADG_ENTITY(container), &map);
478 return canvas;
481 static GtkRadioButton *
482 _adg_group_get_active(GtkRadioButton *radio_group)
484 GSList *list = gtk_radio_button_get_group(radio_group);
486 while (list) {
487 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(list->data)))
488 return list->data;
490 list = list->next;
493 return NULL;
496 static void
497 _adg_do_edit(AdgPart *part)
499 _adg_part_ui_to_double(part, &part->A);
500 _adg_part_ui_to_double(part, &part->B);
501 _adg_part_ui_to_double(part, &part->C);
502 _adg_part_ui_to_double(part, &part->DHOLE);
503 _adg_part_ui_to_double(part, &part->LHOLE);
504 _adg_part_ui_to_double(part, &part->D1);
505 _adg_part_ui_to_double(part, &part->D2);
506 _adg_part_ui_to_double(part, &part->LD2);
507 _adg_part_ui_to_double(part, &part->D3);
508 _adg_part_ui_to_double(part, &part->LD3);
509 _adg_part_ui_to_double(part, &part->D4);
510 //_adg_part_ui_to_double(part, &part->D5);
511 _adg_part_ui_to_double(part, &part->D6);
512 //_adg_part_ui_to_double(part, &part->LD6);
513 _adg_part_ui_to_double(part, &part->D7);
514 //_adg_part_ui_to_double(part, &part->LD7);
516 _adg_part_lock(part);
518 adg_model_clear(ADG_MODEL(part->shape));
519 _adg_define_shape(part->shape, part);
520 adg_model_changed(ADG_MODEL(part->shape));
522 adg_model_clear(ADG_MODEL(part->hatch));
523 _adg_define_hatch(part->hatch, part);
524 adg_model_changed(ADG_MODEL(part->hatch));
526 adg_model_clear(ADG_MODEL(part->edges));
527 adg_model_changed(ADG_MODEL(part->edges));
529 gtk_widget_queue_draw(GTK_WIDGET(part->area));
532 static void
533 _adg_do_reset(AdgPart *part)
535 _adg_part_double_to_ui(part, &part->A);
536 _adg_part_double_to_ui(part, &part->B);
537 _adg_part_double_to_ui(part, &part->C);
538 _adg_part_double_to_ui(part, &part->DHOLE);
539 _adg_part_double_to_ui(part, &part->LHOLE);
540 _adg_part_double_to_ui(part, &part->D1);
541 _adg_part_double_to_ui(part, &part->D2);
542 _adg_part_double_to_ui(part, &part->LD2);
543 _adg_part_double_to_ui(part, &part->D3);
544 _adg_part_double_to_ui(part, &part->LD3);
545 _adg_part_double_to_ui(part, &part->D4);
546 //_adg_part_double_to_ui(part, &part->D5);
547 _adg_part_double_to_ui(part, &part->D6);
548 //_adg_part_double_to_ui(part, &part->LD6);
549 _adg_part_double_to_ui(part, &part->D7);
550 //_adg_part_double_to_ui(part, &part->LD7);
551 _adg_part_lock(part);
554 static void
555 _adg_do_save_as(GtkWidget *window, GtkResponseType response, AdgCanvas *canvas)
557 gchar *file, *suffix;
558 GtkRadioButton *type_radio;
559 cairo_surface_t *surface = NULL;
560 void (*callback)(cairo_surface_t *, gchar *) = NULL;
562 if (response != GTK_RESPONSE_OK) {
563 gtk_widget_hide(window);
564 return;
567 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(window));
568 if (file == NULL)
569 return;
571 type_radio = _adg_group_get_active(g_object_get_data(G_OBJECT(window),
572 "type-group"));
573 g_assert(GTK_IS_RADIO_BUTTON(type_radio));
575 suffix = gtk_widget_get_tooltip_markup(GTK_WIDGET(type_radio));
576 g_assert(suffix != NULL);
578 if (!g_str_has_suffix(file, suffix)) {
579 gchar *tmp = file;
580 file = g_strconcat(file, suffix, NULL);
581 g_free(tmp);
584 if (strcmp(suffix, ".png") == 0) {
585 #ifdef CAIRO_HAS_PNG_FUNCTIONS
586 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 800, 600);
587 callback = (gpointer) cairo_surface_write_to_png;
588 #endif
589 } else if (strcmp(suffix, ".pdf") == 0) {
590 #ifdef CAIRO_HAS_PDF_SURFACE
591 #include <cairo-pdf.h>
592 surface = cairo_pdf_surface_create(file, 841, 595);
593 #endif
594 } else if (strcmp(suffix, ".ps") == 0) {
595 #ifdef CAIRO_HAS_PS_SURFACE
596 #include <cairo-ps.h>
597 surface = cairo_ps_surface_create(file, 841, 595);
598 cairo_ps_surface_dsc_comment(surface, "%%Title: " PACKAGE_STRING);
599 cairo_ps_surface_dsc_comment(surface, "%%Copyright: Copyleft (C) 2006-2010 Fontana Nicola");
600 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Landscape");
601 cairo_ps_surface_dsc_begin_setup(surface);
602 cairo_ps_surface_dsc_begin_page_setup(surface);
603 cairo_ps_surface_dsc_comment(surface, "%%IncludeFeature: *PageSize A4");
604 #endif
607 if (surface) {
608 cairo_t *cr = cairo_create(surface);
609 cairo_surface_destroy(surface);
610 adg_entity_render(ADG_ENTITY(canvas), cr);
611 cairo_show_page(cr);
612 if (callback)
613 callback(surface, file);
614 cairo_destroy(cr);
617 g_free(file);
618 g_free(suffix);
619 gtk_widget_hide(window);
622 static void
623 _adg_print_prepare(GtkPrintOperation *operation, GtkPrintContext *context)
625 gtk_print_operation_set_n_pages(operation, 1);
628 static void
629 _adg_print_page(GtkPrintOperation *operation, GtkPrintContext *context,
630 gint page_nr, AdgEntity *canvas)
632 cairo_t *cr = gtk_print_context_get_cairo_context(context);
633 AdgMatrix old_map;
635 adg_matrix_copy(&old_map, adg_entity_get_global_map(canvas));;
637 adg_entity_set_global_map(canvas, adg_matrix_identity());
638 adg_entity_render(canvas, cr);
640 adg_entity_set_global_map(canvas, &old_map);
643 static void
644 _adg_do_print(GtkWidget *button, AdgCanvas *canvas)
646 static GtkPrintSettings *settings = NULL;
647 GtkWidget *window;
648 GtkPrintOperation *operation;
649 GtkPageSetup *page_setup;
650 GError *error;
652 window = gtk_widget_get_toplevel(button);
653 operation = gtk_print_operation_new();
654 page_setup = g_object_get_data(G_OBJECT(canvas), "_adg_page_setup");
655 error = NULL;
657 if (settings)
658 gtk_print_operation_set_print_settings(operation, settings);
659 if (page_setup)
660 gtk_print_operation_set_default_page_setup(operation, page_setup);
662 g_signal_connect(operation, "begin-print",
663 G_CALLBACK(_adg_print_prepare), NULL);
664 g_signal_connect(operation, "draw-page",
665 G_CALLBACK(_adg_print_page), canvas);
667 gtk_print_operation_set_use_full_page(operation, FALSE);
668 gtk_print_operation_set_unit(operation, GTK_UNIT_POINTS);
669 gtk_print_operation_set_embed_page_setup(operation, TRUE);
671 switch (gtk_print_operation_run(operation,
672 GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
673 GTK_WINDOW(window), &error)) {
675 case GTK_PRINT_OPERATION_RESULT_APPLY:
676 if (settings)
677 g_object_unref(settings);
679 settings = gtk_print_operation_get_print_settings(operation);
680 g_object_ref(settings);
681 break;
683 default:
684 break;
687 g_object_unref(operation);
689 if (error) {
690 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window),
691 GTK_DIALOG_DESTROY_WITH_PARENT,
692 GTK_MESSAGE_ERROR,
693 GTK_BUTTONS_CLOSE,
694 "%s", error->message);
695 g_error_free(error);
696 gtk_dialog_run(GTK_DIALOG(dialog));
697 gtk_widget_destroy(dialog);
701 static AdgPart *
702 _adg_part_new(GtkBuilder *builder)
704 AdgPart *part;
706 part = g_new0(AdgPart, 1);
707 part->widgets = g_hash_table_new_full(g_direct_hash, g_direct_equal,
708 NULL, g_object_unref);
709 part->area = (AdgGtkArea *) gtk_builder_get_object(builder, "mainCanvas");
710 part->apply = (GtkButton *) gtk_builder_get_object(builder, "editApply");
711 part->reset = (GtkButton *) gtk_builder_get_object(builder, "editReset");
712 part->shape = adg_path_new();
713 part->hatch = adg_path_new();
714 part->edges = adg_edges_new_with_source(ADG_TRAIL(part->shape));
716 g_assert(ADG_GTK_IS_AREA(part->area));
717 g_assert(GTK_IS_BUTTON(part->apply));
718 g_assert(GTK_IS_BUTTON(part->reset));
720 _adg_part_link(part, &part->A, gtk_builder_get_object(builder, "editA"));
721 _adg_part_link(part, &part->B, gtk_builder_get_object(builder, "editB"));
722 _adg_part_link(part, &part->C, gtk_builder_get_object(builder, "editC"));
723 _adg_part_link(part, &part->DHOLE, gtk_builder_get_object(builder, "editDHOLE"));
724 _adg_part_link(part, &part->LHOLE, gtk_builder_get_object(builder, "editLHOLE"));
725 _adg_part_link(part, &part->D1, gtk_builder_get_object(builder, "editD1"));
726 _adg_part_link(part, &part->D2, gtk_builder_get_object(builder, "editD2"));
727 _adg_part_link(part, &part->LD2, gtk_builder_get_object(builder, "editLD2"));
728 _adg_part_link(part, &part->D3, gtk_builder_get_object(builder, "editD3"));
729 _adg_part_link(part, &part->LD3, gtk_builder_get_object(builder, "editLD3"));
730 _adg_part_link(part, &part->D4, gtk_builder_get_object(builder, "editD4"));
731 //_adg_part_link(part, &part->D5, gtk_builder_get_object(builder, "editD5"));
732 _adg_part_link(part, &part->D6, gtk_builder_get_object(builder, "editD6"));
733 //_adg_part_link(part, &part->LD6, gtk_builder_get_object(builder, "editLD6"));
734 _adg_part_link(part, &part->D7, gtk_builder_get_object(builder, "editD7"));
735 //_adg_part_link(part, &part->LD7, gtk_builder_get_object(builder, "editLD7"));
737 part->D5 = 4.5;
738 part->RD34 = 1;
739 part->LD5 = 5;
740 part->LD6 = 1;
741 part->LD7 = 0.5;
743 _adg_do_edit(part);
745 return part;
748 static void
749 _adg_part_destroy(AdgPart *part)
751 g_hash_table_destroy(part->widgets);
752 g_free(part);
755 static GtkWidget *
756 _adg_about_window(GtkBuilder *builder)
758 GtkWidget *window;
760 window = (GtkWidget *) gtk_builder_get_object(builder, "wndAbout");
761 g_assert(GTK_IS_ABOUT_DIALOG(window));
763 g_signal_connect(window, "response", G_CALLBACK(gtk_widget_hide), NULL);
765 return window;
769 * _adg_window_hide:
770 * @window: a #GtkWindow
772 * A convenient function that hides @window storing the current position
773 * so any subsequent call to gtk_widget_show() will hopefully reopen
774 * the window at the same position.
776 * It is useful to connect this callback to a #GtkDialog::response signal.
778 static void
779 _adg_window_hide(GtkWindow *window)
781 gint x, y;
783 g_return_if_fail(GTK_IS_WINDOW(window));
785 gtk_window_get_position(window, &x, &y);
786 gtk_widget_hide((GtkWidget *) window);
787 gtk_window_set_position(window, GTK_WIN_POS_NONE);
788 gtk_window_move(window, x, y);
791 static GtkWidget *
792 _adg_edit_window(GtkBuilder *builder, AdgPart *part)
794 GtkWidget *window;
796 window = (GtkWidget *) gtk_builder_get_object(builder, "wndEdit");
797 g_assert(GTK_IS_DIALOG(window));
799 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
801 g_signal_connect_swapped(part->apply, "clicked",
802 G_CALLBACK(_adg_do_edit), part);
803 g_signal_connect_swapped(part->reset, "clicked",
804 G_CALLBACK(_adg_do_reset), part);
805 g_signal_connect(window, "response", G_CALLBACK(_adg_window_hide), NULL);
807 return window;
810 static GtkWidget *
811 _adg_save_as_window(GtkBuilder *builder, AdgCanvas *canvas)
813 GtkWidget *window;
814 GtkWidget *type_group, *button_save;
816 window = (GtkWidget *) gtk_builder_get_object(builder, "wndSaveAs");
817 g_assert(GTK_IS_WINDOW(window));
818 type_group = (GtkWidget *) gtk_builder_get_object(builder, "saveAsPng");
819 g_assert(GTK_IS_RADIO_BUTTON(type_group));
820 button_save = (GtkWidget *) gtk_builder_get_object(builder, "saveAsSave");
821 g_assert(GTK_IS_BUTTON(button_save));
823 g_object_set_data(G_OBJECT(window), "type-group", type_group);
825 g_signal_connect(window, "response", G_CALLBACK(_adg_do_save_as), canvas);
827 return window;
830 static GtkWidget *
831 _adg_main_window(GtkBuilder *builder)
833 GtkWidget *window;
834 AdgPart *part;
835 AdgCanvas *canvas;
836 GtkWidget *button_edit, *button_save_as, *button_print;
837 GtkWidget *button_about, *button_quit;
839 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
840 part = _adg_part_new(builder);
841 canvas = adg_canvas_new();
843 _adg_canvas_init(canvas, part);
844 adg_gtk_area_set_canvas(part->area, canvas);
846 g_assert(GTK_IS_WINDOW(window));
847 button_edit = (GtkWidget *) gtk_builder_get_object(builder, "mainEdit");
848 g_assert(GTK_IS_BUTTON(button_edit));
849 button_save_as = (GtkWidget *) gtk_builder_get_object(builder, "mainSaveAs");
850 g_assert(GTK_IS_BUTTON(button_save_as));
851 button_print = (GtkWidget *) gtk_builder_get_object(builder, "mainPrint");
852 g_assert(GTK_IS_BUTTON(button_print));
853 button_about = (GtkWidget *) gtk_builder_get_object(builder, "mainAbout");
854 g_assert(GTK_IS_BUTTON(button_about));
855 button_quit = (GtkWidget *) gtk_builder_get_object(builder, "mainQuit");
856 g_assert(GTK_IS_BUTTON(button_quit));
858 g_signal_connect_swapped(button_about, "clicked",
859 G_CALLBACK(gtk_dialog_run),
860 _adg_about_window(builder));
861 g_signal_connect_swapped(button_edit, "clicked",
862 G_CALLBACK(gtk_dialog_run),
863 _adg_edit_window(builder, part));
864 g_signal_connect_swapped(button_save_as, "clicked",
865 G_CALLBACK(gtk_dialog_run),
866 _adg_save_as_window(builder, canvas));
867 g_signal_connect(button_print, "clicked",
868 G_CALLBACK(_adg_do_print), canvas);
869 g_signal_connect(button_quit, "clicked", G_CALLBACK(gtk_main_quit), NULL);
870 g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
871 g_signal_connect_swapped(window, "destroy",
872 G_CALLBACK(_adg_part_destroy), part);
874 return window;
879 main(gint argc, gchar **argv)
881 gboolean show_extents;
882 gchar *path;
883 GtkBuilder *builder;
884 GError *error;
885 GtkWidget *main_window;
887 _adg_parse_args(&argc, &argv, &show_extents);
888 adg_switch_extents(show_extents);
890 path = demo_find_data_file("adg-demo.ui", argv[0]);
891 if (path == NULL) {
892 g_print("adg-demo.ui not found!\n");
893 return 1;
896 builder = gtk_builder_new();
897 error = NULL;
898 gtk_builder_add_from_file(builder, path, &error);
900 if (error != NULL) {
901 g_critical("%s", error->message);
902 g_error_free(error);
903 return 2;
906 main_window = _adg_main_window(builder);
907 g_object_unref(builder);
909 gtk_widget_show_all(main_window);
910 gtk_main();
912 return 0;