[AdgToyText] update_origin_cache() must return TRUE when succesfull
[adg.git] / demo / adg-demo.c
blobfd086222915ca46be218df180e53ff35fbc25d19
1 #include <adg/adg.h>
2 #include <math.h>
4 #include "demo.h"
7 #ifndef G_SQRT3
8 #define G_SQRT3 1.732050808
9 #endif
11 #define CHAMFER 0.3
14 /* Dummy model */
15 typedef struct _Piston Piston;
17 struct _Piston {
18 gdouble A, B, C;
19 gdouble D1, D2, D3, D4, D5, D6, D7;
20 gdouble RD34, RD56;
21 gdouble LD2, LD3, LD5, LD6, LD7;
25 static void ldim_path (AdgEntity *entity,
26 cairo_t *cr,
27 gpointer user_data);
28 static void ldim_expose (GtkWidget *widget,
29 GdkEventExpose *event,
30 AdgCanvas *canvas);
32 static void drawing_fill_model (Piston *piston);
33 static void drawing_add_dimensions (AdgCanvas *canvas,
34 Piston *piston);
35 static void drawing_add_stuff (AdgCanvas *canvas);
36 static void drawing_path (AdgEntity *entity,
37 cairo_t *cr,
38 gpointer user_data);
39 static void drawing_expose (GtkWidget *widget,
40 GdkEventExpose *event,
41 AdgCanvas *canvas);
43 static void to_pdf (AdgCanvas *canvas,
44 GtkWidget *caller);
45 static void to_png (AdgCanvas *canvas,
46 GtkWidget *caller);
47 static void to_ps (AdgCanvas *canvas,
48 GtkWidget *caller);
49 static void missing_feature (GtkWidget *caller,
50 const gchar *feature);
51 static void file_generated (GtkWidget *caller,
52 const gchar *file);
54 static Piston model;
57 int
58 main(gint argc, gchar **argv)
60 gchar *path;
61 GtkBuilder *builder;
62 GError *error;
63 GtkWidget *window;
64 AdgCanvas *ldim_canvas, *drawing_canvas;
65 AdgEntity *entity;
67 gtk_init(&argc, &argv);
70 /* LDim demo */
71 ldim_canvas = adg_canvas_new();
73 entity = adg_stroke_new(ldim_path, NULL);
74 adg_container_add(ADG_CONTAINER(ldim_canvas), entity);
76 entity = adg_ldim_new_full_explicit(2, -10, 8, -10, ADG_DIR_UP, 0, -10);
77 adg_container_add(ADG_CONTAINER(ldim_canvas), entity);
79 entity = adg_ldim_new_full_explicit(0, -5, 10, -5, ADG_DIR_UP, 0, -10);
80 adg_dim_set_level(ADG_DIM(entity), 2);
81 adg_container_add(ADG_CONTAINER(ldim_canvas), entity);
84 /* Drawing demo */
85 drawing_canvas = adg_canvas_new();
87 drawing_fill_model(&model);
89 entity = adg_stroke_new(drawing_path, NULL);
90 adg_container_add(ADG_CONTAINER(drawing_canvas), entity);
92 drawing_add_dimensions(drawing_canvas, &model);
93 drawing_add_stuff(drawing_canvas);
96 /* User interface stuff */
97 path = demo_find_data_file("adg-demo.ui");
98 if (path == NULL) {
99 g_print("adg-demo.ui not found!\n");
100 return 1;
103 builder = gtk_builder_new();
104 error = NULL;
106 gtk_builder_add_from_file(builder, path, &error);
107 if (error != NULL) {
108 g_print("%s\n", error->message);
109 return 2;
112 window = (GtkWidget *) gtk_builder_get_object(builder, "wndMain");
114 /* Connect signals */
115 g_signal_connect(window, "delete-event",
116 G_CALLBACK(gtk_main_quit), NULL);
117 g_signal_connect(gtk_builder_get_object(builder, "btnQuit"),
118 "clicked", G_CALLBACK(gtk_main_quit), NULL);
120 g_signal_connect(gtk_builder_get_object(builder, "areaLDim"),
121 "expose-event", G_CALLBACK(ldim_expose), ldim_canvas);
123 g_signal_connect(gtk_builder_get_object(builder, "areaDrawing"),
124 "expose-event", G_CALLBACK(drawing_expose), drawing_canvas);
125 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPng"),
126 "clicked", G_CALLBACK(to_png), drawing_canvas);
127 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPdf"),
128 "clicked", G_CALLBACK(to_pdf), drawing_canvas);
129 g_signal_connect_swapped(gtk_builder_get_object(builder, "btnPs"),
130 "clicked", G_CALLBACK(to_ps), drawing_canvas);
132 g_object_unref(builder);
134 gtk_widget_show_all(window);
135 gtk_main();
137 return 0;
141 static void
142 ldim_path(AdgEntity *entity, cairo_t *cr, gpointer user_data)
144 cairo_move_to(cr, 0, 0);
145 cairo_line_to(cr, 0, -5);
146 cairo_line_to(cr, 2, -5);
147 cairo_line_to(cr, 2, -10);
148 cairo_line_to(cr, 8, -10);
149 cairo_line_to(cr, 8, -5);
150 cairo_line_to(cr, 10., -5);
151 cairo_line_to(cr, 10., 0);
152 cairo_close_path(cr);
155 static void
156 ldim_expose(GtkWidget *widget, GdkEventExpose *event, AdgCanvas *canvas)
158 cairo_t *cr;
159 gint width, height;
160 double xscale, yscale, scale;
161 AdgMatrix matrix;
163 cr = gdk_cairo_create(widget->window);
164 width = widget->allocation.width;
165 height = widget->allocation.height;
167 /* Fit ldim in horizontal or vertical space keeping the aspect ratio:
168 * the lesser scale factor will be used */
169 xscale = (double) (width - 20) / 10;
170 yscale = (double) (height - 90) / 10;
172 if (xscale < yscale)
173 scale = xscale;
174 else
175 scale = yscale;
177 cairo_matrix_init_translate(&matrix, 10, 80);
178 cairo_matrix_scale(&matrix, scale, scale);
179 cairo_matrix_translate(&matrix, 0, 10);
180 adg_container_set_model_transformation(ADG_CONTAINER(canvas), &matrix);
182 /* Rendering process */
183 adg_entity_render(ADG_ENTITY(canvas), cr);
185 cairo_destroy(cr);
189 static void
190 drawing_fill_model(Piston *piston)
192 piston->A = 52.3;
193 piston->B = 20.6;
194 piston->C = 2;
195 piston->D1 = 9.3;
196 piston->D2 = 6.5;
197 piston->D3 = 11.9;
198 piston->D4 = 6.5;
199 piston->D5 = 4.5;
200 piston->D6 = 7.2;
201 piston->D7 = 3.;
202 piston->RD34 = 1.;
203 piston->LD2 = 7.;
204 piston->LD3 = 3.5;
205 piston->LD5 = 5.;
206 piston->LD6 = 1.;
207 piston->LD7 = 0.5;
210 static void
211 drawing_add_dimensions(AdgCanvas *canvas, Piston *piston)
213 double A, B, C;
214 double D1, D2, D3, D4, D5, D6, D7;
215 double LD2, LD3, LD5, LD6, LD7;
216 double RD34, RD56;
217 AdgEntity *entity;
218 double x, y;
220 A = piston->A;
221 B = piston->B;
222 C = piston->C;
223 D1 = piston->D1;
224 D2 = piston->D2;
225 D3 = piston->D3;
226 D4 = piston->D4;
227 D5 = piston->D5;
228 D6 = piston->D6;
229 D7 = piston->D7;
230 LD2 = piston->LD2;
231 LD3 = piston->LD3;
232 LD5 = piston->LD5;
233 LD6 = piston->LD6;
234 LD7 = piston->LD7;
235 RD34 = piston->RD34;
236 RD56 = piston->RD56;
239 /* North */
241 /* LD2 */
242 entity = adg_ldim_new_full_explicit(A - B - LD2, -D1 / 2, A - B,
243 -D3 / 2 + CHAMFER, ADG_DIR_UP, 0,
244 -D3 / 2);
245 adg_container_add(ADG_CONTAINER(canvas), entity);
247 /* LD3 */
248 entity = adg_ldim_new_full_explicit(A - B, -D3 / 2 + CHAMFER, A - B + LD3,
249 -D3 / 2 + CHAMFER, ADG_DIR_UP, 0,
250 -D3 / 2);
251 adg_container_add(ADG_CONTAINER(canvas), entity);
254 /* South */
256 /* B */
257 entity = adg_ldim_new_full_explicit(A - B, D3 / 2 - CHAMFER, A, D7 / 2,
258 ADG_DIR_DOWN, 0, D3 / 2);
259 adg_dim_set_tolerances(ADG_DIM(entity), "+0.1", NULL);
260 adg_container_add(ADG_CONTAINER(canvas), entity);
262 /* A */
263 entity = adg_ldim_new_full_explicit(0, D1 / 2, A, D7 / 2,
264 ADG_DIR_DOWN, 0, D3 / 2);
265 adg_dim_set_tolerances(ADG_DIM(entity), "+0.05", "-0.05");
266 adg_dim_set_level(ADG_DIM(entity), 2);
267 adg_container_add(ADG_CONTAINER(canvas), entity);
270 /* East */
272 /* D3 */
273 x = A - B + LD3 - CHAMFER;
274 entity = adg_ldim_new_full_explicit(x, -D3 / 2, x, D3 / 2,
275 ADG_DIR_RIGHT, A, 0);
276 adg_dim_set_tolerances(ADG_DIM(entity), "-0.25", NULL);
277 adg_dim_set_level(ADG_DIM(entity), 5);
278 adg_container_add(ADG_CONTAINER(canvas), entity);
280 /* D6 */
281 x = A - C + LD6;
282 entity = adg_ldim_new_full_explicit(x, -D6 / 2, x, D6 / 2,
283 ADG_DIR_RIGHT, A, 0);
284 adg_dim_set_tolerances(ADG_DIM(entity), "-0.1", NULL);
285 adg_dim_set_level(ADG_DIM(entity), 4);
286 adg_container_add(ADG_CONTAINER(canvas), entity);
288 /* D4 */
289 x = A - C - LD5;
290 entity = adg_ldim_new_full_explicit(x, -D4 / 2, x, D4 / 2,
291 ADG_DIR_RIGHT, A, 0);
292 adg_dim_set_level(ADG_DIM(entity), 3);
293 adg_container_add(ADG_CONTAINER(canvas), entity);
295 /* D5 */
296 x = A - C;
297 entity = adg_ldim_new_full_explicit(x, -D5 / 2, x, D5 / 2,
298 ADG_DIR_RIGHT, A, 0);
299 adg_dim_set_tolerances(ADG_DIM(entity), "-0.1", NULL);
300 adg_dim_set_level(ADG_DIM(entity), 2);
301 adg_container_add(ADG_CONTAINER(canvas), entity);
303 /* D7 */
304 entity = adg_ldim_new_full_explicit(A, -D7 / 2, A, D7 / 2,
305 ADG_DIR_RIGHT, A, 0);
306 adg_container_add(ADG_CONTAINER(canvas), entity);
309 /* West */
311 /* D1 */
312 entity = adg_ldim_new_full_explicit(0, -D1 / 2, 0, D1 / 2,
313 ADG_DIR_LEFT, 0, 0);
314 adg_dim_set_tolerances(ADG_DIM(entity), "+0.05", "-0.05");
315 adg_dim_set_level(ADG_DIM(entity), 2);
316 adg_container_add(ADG_CONTAINER(canvas), entity);
318 /* D2 */
319 y = (D1 - D2) / 2;
320 x = A - B - LD2 + y * G_SQRT3;
321 entity = adg_ldim_new_full_explicit(x, -D2 / 2, x, D2 / 2,
322 ADG_DIR_LEFT, 0, 0);
323 adg_dim_set_tolerances(ADG_DIM(entity), "-0.1", NULL);
324 adg_container_add(ADG_CONTAINER(canvas), entity);
327 static void
328 drawing_add_stuff(AdgCanvas *canvas)
330 AdgEntity *toy_text;
332 toy_text = adg_toy_text_new("Horizontal toy_text above the piston");
333 adg_translatable_set_origin_explicit(ADG_TRANSLATABLE(toy_text),
334 0., -4.65,
335 0., -5.);
336 adg_container_add(ADG_CONTAINER(canvas), toy_text);
338 toy_text = adg_toy_text_new("toy_text");
339 adg_translatable_set_origin_explicit(ADG_TRANSLATABLE(toy_text),
340 0., 4.65,
341 0., -5.);
342 adg_rotable_set_angle(ADG_ROTABLE(toy_text), M_PI * 3./2.);
343 adg_container_add(ADG_CONTAINER(canvas), toy_text);
346 static void
347 drawing_path(AdgEntity *entity, cairo_t *cr, gpointer user_data)
349 Piston *piston;
350 double A, B, C;
351 double D1, D2, D3, D4, D5, D6, D7;
352 double LD2, LD3, LD5, LD6, LD7;
353 double RD34, RD56;
354 double x, y;
355 cairo_path_t *path;
356 CpmlSegment segment;
357 AdgMatrix matrix;
359 piston = &model;
361 A = piston->A;
362 B = piston->B;
363 C = piston->C;
364 D1 = piston->D1;
365 D2 = piston->D2;
366 D3 = piston->D3;
367 D4 = piston->D4;
368 D5 = piston->D5;
369 D6 = piston->D6;
370 D7 = piston->D7;
371 LD2 = piston->LD2;
372 LD3 = piston->LD3;
373 LD5 = piston->LD5;
374 LD6 = piston->LD6;
375 LD7 = piston->LD7;
376 RD34 = piston->RD34;
377 RD56 = piston->RD56;
379 cairo_move_to(cr, 0, D1 / 2);
380 cairo_line_to(cr, A - B - LD2, D1 / 2);
381 y = (D1 - D2) / 2;
382 cairo_line_to(cr, A - B - LD2 + y * G_SQRT3, D1 / 2 - y);
383 cairo_line_to(cr, A - B, D2 / 2);
384 cairo_line_to(cr, A - B, D3 / 2 - CHAMFER);
385 cairo_line_to(cr, A - B + CHAMFER, D3 / 2);
386 cairo_line_to(cr, A - B + LD3 - CHAMFER, D3 / 2);
387 cairo_line_to(cr, A - B + LD3, D3 / 2 - CHAMFER);
388 x = A - B + LD3 + RD34;
389 y = D4 / 2 + RD34;
390 cairo_arc(cr, x, y, RD34, G_PI, 3 * G_PI_2);
391 cairo_line_to(cr, A - C - LD5, D4 / 2);
392 y = (D4 - D5) / 2;
393 cairo_line_to(cr, A - C - LD5 + y, D4 / 2 - y);
394 cairo_line_to(cr, A - C, D5 / 2);
395 cairo_line_to(cr, A - C, D6 / 2);
396 cairo_line_to(cr, A - C + LD6, D6 / 2);
397 x = C - LD7 - LD6;
398 y = x / G_SQRT3;
399 cairo_line_to(cr, A - C + LD6 + x, D6 / 2 - y);
400 cairo_line_to(cr, A - LD7, D7 / 2);
401 cairo_line_to(cr, A, D7 / 2);
403 /* Build the shape by reflecting the current path, reversing the order
404 * and joining the result to the current path */
405 path = cairo_copy_path(cr);
406 cpml_segment_from_cairo(&segment, path);
407 cpml_segment_reverse(&segment);
408 adg_matrix_init_reflection(&matrix, 0);
409 cpml_segment_transform(&segment, &matrix);
410 path->data[0].header.type = CAIRO_PATH_LINE_TO;
411 cairo_append_path(cr, path);
412 cairo_path_destroy(path);
413 cairo_close_path(cr);
416 static void
417 drawing_expose(GtkWidget *widget, GdkEventExpose *event, AdgCanvas *canvas)
419 cairo_t *cr;
420 gint width, height;
421 double scale;
422 AdgMatrix matrix;
424 cr = gdk_cairo_create(widget->window);
425 width = widget->allocation.width;
426 height = widget->allocation.height;
428 /* Hardcoding sizes is a really ugly way to scale a drawing but... */
429 scale = (double) (width - 100 - 180) / 52.3;
431 cairo_matrix_init_translate(&matrix, 100, 70);
432 cairo_matrix_scale(&matrix, scale, scale);
433 cairo_matrix_translate(&matrix, 0, 6);
434 adg_container_set_model_transformation(ADG_CONTAINER(canvas), &matrix);
436 /* Rendering process */
437 adg_entity_render(ADG_ENTITY(canvas), cr);
439 cairo_destroy(cr);
443 #ifdef CAIRO_HAS_PNG_FUNCTIONS
445 static void
446 to_png(AdgCanvas *canvas, GtkWidget *caller)
448 cairo_surface_t *surface;
449 cairo_t *cr;
451 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
452 cr = cairo_create(surface);
453 cairo_surface_destroy(surface);
455 /* Rendering process */
456 adg_entity_render(ADG_ENTITY(canvas), cr);
458 cairo_show_page(cr);
459 cairo_surface_write_to_png(surface, "test.png");
460 cairo_destroy(cr);
462 file_generated(caller, "test.png");
465 #else
467 static void
468 to_png(AdgCanvas *canvas, GtkWidget *caller)
470 missing_feature(caller, "PNG");
473 #endif
476 #ifdef CAIRO_HAS_PDF_SURFACE
478 #include <cairo-pdf.h>
480 static void
481 to_pdf(AdgCanvas *canvas, GtkWidget *caller)
483 cairo_surface_t *surface;
484 cairo_t *cr;
486 surface = cairo_pdf_surface_create("test.pdf", 841, 595);
487 cr = cairo_create(surface);
488 cairo_surface_destroy(surface);
490 adg_entity_render(ADG_ENTITY(canvas), cr);
492 cairo_show_page(cr);
493 cairo_destroy(cr);
495 file_generated(caller, "test.pdf");
498 #else
500 static void
501 to_pdf(AdgCanvas *canvas, GtkWidget *caller)
503 missing_feature(caller, "PDF");
506 #endif
509 #ifdef CAIRO_HAS_PS_SURFACE
511 #include <cairo-ps.h>
513 static void
514 to_ps(AdgCanvas *canvas, GtkWidget *caller)
516 cairo_surface_t *surface;
517 cairo_t *cr;
519 /* Surface creation: A4 size */
520 surface = cairo_ps_surface_create("test.ps", 841, 595);
521 cairo_ps_surface_dsc_comment(surface,
522 "%%Title: Automatic Drawing Generation (Adg) demo");
523 cairo_ps_surface_dsc_comment(surface,
524 "%%Copyright: Copyright (C) 2006 Fontana Nicola");
525 cairo_ps_surface_dsc_comment(surface, "%%Orientation: Portrait");
527 cairo_ps_surface_dsc_begin_setup(surface);
529 cairo_ps_surface_dsc_begin_page_setup(surface);
530 cairo_ps_surface_dsc_comment(surface,
531 "%%IncludeFeature: *PageSize A4");
533 cr = cairo_create(surface);
534 cairo_surface_destroy(surface);
536 adg_entity_render(ADG_ENTITY(canvas), cr);
538 cairo_show_page(cr);
539 cairo_destroy(cr);
541 file_generated(caller, "test.ps");
544 #else
546 static void
547 to_ps(AdgCanvas *canvas, GtkWidget *caller)
549 missing_feature(caller, "PostScript");
552 #endif
555 static void
556 missing_feature(GtkWidget *caller, const gchar *feature)
558 GtkWindow *window;
559 GtkWidget *dialog;
561 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
562 dialog = gtk_message_dialog_new(window, GTK_DIALOG_MODAL,
563 GTK_MESSAGE_WARNING,
564 GTK_BUTTONS_OK,
565 "The provided cairo library\n"
566 "was compiled with no %s support!",
567 feature);
568 gtk_window_set_title(GTK_WINDOW(dialog), "Missing feature");
569 gtk_dialog_run(GTK_DIALOG(dialog));
570 gtk_widget_destroy(dialog);
573 static void
574 file_generated(GtkWidget *caller, const gchar *file)
576 GtkWindow *window;
577 GtkWidget *dialog;
579 window = (GtkWindow *) gtk_widget_get_toplevel(caller);
580 dialog = gtk_message_dialog_new_with_markup(window, GTK_DIALOG_MODAL,
581 GTK_MESSAGE_INFO,
582 GTK_BUTTONS_CLOSE,
583 "The requested operation generated\n"
584 "<b>%s</b> in the current directory.",
585 file);
586 gtk_window_set_title(GTK_WINDOW(dialog), "Operation completed");
587 gtk_dialog_run(GTK_DIALOG(dialog));
588 gtk_widget_destroy(dialog);