1 /*
2  * GooCanvas Demo. Copyright (C) 2005 Damon Chaplin.
3  * Released under the GNU LGPL license. See COPYING for details.
4  *
5  * main.c - demo app.
6  */
7 #include <config.h>
8 #include <math.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <glib/gi18n.h>
12 #include <gtk/gtk.h>
13 #include <cairo.h>
14 #if CAIRO_HAS_PDF_SURFACE
15 #include <cairo-pdf.h>
16 #endif
17 #include <goocanvas.h>
18 #include "demo-item.h"
19 
20 static GooCanvasItem *ellipse2, *textitem;
21 
22 static gboolean dragging = FALSE;
23 static double drag_x, drag_y;
24 
25 static void setup_canvas (GooCanvas *canvas);
26 GtkWidget *create_canvas_fifteen (void);
27 GtkWidget *create_canvas_features (void);
28 GtkWidget *create_canvas_arrowhead (void);
29 GtkWidget *create_canvas_scalability (void);
30 GtkWidget *create_grabs_page (void);
31 GtkWidget *create_events_page (void);
32 GtkWidget *create_paths_page (void);
33 GtkWidget *create_focus_page (void);
34 GtkWidget *create_animation_page (void);
35 GtkWidget *create_clipping_page (void);
36 GtkWidget *create_table_page (void);
37 GtkWidget *create_large_items_page (void);
38 
39 #if CAIRO_HAS_PDF_SURFACE
40 static void
write_pdf_clicked(GtkWidget * button,GooCanvas * canvas)41 write_pdf_clicked (GtkWidget *button, GooCanvas *canvas)
42 {
43   cairo_surface_t *surface;
44   GooCanvasBounds bounds G_GNUC_UNUSED;
45   cairo_t *cr;
46 
47   g_print ("In write_pdf_clicked\n");
48 
49   surface = cairo_pdf_surface_create ("demo.pdf", 9 * 72, 10 * 72);
50   cr = cairo_create (surface);
51 
52   /* Place it in the middle of our 9x10 page. */
53   cairo_translate (cr, 20, 130);
54 
55   bounds.x1 = 100;
56   bounds.y1 = 100;
57   bounds.x2 = 300;
58   bounds.y2 = 300;
59 
60 #if 1
61   goo_canvas_render (canvas, cr, NULL, 1.0);
62 #else
63   goo_canvas_render (canvas, cr, &bounds, 1.0);
64 #endif
65 
66   cairo_show_page (cr);
67 
68   cairo_surface_destroy (surface);
69   cairo_destroy (cr);
70 }
71 #endif
72 
73 static void
zoom_changed(GtkAdjustment * adj,GooCanvas * canvas)74 zoom_changed (GtkAdjustment *adj, GooCanvas *canvas)
75 {
76   goo_canvas_set_scale (canvas, gtk_adjustment_get_value (adj));
77 }
78 
79 
80 static void
zoom_x_changed(GtkAdjustment * adj,GooCanvas * canvas)81 zoom_x_changed (GtkAdjustment *adj, GooCanvas *canvas)
82 {
83   g_object_set (G_OBJECT (canvas),
84 		"scale-x", gtk_adjustment_get_value (adj),
85 		NULL);
86 }
87 
88 
89 static void
zoom_y_changed(GtkAdjustment * adj,GooCanvas * canvas)90 zoom_y_changed (GtkAdjustment *adj, GooCanvas *canvas)
91 {
92   g_object_set (G_OBJECT (canvas),
93 		"scale-y", gtk_adjustment_get_value (adj),
94 		NULL);
95 }
96 
97 
98 static void
center_toggled(GtkToggleButton * button,gpointer data)99 center_toggled (GtkToggleButton *button, gpointer data)
100 {
101   /*foo_canvas_set_center_scroll_region (data,
102                                    gtk_toggle_button_get_active (button));*/
103 }
104 
105 
106 static void
anchor_toggled(GtkWidget * button,GooCanvas * canvas)107 anchor_toggled (GtkWidget *button, GooCanvas *canvas)
108 {
109   GooCanvasAnchorType anchor;
110 
111   anchor = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "anchor"));
112 
113   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
114     g_object_set (canvas, "anchor", anchor, NULL);
115 }
116 
117 
118 static void
scroll_to_50_50_clicked(GtkWidget * button,GooCanvas * canvas)119 scroll_to_50_50_clicked (GtkWidget *button, GooCanvas *canvas)
120 {
121   goo_canvas_scroll_to (canvas, 50, 50);
122 }
123 
124 
125 static void
scroll_to_500_500_clicked(GtkWidget * button,GooCanvas * canvas)126 scroll_to_500_500_clicked (GtkWidget *button, GooCanvas *canvas)
127 {
128   goo_canvas_scroll_to (canvas, 500, 500);
129 }
130 
131 
132 static void
scroll_to_250_250_clicked(GtkWidget * button,GooCanvas * canvas)133 scroll_to_250_250_clicked (GtkWidget *button, GooCanvas *canvas)
134 {
135   goo_canvas_scroll_to (canvas, 250, 250);
136 }
137 
138 
139 static void
animate_ellipse_clicked(GtkWidget * button,GooCanvas * canvas)140 animate_ellipse_clicked (GtkWidget *button, GooCanvas *canvas)
141 {
142 #if 1
143   goo_canvas_item_animate (ellipse2, 100, 100, 1, 90, TRUE, 1000, 40,
144 			   GOO_CANVAS_ANIMATE_BOUNCE);
145 #endif
146 #if 0
147   goo_canvas_item_animate (textitem, -300, -200, 1, 90, TRUE, 1000, 40,
148 			   GOO_CANVAS_ANIMATE_BOUNCE);
149 #endif
150 }
151 
152 
153 static void
stop_animation_clicked(GtkWidget * button,GooCanvas * canvas)154 stop_animation_clicked (GtkWidget *button, GooCanvas *canvas)
155 {
156   goo_canvas_item_stop_animation (ellipse2);
157 }
158 
159 
160 static void
change_bounds_clicked(GtkWidget * button,GooCanvas * canvas)161 change_bounds_clicked (GtkWidget *button, GooCanvas *canvas)
162 {
163   static gdouble bounds[4][4] = {
164     { -100, -100, 200, 200 },
165     { 100, 100, 200, 200 },
166     { 0, 0, 300, 300 },
167     { 0, 0, 604, 454 }
168   };
169   static gint bounds_num = 0;
170 
171   gboolean automatic_bounds = TRUE;
172   gboolean bounds_from_origin = FALSE;
173   gdouble bounds_padding = 50.0;
174 
175   if (bounds_num < 4)
176     {
177       automatic_bounds = FALSE;
178       goo_canvas_set_bounds (canvas,
179 			     bounds[bounds_num][0], bounds[bounds_num][1],
180 			     bounds[bounds_num][2], bounds[bounds_num][3]);
181     }
182   else if (bounds_num == 4)
183     {
184       bounds_from_origin = TRUE;
185       bounds_padding = 50.0;
186     }
187 
188   g_object_set (G_OBJECT (canvas),
189 		"automatic-bounds", automatic_bounds,
190 		"bounds-from-origin", bounds_from_origin,
191 		"bounds-padding", bounds_padding,
192 		NULL);
193 
194   bounds_num = (bounds_num + 1) % 6;
195 }
196 
197 
198 static void
move_ellipse_clicked(GtkWidget * button,GooCanvas * canvas)199 move_ellipse_clicked (GtkWidget *button, GooCanvas *canvas)
200 {
201   static int last_state = 0;
202 
203 #if 0
204   g_print ("Moving ellipse\n");
205 #endif
206 
207   goo_canvas_item_set_transform (ellipse2, NULL);
208 
209   if (last_state == 0)
210     {
211       g_object_set (ellipse2,
212 		    "center-x", 300.0,
213 		    "center-y", 70.0,
214 		    "radius-x", 45.0,
215 		    "radius-y", 30.0,
216 		    "fill-color", "red",
217 		    "stroke-color", "midnightblue",
218 		    "line-width", 4.0,
219 		    "title", "A red ellipse",
220 		    NULL);
221       last_state = 1;
222     }
223   else if (last_state == 1)
224     {
225       g_object_set (ellipse2,
226 		    "center-x", 390.0,
227 		    "center-y", 150.0,
228 		    "radius-x", 45.0,
229 		    "radius-y", 40.0,
230 		    "fill-pattern", NULL,
231 		    "stroke-color", "midnightblue",
232 		    "line-width", 4.0,
233 		    "title", "A brown ellipse",
234 		    NULL);
235       last_state = 2;
236     }
237   else if (last_state == 2)
238     {
239       g_object_set (ellipse2,
240 		    "center-x", 0.0,
241 		    "center-y", 0.0,
242 		    "radius-y", 30.0,
243 		    NULL);
244       goo_canvas_item_set_simple_transform (ellipse2, 100, 100, 1, 0);
245       last_state = 3;
246     }
247   else if (last_state == 3)
248     {
249       goo_canvas_item_set_simple_transform (ellipse2, 200, 100, 2, 0);
250       last_state = 4;
251     }
252   else if (last_state == 4)
253     {
254       goo_canvas_item_set_simple_transform (ellipse2, 200, 200, 1, 45);
255       last_state = 5;
256     }
257   else if (last_state == 5)
258     {
259       goo_canvas_item_set_simple_transform (ellipse2, 50, 50, 0.2, 225);
260       last_state = 6;
261     }
262   else
263     {
264       g_object_set (ellipse2,
265 		    "center-x", 335.0,
266 		    "center-y", 70.0,
267 		    "radius-x", 45.0,
268 		    "radius-y", 30.0,
269 		    "fill-color", "purple",
270 		    "stroke-color", "midnightblue",
271 		    "line-width", 4.0,
272 		    "title", "A purple ellipse",
273 		    NULL);
274       last_state = 0;
275     }
276 }
277 
278 
279 static gboolean
on_motion_notify(GooCanvasItem * item,GooCanvasItem * target,GdkEventMotion * event,gpointer data)280 on_motion_notify (GooCanvasItem *item,
281 		  GooCanvasItem *target,
282 		  GdkEventMotion *event,
283 		  gpointer data)
284 {
285 #if 0
286   g_print ("received 'motion-notify' signal at %g, %g\n",
287 	   event->x, event->y);
288 #endif
289 
290   if (dragging && (event->state & GDK_BUTTON1_MASK))
291     {
292       double new_x = event->x;
293       double new_y = event->y;
294 
295       goo_canvas_item_translate (item, new_x - drag_x, new_y - drag_y);
296     }
297 
298   return TRUE;
299 }
300 
301 
302 static void
output_items_in_area(GooCanvas * canvas,gdouble x,gdouble y)303 output_items_in_area (GooCanvas *canvas,
304 		      gdouble x,
305 		      gdouble y)
306 {
307   static gdouble last_x = 0.0, last_y = 0.0;
308   GooCanvasBounds area;
309   GList *items, *elem;
310 
311   /* Print out the items from the last point to this one. */
312   area.x1 = MIN (x, last_x);
313   area.x2 = MAX (x, last_x);
314   area.y1 = MIN (y, last_y);
315   area.y2 = MAX (y, last_y);
316   items = goo_canvas_get_items_in_area (canvas, &area, TRUE, FALSE, FALSE);
317   for (elem = items; elem; elem = elem->next)
318     {
319       g_print ("  found items in area (%g, %g - %g, %g): %p\n",
320 	       area.x1, area.y1, area.x2, area.y2, elem->data);
321     }
322   g_list_free (items);
323   last_x = x;
324   last_y = y;
325 }
326 
327 
328 static gboolean
on_button_press(GooCanvasItem * item,GooCanvasItem * target,GdkEventButton * event,gpointer data)329 on_button_press (GooCanvasItem *item,
330 		 GooCanvasItem *target,
331 		 GdkEventButton *event,
332 		 gpointer data)
333 {
334   GooCanvas *canvas;
335   GdkDisplay *display;
336   GdkCursor *fleur;
337   GList *items, *elem;
338 
339   g_print ("%p received 'button-press' signal at %g, %g (root: %g, %g)\n",
340 	   item, event->x, event->y, event->x_root, event->y_root);
341 
342   canvas = goo_canvas_item_get_canvas (item);
343   items = goo_canvas_get_items_at (canvas, event->x_root, event->y_root,
344 				   TRUE);
345   for (elem = items; elem; elem = elem->next)
346     g_print ("  found items: %p\n", elem->data);
347   g_list_free (items);
348 
349   output_items_in_area (canvas, event->x_root, event->y_root);
350 
351   switch (event->button)
352     {
353     case 1:
354       if (event->state & GDK_SHIFT_MASK)
355 	{
356 	  goo_canvas_item_remove (item);
357 	}
358       else
359 	{
360 	  drag_x = event->x;
361 	  drag_y = event->y;
362 
363 	  display = gtk_widget_get_display (GTK_WIDGET (canvas));
364 	  fleur = gdk_cursor_new_for_display (display, GDK_FLEUR);
365 	  goo_canvas_pointer_grab (canvas, item,
366 				   GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_RELEASE_MASK,
367 				   fleur,
368 				   event->time);
369 	  g_object_unref (fleur);
370 	  dragging = TRUE;
371 	}
372       break;
373 
374     case 2:
375       goo_canvas_item_lower (item, NULL);
376       break;
377 
378     case 3:
379       goo_canvas_item_raise (item, NULL);
380       break;
381 
382     default:
383       break;
384     }
385 
386   return TRUE;
387 }
388 
389 
390 static gboolean
on_scroll(GooCanvasItem * item,GooCanvasItem * target,GdkEventScroll * event,gpointer data)391 on_scroll (GooCanvasItem *item,
392 	   GooCanvasItem *target,
393 	   GdkEventScroll *event,
394 	   gpointer data)
395 {
396 #if 0
397   g_print ("received 'scroll-event' signal\n");
398 #endif
399 
400   if (event->direction == GDK_SCROLL_UP)
401     goo_canvas_item_scale (item, 1.1, 1.1);
402   else if (event->direction == GDK_SCROLL_DOWN)
403     goo_canvas_item_scale (item, 0.909, 0.909);
404   else return FALSE;
405 
406   return TRUE;
407 }
408 
409 static gboolean
on_button_release(GooCanvasItem * item,GooCanvasItem * target,GdkEventButton * event,gpointer data)410 on_button_release (GooCanvasItem *item,
411 		   GooCanvasItem *target,
412 		   GdkEventButton *event,
413 		   gpointer data)
414 {
415   GooCanvas *canvas;
416 
417 #if 0
418   g_print ("received 'button-release' signal\n");
419 #endif
420 
421   canvas = goo_canvas_item_get_canvas (item);
422   goo_canvas_pointer_ungrab (canvas, item, event->time);
423   dragging = FALSE;
424 
425   return TRUE;
426 }
427 
428 static gboolean
on_background_button_press(GooCanvasItem * item,GooCanvasItem * target,GdkEventButton * event,gpointer data)429 on_background_button_press (GooCanvasItem *item,
430 			    GooCanvasItem *target,
431 			    GdkEventButton *event,
432 			    gpointer data)
433 {
434   GooCanvas *canvas;
435   GList *items, *elem;
436 
437 #if 1
438   g_print ("background received 'button-press' signal\n");
439 #endif
440 
441   canvas = goo_canvas_item_get_canvas (item);
442   output_items_in_area (canvas, event->x_root, event->y_root);
443 
444   items = goo_canvas_get_items_at (canvas, event->x_root, event->y_root,
445 				   FALSE);
446   for (elem = items; elem; elem = elem->next)
447     g_print ("  clicked items: %p\n", elem->data);
448   g_list_free (items);
449 
450   return TRUE;
451 }
452 
453 
454 static void
setup_item_signals(GooCanvasItem * item)455 setup_item_signals (GooCanvasItem *item)
456 {
457   g_signal_connect (item, "motion_notify_event",
458 		    G_CALLBACK (on_motion_notify), NULL);
459   g_signal_connect (item, "button_press_event",
460 		    G_CALLBACK (on_button_press), NULL);
461   g_signal_connect (item, "button_release_event",
462 		    G_CALLBACK (on_button_release), NULL);
463 }
464 
465 
466 GtkWidget *
create_canvas_primitives()467 create_canvas_primitives ()
468 {
469 	GtkWidget *vbox;
470 	GtkWidget *hbox;
471 	GtkWidget *w;
472 	GtkWidget *scrolled_win, *canvas;
473 	GtkAdjustment *adj;
474 	GSList *group = NULL;
475 
476 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
477 	gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
478 	gtk_widget_show (vbox);
479 
480 	w = gtk_label_new ("Drag an item with button 1.  Click button 2 on an item to lower it, or button 3 to raise it.");
481 	gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
482 	gtk_widget_show (w);
483 
484 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
485 	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
486 	gtk_widget_show (hbox);
487 
488 	/* Create the canvas */
489 
490 	canvas = goo_canvas_new ();
491 	g_object_set (G_OBJECT (canvas),
492 		      "automatic-bounds", TRUE,
493 		      "bounds-from-origin", FALSE,
494 		      "bounds-padding", 4.0,
495 		      "background-color-rgb", 0xC3C3FF,
496  		      "has-tooltip", TRUE,
497 #if 0
498 		      "redraw-when-scrolled", TRUE,
499 #endif
500 		      NULL);
501 	goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 604, 454);
502 
503 	/* Scale */
504 
505 	w = gtk_label_new ("Scale:");
506 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
507 	gtk_widget_show (w);
508 
509 	adj = GTK_ADJUSTMENT (gtk_adjustment_new (1.00, 0.05, 50.00, 0.05, 0.50, 0.50));
510 	w = gtk_spin_button_new (adj, 0.0, 2);
511 	g_signal_connect (adj, "value_changed",
512 			  G_CALLBACK (zoom_changed),
513 			  canvas);
514 	gtk_widget_set_size_request (w, 50, -1);
515 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
516 	gtk_widget_show (w);
517 
518 
519 	w = gtk_label_new ("Scale X:");
520 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
521 	gtk_widget_show (w);
522 
523 	adj = GTK_ADJUSTMENT (gtk_adjustment_new (1.00, 0.05, 50.00, 0.05, 0.50, 0.50));
524 	w = gtk_spin_button_new (adj, 0.0, 2);
525 	g_signal_connect (adj, "value_changed",
526 			  G_CALLBACK (zoom_x_changed),
527 			  canvas);
528 	gtk_widget_set_size_request (w, 50, -1);
529 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
530 	gtk_widget_show (w);
531 
532 
533 	w = gtk_label_new ("Scale Y:");
534 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
535 	gtk_widget_show (w);
536 
537 	adj = GTK_ADJUSTMENT (gtk_adjustment_new (1.00, 0.05, 50.00, 0.05, 0.50, 0.50));
538 	w = gtk_spin_button_new (adj, 0.0, 2);
539 	g_signal_connect (adj, "value_changed",
540 			  G_CALLBACK (zoom_y_changed),
541 			  canvas);
542 	gtk_widget_set_size_request (w, 50, -1);
543 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
544 	gtk_widget_show (w);
545 
546 
547 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
548 	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
549 	gtk_widget_show (hbox);
550 
551 	/* Center: */
552 
553 	w = gtk_check_button_new_with_label("Center scroll region");
554 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
555 	/*gtk_widget_show (w);*/
556 	g_signal_connect (w, "toggled",
557 			  G_CALLBACK (center_toggled),
558 			  canvas);
559 
560 	/* Move Ellipse */
561 
562 	w = gtk_button_new_with_label("Move Ellipse");
563 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
564 	gtk_widget_show (w);
565 	g_signal_connect (w, "clicked",
566 			  G_CALLBACK (move_ellipse_clicked),
567 			  canvas);
568 
569 	/* Animate Ellipse */
570 
571 	w = gtk_button_new_with_label("Animate Ellipse");
572 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
573 	gtk_widget_show (w);
574 	g_signal_connect (w, "clicked",
575 			  G_CALLBACK (animate_ellipse_clicked),
576 			  canvas);
577 
578 	/* Stop Animation */
579 
580 	w = gtk_button_new_with_label("Stop Animation");
581 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
582 	gtk_widget_show (w);
583 	g_signal_connect (w, "clicked",
584 			  G_CALLBACK (stop_animation_clicked),
585 			  canvas);
586 
587 
588 #if CAIRO_HAS_PDF_SURFACE
589 	/* Create PDF */
590 
591 	w = gtk_button_new_with_label("Write PDF");
592 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
593 	gtk_widget_show (w);
594 	g_signal_connect (w, "clicked",
595 			  G_CALLBACK (write_pdf_clicked),
596 			  canvas);
597 #endif
598 
599 	w = gtk_button_new_with_label("Change Bounds");
600 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
601 	gtk_widget_show (w);
602 	g_signal_connect (w, "clicked",
603 			  G_CALLBACK (change_bounds_clicked),
604 			  canvas);
605 
606 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
607 	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
608 	gtk_widget_show (hbox);
609 
610 	/* Scroll to */
611 
612 	w = gtk_label_new ("Scroll To:");
613 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
614 	gtk_widget_show (w);
615 
616 	w = gtk_button_new_with_label("50,50");
617 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
618 	gtk_widget_show (w);
619 	g_signal_connect (w, "clicked",
620 			  G_CALLBACK (scroll_to_50_50_clicked),
621 			  canvas);
622 
623 	w = gtk_button_new_with_label("250,250");
624 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
625 	gtk_widget_show (w);
626 	g_signal_connect (w, "clicked",
627 			  G_CALLBACK (scroll_to_250_250_clicked),
628 			  canvas);
629 
630 	w = gtk_button_new_with_label("500,500");
631 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
632 	gtk_widget_show (w);
633 	g_signal_connect (w, "clicked",
634 			  G_CALLBACK (scroll_to_500_500_clicked),
635 			  canvas);
636 
637 	/* Scroll anchor */
638 
639 	w = gtk_label_new ("Anchor:");
640 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
641 	gtk_widget_show (w);
642 
643 	w = gtk_radio_button_new_with_label (group, "NW");
644 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
645 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
646 	gtk_widget_show (w);
647 	g_signal_connect (w, "toggled",
648 			  G_CALLBACK (anchor_toggled),
649 			  canvas);
650 	g_object_set_data (G_OBJECT (w), "anchor",
651 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_NW));
652 
653 	w = gtk_radio_button_new_with_label (group, "N");
654 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
655 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
656 	gtk_widget_show (w);
657 	g_signal_connect (w, "toggled",
658 			  G_CALLBACK (anchor_toggled),
659 			  canvas);
660 	g_object_set_data (G_OBJECT (w), "anchor",
661 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_N));
662 
663 	w = gtk_radio_button_new_with_label (group, "NE");
664 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
665 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
666 	gtk_widget_show (w);
667 	g_signal_connect (w, "toggled",
668 			  G_CALLBACK (anchor_toggled),
669 			  canvas);
670 	g_object_set_data (G_OBJECT (w), "anchor",
671 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_NE));
672 
673 	w = gtk_radio_button_new_with_label (group, "W");
674 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
675 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
676 	gtk_widget_show (w);
677 	g_signal_connect (w, "toggled",
678 			  G_CALLBACK (anchor_toggled),
679 			  canvas);
680 	g_object_set_data (G_OBJECT (w), "anchor",
681 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_W));
682 
683 	w = gtk_radio_button_new_with_label (group, "C");
684 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
685 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
686 	gtk_widget_show (w);
687 	g_signal_connect (w, "toggled",
688 			  G_CALLBACK (anchor_toggled),
689 			  canvas);
690 	g_object_set_data (G_OBJECT (w), "anchor",
691 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_CENTER));
692 
693 	w = gtk_radio_button_new_with_label (group, "E");
694 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
695 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
696 	gtk_widget_show (w);
697 	g_signal_connect (w, "toggled",
698 			  G_CALLBACK (anchor_toggled),
699 			  canvas);
700 	g_object_set_data (G_OBJECT (w), "anchor",
701 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_E));
702 
703 	w = gtk_radio_button_new_with_label (group, "SW");
704 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
705 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
706 	gtk_widget_show (w);
707 	g_signal_connect (w, "toggled",
708 			  G_CALLBACK (anchor_toggled),
709 			  canvas);
710 	g_object_set_data (G_OBJECT (w), "anchor",
711 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_SW));
712 
713 	w = gtk_radio_button_new_with_label (group, "S");
714 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
715 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
716 	gtk_widget_show (w);
717 	g_signal_connect (w, "toggled",
718 			  G_CALLBACK (anchor_toggled),
719 			  canvas);
720 	g_object_set_data (G_OBJECT (w), "anchor",
721 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_S));
722 
723 	w = gtk_radio_button_new_with_label (group, "SE");
724 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (w));
725 	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
726 	gtk_widget_show (w);
727 	g_signal_connect (w, "toggled",
728 			  G_CALLBACK (anchor_toggled),
729 			  canvas);
730 	g_object_set_data (G_OBJECT (w), "anchor",
731 			   GINT_TO_POINTER (GOO_CANVAS_ANCHOR_SE));
732 
733 
734 	/* Layout the stuff */
735 
736 	scrolled_win = gtk_scrolled_window_new (NULL, NULL);
737 	gtk_widget_show (scrolled_win);
738 	gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
739 
740 	gtk_widget_show (canvas);
741 	gtk_container_add (GTK_CONTAINER (scrolled_win), canvas);
742 
743 	/* Add all the canvas items. */
744 	setup_canvas (GOO_CANVAS (canvas));
745 
746 #if 0
747 	g_signal_connect_after (canvas, "key_press_event",
748 				G_CALLBACK (key_press),
749 				NULL);
750 
751 	GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
752 	gtk_widget_grab_focus (canvas);
753 #endif
754 
755 	return vbox;
756 }
757 
758 
759 static void
setup_heading(GooCanvasItem * root,char * text,int pos)760 setup_heading (GooCanvasItem *root, char *text, int pos)
761 {
762   double x = (pos % 3) * 200 + 100;
763   double y = (pos / 3) * 150 + 5;
764   GooCanvasItem *item;
765   PangoRectangle ink_rect, logical_rect;
766 
767   item = goo_canvas_text_new (root, text, x, y, -1, GOO_CANVAS_ANCHOR_N,
768 			      "font", "Sans 12",
769 			      NULL);
770   goo_canvas_item_skew_y (item, 30, x, y);
771   /*goo_canvas_item_rotate (item, 30, x, y);*/
772 
773   goo_canvas_text_get_natural_extents (GOO_CANVAS_TEXT (item),
774 				       &ink_rect, &logical_rect);
775   g_print ("Ink Extents: %i,%i %ix%i  Logical: %i,%i %ix%i\n",
776 	   ink_rect.x, ink_rect.y, ink_rect.width, ink_rect.height,
777 	   logical_rect.x, logical_rect.y,
778 	   logical_rect.width, logical_rect.height);
779 }
780 
781 
782 static void
setup_divisions(GooCanvasItem * root)783 setup_divisions (GooCanvasItem *root)
784 {
785   GooCanvasItem *group, *item G_GNUC_UNUSED;
786 
787   group = goo_canvas_group_new (root, NULL);
788   goo_canvas_item_translate (group, 2, 2);
789 
790   item = goo_canvas_rect_new (group, 0, 0, 600, 450,
791 			      "line-width", 4.0,
792 			      NULL);
793 
794   item = goo_canvas_polyline_new_line (group, 0, 150, 600, 150,
795 			      "line-width", 4.0,
796 			      NULL);
797 
798   item = goo_canvas_polyline_new_line (group, 0, 300, 600, 300,
799 			      "line-width", 4.0,
800 			      NULL);
801 
802   item = goo_canvas_polyline_new_line (group, 200, 0, 200, 450,
803 			      "line-width", 4.0,
804 			      NULL);
805 
806   item = goo_canvas_polyline_new_line (group, 400, 0, 400, 450,
807 			      "line-width", 4.0,
808 			      NULL);
809 
810 #if 1
811   setup_heading (group, "Rectangles", 0);
812   setup_heading (group, "Ellipses", 1);
813   setup_heading (group, "Texts", 2);
814   setup_heading (group, "Images", 3);
815   setup_heading (group, "Lines", 4);
816   /*setup_heading (group, "No Curves", 5);*/
817   /*setup_heading (group, "Arcs", 6);*/
818   setup_heading (group, "Polygons", 7);
819   /*setup_heading (group, "Widgets", 8);*/
820 #endif
821 }
822 
823 
824 /* FIXME: I think we may need to check byte order. */
825 static cairo_pattern_t*
create_stipple(const char * color_name,guchar stipple_data[16])826 create_stipple (const char *color_name, guchar stipple_data[16])
827 {
828   cairo_surface_t *surface;
829   cairo_pattern_t *pattern;
830   GdkRGBA color;
831 
832   gdk_rgba_parse (&color, color_name);
833   stipple_data[2] = stipple_data[14] = color.red * 255;
834   stipple_data[1] = stipple_data[13] = color.green * 255;
835   stipple_data[0] = stipple_data[12] = color.blue * 255;
836   surface = cairo_image_surface_create_for_data (stipple_data,
837 						 CAIRO_FORMAT_ARGB32,
838 						 2, 2, 8);
839   pattern = cairo_pattern_create_for_surface (surface);
840   cairo_surface_destroy (surface);
841   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
842 
843   return pattern;
844 }
845 
846 static void
setup_rectangles(GooCanvasItem * root)847 setup_rectangles (GooCanvasItem *root)
848 {
849   GooCanvasItem *item;
850   cairo_pattern_t *pattern;
851   static guchar stipple_data[16] = {
852     0, 0, 0, 255,   0, 0, 0, 0,   0, 0, 0, 0,     0, 0, 0, 255
853   };
854   GooCanvasLineDash *dash;
855 
856   item = goo_canvas_rect_new (root, 20, 30, 50, 30,
857 			      "stroke-color", "red",
858 			      "line-width", 8.0,
859 			      "tooltip", "Red stroked rectangle",
860 			      NULL);
861   setup_item_signals (item);
862 
863   pattern = create_stipple ("mediumseagreen", stipple_data);
864   item = goo_canvas_rect_new (root, 90, 40, 90, 60,
865 			      "fill-pattern", pattern,
866 			      "stroke-color", "black",
867 			      "line-width", 4.0,
868 			      "tooltip", "Medium Sea Green stippled rectangle",
869 			      NULL);
870   cairo_pattern_destroy (pattern);
871   setup_item_signals (item);
872 
873   item = goo_canvas_rect_new (root, 10, 80, 70, 60,
874 			      "fill-color", "steelblue",
875 			      /*"fill-pattern", NULL,*/
876 			      "tooltip", "Steel Blue rectangle",
877 			      NULL);
878   setup_item_signals (item);
879 
880   dash = goo_canvas_line_dash_new (2, 5.0, 2.0);
881   goo_canvas_line_dash_set_offset (dash, 2.0);
882   item = goo_canvas_rect_new (root, 20, 90, 70, 60,
883 			      "fill-color-rgba", 0x3cb37180,
884 			      "line-dash", dash,
885 			      "stroke-color", "blue",
886 			      "line-width", 2.0,
887 			      "tooltip", "Partially transparent rectangle",
888 			      NULL);
889   goo_canvas_line_dash_unref (dash);
890   setup_item_signals (item);
891 
892   item = goo_canvas_rect_new (root, 110, 80, 50, 30,
893 			      "radius-x", 20.0,
894 			      "radius-y", 10.0,
895 			      "stroke-color", "yellow",
896 			      "fill-color-rgba", 0x3cb3f180,
897 			      "tooltip", "Rectangle with rounded corners",
898 			      NULL);
899   setup_item_signals (item);
900 
901   item = goo_demo_item_new (root, 30, 20, 50, 30,
902 			    "fill-color", "yellow",
903 			    "tooltip", "Yellow demo item",
904 			    NULL);
905   setup_item_signals (item);
906 }
907 
908 
909 static void
setup_ellipses(GooCanvasItem * root)910 setup_ellipses (GooCanvasItem *root)
911 {
912   GooCanvasItem *ellipse1, *ellipse3;
913   cairo_pattern_t *pattern;
914   static guchar stipple_data[16] = {
915     0, 0, 0, 255,   0, 0, 0, 0,
916     0, 0, 0, 0,     0, 0, 0, 255
917   };
918 
919 #if 1
920   ellipse1 = goo_canvas_ellipse_new (root, 245, 45, 25, 15,
921 				     "stroke-color", "goldenrod",
922 				     "line-width", 8.0,
923 				     NULL);
924   setup_item_signals (ellipse1);
925 #endif
926 
927   ellipse2 = goo_canvas_ellipse_new (root, 335, 70, 45, 30,
928 				     "fill-color", "wheat",
929 				     "stroke-color", "midnightblue",
930 				     "line-width", 4.0,
931 				     "title", "An ellipse",
932 				     NULL);
933 #if 0
934   goo_canvas_item_rotate (ellipse2, 30, 0, 0);
935 #endif
936   setup_item_signals (ellipse2);
937 
938 #if 1
939   pattern = create_stipple ("cadetblue", stipple_data);
940   ellipse3 = goo_canvas_ellipse_new (root, 245, 110, 35, 30,
941 				     "fill-pattern", pattern,
942 				     "stroke-color", "black",
943 				     "line-width", 1.0,
944 				     NULL);
945   cairo_pattern_destroy (pattern);
946   setup_item_signals (ellipse3);
947 #endif
948 }
949 
950 
951 #define VERTICES 10
952 #define RADIUS 60.0
953 
954 static void
polish_diamond(GooCanvasItem * root)955 polish_diamond (GooCanvasItem *root)
956 {
957   GooCanvasItem *group, *item G_GNUC_UNUSED;
958   int i, j;
959   double a, x1, y1, x2, y2;
960 
961   group = goo_canvas_group_new (root,
962 				"line-width", 1.0,
963 				"line-cap", CAIRO_LINE_CAP_ROUND,
964 				NULL);
965   goo_canvas_item_translate (group, 270, 230);
966   setup_item_signals (group);
967 
968   for (i = 0; i < VERTICES; i++) {
969     a = 2.0 * M_PI * i / VERTICES;
970     x1 = RADIUS * cos (a);
971     y1 = RADIUS * sin (a);
972 
973     for (j = i + 1; j < VERTICES; j++) {
974       a = 2.0 * M_PI * j / VERTICES;
975       x2 = RADIUS * cos (a);
976       y2 = RADIUS * sin (a);
977       item = goo_canvas_polyline_new_line (group, x1, y1, x2, y2, NULL);
978     }
979   }
980 }
981 
982 
983 #define SCALE 7.0
984 
985 static void
make_hilbert(GooCanvasItem * root)986 make_hilbert (GooCanvasItem *root)
987 {
988   char hilbert[] = "urdrrulurulldluuruluurdrurddldrrruluurdrurddldrddlulldrdldrrurd";
989   char *c;
990   double *pp, *p;
991   GooCanvasItem *item;
992   GooCanvasPoints *points;
993   cairo_pattern_t *pattern;
994   static guchar stipple_data[16] = {
995     0, 0, 0, 255,   0, 0, 0, 0,   0, 0, 0, 0,     0, 0, 0, 255
996   };
997 
998   points = goo_canvas_points_new (strlen (hilbert) + 1);
999   points->coords[0] = 340.0;
1000   points->coords[1] = 290.0;
1001 
1002   pp = points->coords;
1003   for (c = hilbert, p = points->coords + 2; *c; c++, p += 2, pp += 2)
1004     switch (*c) {
1005     case 'u':
1006       p[0] = pp[0];
1007       p[1] = pp[1] - SCALE;
1008       break;
1009 
1010     case 'd':
1011       p[0] = pp[0];
1012       p[1] = pp[1] + SCALE;
1013       break;
1014 
1015     case 'l':
1016       p[0] = pp[0] - SCALE;
1017       p[1] = pp[1];
1018       break;
1019 
1020     case 'r':
1021       p[0] = pp[0] + SCALE;
1022       p[1] = pp[1];
1023       break;
1024     }
1025 
1026   pattern = create_stipple ("red", stipple_data);
1027   item = goo_canvas_polyline_new (root, FALSE, 0,
1028 				  "points", points,
1029 				  "line-width", 4.0,
1030 				  "stroke-pattern", pattern,
1031 				  "line-cap", CAIRO_LINE_CAP_SQUARE,
1032 				  "line-join", CAIRO_LINE_JOIN_MITER,
1033 				  NULL);
1034   cairo_pattern_destroy (pattern);
1035   setup_item_signals (item);
1036 
1037   goo_canvas_points_unref (points);
1038 }
1039 
1040 static void
setup_lines(GooCanvasItem * root)1041 setup_lines (GooCanvasItem *root)
1042 {
1043   GooCanvasItem *polyline1, *polyline2, *polyline3, *polyline4, *polyline5;
1044 
1045   polish_diamond (root);
1046   make_hilbert (root);
1047 
1048   /* Arrow tests */
1049 
1050   polyline1 = goo_canvas_polyline_new (root, FALSE, 4,
1051 				       340.0, 170.0,
1052 				       340.0, 230.0,
1053 				       390.0, 230.0,
1054 				       390.0, 170.0,
1055 				       "stroke-color", "midnightblue",
1056 				       "line-width", 3.0,
1057 				       "start-arrow", TRUE,
1058 				       "end-arrow", TRUE,
1059 				       "arrow-tip-length", 3.0,
1060 				       "arrow-length", 4.0,
1061 				       "arrow-width", 3.5,
1062 				       NULL);
1063   setup_item_signals (polyline1);
1064 
1065   polyline2 = goo_canvas_polyline_new (root, FALSE, 2,
1066 				       356.0, 180.0,
1067 				       374.0, 220.0,
1068 				       "stroke-color", "blue",
1069 				       "line-width", 1.0,
1070 				       "start-arrow", TRUE,
1071 				       "end-arrow", TRUE,
1072 				       "arrow-tip-length", 5.0,
1073 				       "arrow-length", 6.0,
1074 				       "arrow-width", 6.0,
1075 				       NULL);
1076   setup_item_signals (polyline2);
1077 
1078   polyline3 = goo_canvas_polyline_new (root, FALSE, 2,
1079 				       356.0, 220.0,
1080 				       374.0, 180.0,
1081 				       "stroke-color", "blue",
1082 				       "line-width", 1.0,
1083 				       "start-arrow", TRUE,
1084 				       "end-arrow", TRUE,
1085 				       "arrow-tip-length", 5.0,
1086 				       "arrow-length", 6.0,
1087 				       "arrow-width", 6.0,
1088 				       NULL);
1089   setup_item_signals (polyline3);
1090 
1091   /* Test polyline without any coords. */
1092   polyline4 = goo_canvas_polyline_new (root, FALSE, 0,
1093 				       NULL);
1094   setup_item_signals (polyline4);
1095 
1096   /* Test polyline with 1 coord and arrows. */
1097   polyline5 = goo_canvas_polyline_new (root, FALSE, 1,
1098 				       356.0, 220.0,
1099 				       "start-arrow", TRUE,
1100 				       "end-arrow", TRUE,
1101 				       NULL);
1102   setup_item_signals (polyline5);
1103 }
1104 
1105 
1106 static void
setup_polygons(GooCanvasItem * root)1107 setup_polygons (GooCanvasItem *root)
1108 {
1109   GooCanvasItem *polyline1, *polyline2;
1110   GooCanvasPoints *points;
1111   cairo_pattern_t *pattern;
1112   static guchar stipple_data[16] = {
1113     0, 0, 0, 255,   0, 0, 0, 0,   0, 0, 0, 0,     0, 0, 0, 255
1114   };
1115 
1116   points = goo_canvas_points_new (3);
1117   points->coords[0] = 210.0;
1118   points->coords[1] = 320.0;
1119   points->coords[2] = 210.0;
1120   points->coords[3] = 380.0;
1121   points->coords[4] = 260.0;
1122   points->coords[5] = 350.0;
1123   pattern = create_stipple ("blue", stipple_data);
1124   polyline1 = goo_canvas_polyline_new (root, TRUE, 0,
1125 				       "line-width", 1.0,
1126 				       "points", points,
1127 				       "fill_pattern", pattern,
1128 				       "stroke_color", "black",
1129 				       NULL);
1130   cairo_pattern_destroy (pattern);
1131   goo_canvas_points_unref (points);
1132   setup_item_signals (polyline1);
1133 
1134 
1135   points = goo_canvas_points_new (14);
1136   points->coords[0] = 270.0;
1137   points->coords[1] = 330.0;
1138   points->coords[2] = 270.0;
1139   points->coords[3] = 430.0;
1140   points->coords[4] = 390.0;
1141   points->coords[5] = 430.0;
1142   points->coords[6] = 390.0;
1143   points->coords[7] = 330.0;
1144   points->coords[8] = 310.0;
1145   points->coords[9] = 330.0;
1146   points->coords[10] = 310.0;
1147   points->coords[11] = 390.0;
1148   points->coords[12] = 350.0;
1149   points->coords[13] = 390.0;
1150   points->coords[14] = 350.0;
1151   points->coords[15] = 370.0;
1152   points->coords[16] = 330.0;
1153   points->coords[17] = 370.0;
1154   points->coords[18] = 330.0;
1155   points->coords[19] = 350.0;
1156   points->coords[20] = 370.0;
1157   points->coords[21] = 350.0;
1158   points->coords[22] = 370.0;
1159   points->coords[23] = 410.0;
1160   points->coords[24] = 290.0;
1161   points->coords[25] = 410.0;
1162   points->coords[26] = 290.0;
1163   points->coords[27] = 330.0;
1164   polyline2 = goo_canvas_polyline_new (root, TRUE, 0,
1165 				       "points", points,
1166 				       "fill_color", "tan",
1167 				       "stroke_color", "black",
1168 				       "line-width", 3.0,
1169 				       NULL);
1170   goo_canvas_points_unref (points);
1171   setup_item_signals (polyline2);
1172 }
1173 
1174 
1175 static GooCanvasItem *
make_anchor(GooCanvasItem * root,double x,double y)1176 make_anchor (GooCanvasItem *root, double x, double y)
1177 {
1178   GooCanvasItem *group, *item;
1179   cairo_matrix_t transform = { 0.8, 0.2, -0.3, 0.5, x, y };
1180 
1181   group = goo_canvas_group_new (root, NULL);
1182   goo_canvas_item_translate (group, x, y);
1183 #if 1
1184   g_object_set (group,
1185 		"transform", &transform,
1186 		NULL);
1187 #endif
1188 
1189   item = goo_canvas_rect_new (group, -2.5, -2.5, 4, 4,
1190 			      "line-width", 1.0,
1191 			      NULL);
1192   setup_item_signals (item);
1193 
1194   g_signal_connect (group, "scroll_event",
1195 		    G_CALLBACK (on_scroll), NULL);
1196 
1197   return group;
1198 }
1199 
1200 static void
setup_texts(GooCanvasItem * root)1201 setup_texts (GooCanvasItem *root)
1202 {
1203   GooCanvasItem *item;
1204   cairo_pattern_t *pattern;
1205   static guchar stipple_data[16] = {
1206     0, 0, 0, 255,   0, 0, 0, 0,   0, 0, 0, 0,     0, 0, 0, 255
1207   };
1208 
1209 #if 1
1210   pattern = create_stipple ("blue", stipple_data);
1211   item = goo_canvas_text_new (make_anchor (root, 420, 20),
1212 			      "Anchor NW", 0, 0, -1, GOO_CANVAS_ANCHOR_NW,
1213 			      "font", "Sans Bold 24",
1214 			      "fill_pattern", pattern,
1215 			      NULL);
1216   cairo_pattern_destroy (pattern);
1217   setup_item_signals (item);
1218 
1219   item = goo_canvas_text_new (make_anchor (root, 470, 75),
1220 			      "Anchor center\nJustify center\nMultiline text\nb8bit text ÅÄÖåäö",
1221 			      0, 0, -1, GOO_CANVAS_ANCHOR_CENTER,
1222 			      "font", "monospace bold 14",
1223 			      "alignment", PANGO_ALIGN_CENTER,
1224 			      "fill_color", "firebrick",
1225 			      NULL);
1226   setup_item_signals (item);
1227 #endif
1228 
1229 #if 0
1230   item = goo_canvas_text_new (make_anchor (root, 590, 140),
1231 			      "Clipped text\nClipped text\nClipped text\nClipped text\nClipped text\nClipped text",
1232 			      0, 0, -1, GOO_CANVAS_ANCHOR_SE,
1233 			      "font", "Sans 12",
1234 			      /*"clip", TRUE,*/
1235 			      /*"clip_width", 50.0,*/
1236 			      /*"clip_height", 55.0,*/
1237 			      /*"x_offset", 10.0,*/
1238 			      "fill_color", "darkgreen",
1239 			      NULL);
1240   setup_item_signals (item);
1241 #endif
1242 
1243 #if 1
1244   textitem = goo_canvas_text_new (make_anchor (root, 420, 240),
1245 				  "This is a very long paragraph that will need to be wrapped over several lines so we can see what happens to line-breaking as the view is zoomed in and out.",
1246 				  0, 0, 180, GOO_CANVAS_ANCHOR_W,
1247 				  "font", "Sans 12",
1248 				  "fill_color", "goldenrod",
1249 				  NULL);
1250   setup_item_signals (textitem);
1251 #endif
1252 
1253 #if 1
1254   textitem = goo_canvas_text_new (root,
1255 				  "Ellipsized text.",
1256 				  20, 420, 115, GOO_CANVAS_ANCHOR_W,
1257 				  "font", "Sans 12",
1258 				  "fill_color", "blue",
1259 				  "ellipsize", PANGO_ELLIPSIZE_END,
1260 				  NULL);
1261   setup_item_signals (textitem);
1262 #endif
1263 }
1264 
1265 
1266 static void
setup_invisible_texts(GooCanvasItem * root)1267 setup_invisible_texts (GooCanvasItem *root)
1268 {
1269   goo_canvas_text_new (root, "Visible above 0.8x", 500, 330, -1,
1270 		       GOO_CANVAS_ANCHOR_CENTER,
1271 		       "visibility", GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD,
1272 		       "visibility-threshold", 0.8,
1273 		       NULL);
1274   goo_canvas_rect_new (root, 410.5, 322.5, 180, 15,
1275 		       "line-width", 1.0,
1276 		       "visibility", GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD,
1277 		       "visibility-threshold", 0.8,
1278 		       NULL);
1279 
1280   goo_canvas_text_new (root, "Visible above 1.5x", 500, 350, -1,
1281 		       GOO_CANVAS_ANCHOR_CENTER,
1282 		       "visibility", GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD,
1283 		       "visibility-threshold", 1.5,
1284 		       NULL);
1285   goo_canvas_rect_new (root, 410.5, 342.5, 180, 15,
1286 		       "line-width", 1.0,
1287 		       "visibility", GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD,
1288 		       "visibility-threshold", 1.5,
1289 		       NULL);
1290 
1291   goo_canvas_text_new (root, "Visible above 3.0x", 500, 370, -1,
1292 		       GOO_CANVAS_ANCHOR_CENTER,
1293 		       "visibility", GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD,
1294 		       "visibility-threshold", 3.0,
1295 		       NULL);
1296   goo_canvas_rect_new (root, 410.5, 362.5, 180, 15,
1297 		       "line-width", 1.0,
1298 		       "visibility", GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD,
1299 		       "visibility-threshold", 3.0,
1300 		       NULL);
1301 
1302   /* This should never be seen. */
1303   goo_canvas_text_new (root, "Always Invisible", 500, 390, -1,
1304 		       GOO_CANVAS_ANCHOR_CENTER,
1305 		       "visibility", GOO_CANVAS_ITEM_INVISIBLE,
1306 		       NULL);
1307   goo_canvas_rect_new (root, 410.5, 350.5, 180, 15,
1308 		       "line-width", 1.0,
1309 		       "visibility", GOO_CANVAS_ITEM_INVISIBLE,
1310 		       NULL);
1311 }
1312 
1313 
1314 static void
plant_flower(GooCanvasItem * root,double x,double y,GooCanvasAnchorType anchor,gdouble opacity)1315 plant_flower (GooCanvasItem *root, double x, double y, GooCanvasAnchorType anchor, gdouble opacity)
1316 {
1317   cairo_pattern_t *pattern;
1318   cairo_surface_t *surface;
1319   GooCanvasItem *image;
1320   double w, h;
1321 
1322   surface = cairo_image_surface_create_from_png ("flower.png");
1323   w = cairo_image_surface_get_width (surface);
1324   h = cairo_image_surface_get_height (surface);
1325 
1326   pattern = cairo_pattern_create_for_surface (surface);
1327   cairo_surface_destroy (surface);
1328 
1329   image = goo_canvas_image_new (root, NULL, x, y,
1330 			       "pattern", pattern,
1331 			       "width", w * 1.5,
1332 			       "height", h * 2,
1333 				"scale-to-fit", TRUE,
1334 				"alpha", opacity,
1335 			       NULL);
1336   cairo_pattern_destroy (pattern);
1337   setup_item_signals (image);
1338 }
1339 
1340 static void
setup_images(GooCanvasItem * root)1341 setup_images (GooCanvasItem *root)
1342 {
1343   GdkPixbuf *im;
1344   GooCanvasItem *image;
1345 
1346   im = gdk_pixbuf_new_from_file ("toroid.png", NULL);
1347 
1348   if (im)
1349     {
1350       double w = gdk_pixbuf_get_width (im);
1351       double h = gdk_pixbuf_get_height (im);
1352       image = goo_canvas_image_new (root, im, 100.0 - w / 2, 225.0 - h / 2,
1353 				   "width", w,
1354 				   "height", h,
1355 				   /* "anchor", GOO_CANVAS_ANCHOR_CENTER, */
1356 				   NULL);
1357       g_object_unref(im);
1358       setup_item_signals (image);
1359     }
1360   else
1361     g_warning ("Could not find the toroid.png sample file");
1362 
1363   plant_flower (root,  20.0, 170.0, GOO_CANVAS_ANCHOR_NW, 0.3);
1364   plant_flower (root, 180.0, 170.0, GOO_CANVAS_ANCHOR_NE, 0.5);
1365   plant_flower (root,  20.0, 280.0, GOO_CANVAS_ANCHOR_SW, 0.7);
1366   plant_flower (root, 180.0, 280.0, GOO_CANVAS_ANCHOR_SE, 1.0);
1367 }
1368 
1369 
1370 static void
setup_static_items(GooCanvas * canvas)1371 setup_static_items (GooCanvas *canvas)
1372 {
1373   GooCanvasItem *static_root, *group, *item;
1374 
1375   static_root = goo_canvas_get_static_root_item (canvas);
1376 
1377   /* All static items in one place in the canvas should be placed in the same
1378      group. */
1379   group = goo_canvas_group_new (static_root, NULL);
1380 
1381   item = goo_canvas_polyline_new_line (group,
1382 				       40.0, 410.0,
1383 				       40.0, 330.0,
1384 				       "stroke-color", "midnightblue",
1385 				       "line-width", 3.0,
1386 				       "end-arrow", TRUE,
1387 				       "arrow-tip-length", 3.0,
1388 				       "arrow-length", 4.0,
1389 				       "arrow-width", 3.5,
1390 				       NULL);
1391   setup_item_signals (item);
1392 
1393   item = goo_canvas_polyline_new_line (group,
1394 				       32.0, 370.0,
1395 				       48.0, 370.0,
1396 				       "stroke-color", "midnightblue",
1397 				       "line-width", 3.0,
1398 				       NULL);
1399   setup_item_signals (item);
1400 
1401   item = goo_canvas_text_new (group, "N", 40, 320, -1, GOO_CANVAS_ANCHOR_S,
1402 			      "font", "Sans 12",
1403 			      NULL);
1404   setup_item_signals (item);
1405 }
1406 
1407 
1408 /* This checks that the rgba color properties work properly, i.e. the value
1409    written to them is the same when read back out. */
1410 static void
test_color_properties(GooCanvasItem * root)1411 test_color_properties (GooCanvasItem *root)
1412 {
1413 #if 0
1414   GooCanvasItem *item;
1415   guint red, green, blue, alpha, rgba_in, rgba_out;
1416 
1417   item = goo_canvas_rect_new (root, 20, 30, 50, 30,
1418 			      NULL);
1419 
1420   for (red = 0; red < 256; red += 15)
1421     {
1422       for (green = 0; green < 256; green += 15)
1423 	{
1424 	  for (blue = 0; blue < 256; blue ++)
1425 	    {
1426 	      for (alpha = 0; alpha < 256; alpha += 15)
1427 		{
1428 		  rgba_in = (red << 24) + (green << 16) + (blue << 8) + alpha;
1429 		  g_object_set (item, "fill_color_rgba", rgba_in, NULL);
1430 		  rgba_out = 0;
1431 		  g_object_get (item, "fill_color_rgba", &rgba_out, NULL);
1432 
1433 		  if (rgba_in != rgba_out)
1434 		    g_print ("ERROR: rgba in: %.8X out: %.8X\n", rgba_in, rgba_out);
1435 		}
1436 	    }
1437 	}
1438     }
1439 #endif
1440 }
1441 
1442 static void
test_simple_transforms(GooCanvasItem * root)1443 test_simple_transforms (GooCanvasItem *root)
1444 {
1445 #if 0
1446   GooCanvasItem *item;
1447   int rotation, x, y;
1448   double scale, x_out, y_out, scale_out, rotation_out, max_error = 0.0000001;
1449 
1450   item = goo_canvas_rect_new (root, 20, 30, 50, 30,
1451 			      NULL);
1452 
1453   for (rotation = 0; rotation < 360; rotation += 20)
1454     {
1455       scale = 0.1;
1456       while (scale < 10)
1457 	{
1458 	  g_print ("Rotation: %i Scale: %g\n", rotation, scale);
1459 
1460 	  for (x = -100; x < 100; x += 10)
1461 	    {
1462 	      for (y = -100; y < 100; y += 10)
1463 		{
1464 		  goo_canvas_item_set_simple_transform (item, x, y, scale,
1465 							rotation);
1466 
1467 		  goo_canvas_item_get_simple_transform (item, &x_out, &y_out,
1468 							&scale_out,
1469 							&rotation_out);
1470 
1471 		  if (fabs (x_out - x) > max_error
1472 		      || fabs (y_out - y) > max_error
1473 		      || fabs (scale_out - scale) > max_error
1474 		      || fabs (rotation_out - rotation) > max_error)
1475 		    {
1476 		      g_print ("IN X:%i Y:%i Scale:%g Rotation:%i -> %g, %g, %g, %g\n", x, y, scale, rotation, x_out, y_out, scale_out, rotation_out);
1477 		    }
1478 		}
1479 	    }
1480 	  scale += 0.1;
1481 	}
1482     }
1483 #endif
1484 }
1485 
1486 
1487 static void
setup_grids(GooCanvasItem * root)1488 setup_grids (GooCanvasItem *root)
1489 {
1490   GooCanvasItem *item G_GNUC_UNUSED;
1491 
1492   item = goo_canvas_grid_new (root, 80, 310, 90, 90, 10, 10, 5, 5,
1493 			      "stroke-color", "yellow",
1494 			      "fill-color", "pink",
1495 			      "border-width", 2.0,
1496 			      "border-color", "red",
1497 			      "vert-grid-line-color", "lightblue",
1498 			      "horz-grid-line-width", 1.0,
1499 			      "vert-grid-line-width", 1.0,
1500 			      "vert-grid-lines-on-top", TRUE,
1501 			      NULL);
1502 }
1503 
1504 
1505 static void
setup_canvas(GooCanvas * canvas)1506 setup_canvas (GooCanvas *canvas)
1507 {
1508   GooCanvasItem *root;
1509 
1510   root = goo_canvas_get_root_item (canvas);
1511   g_signal_connect (root, "button_press_event",
1512 		    G_CALLBACK (on_background_button_press), NULL);
1513 
1514   /* Setup canvas items */
1515 #if 1
1516   setup_divisions (root);
1517   setup_rectangles (root);
1518   setup_ellipses (root);
1519   setup_lines (root);
1520   setup_polygons (root);
1521   setup_texts (root);
1522   setup_images (root);
1523   setup_invisible_texts (root);
1524   setup_static_items (canvas);
1525   setup_grids (root);
1526 #endif
1527 
1528   test_color_properties (root);
1529   test_simple_transforms (root);
1530 }
1531 
1532 
1533 static gboolean
on_delete_event(GtkWidget * window,GdkEvent * event,gpointer unused_data)1534 on_delete_event (GtkWidget *window,
1535 		 GdkEvent *event,
1536 		 gpointer unused_data)
1537 {
1538   gtk_main_quit ();
1539   return FALSE;
1540 }
1541 
1542 
1543 static GtkWidget*
create_window()1544 create_window ()
1545 {
1546   GtkWidget *window, *notebook;
1547 
1548   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1549   gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
1550   gtk_widget_show (window);
1551   g_signal_connect (window, "delete_event", G_CALLBACK (on_delete_event),
1552 		    NULL);
1553 
1554   notebook = gtk_notebook_new ();
1555   gtk_widget_show (notebook);
1556   gtk_container_add (GTK_CONTAINER (window), notebook);
1557 
1558 #if 1
1559   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1560 			    create_canvas_primitives (),
1561 			    gtk_label_new ("Primitives"));
1562 #endif
1563 #if 1
1564   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1565 			    create_canvas_arrowhead (),
1566 			    gtk_label_new ("Arrowhead"));
1567 #endif
1568 #if 1
1569   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1570 			    create_canvas_fifteen (),
1571 			    gtk_label_new ("Fifteen"));
1572 #endif
1573 #if 1
1574   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1575 			    create_canvas_features (),
1576 			    gtk_label_new ("Reparent"));
1577 #endif
1578 #if 1
1579   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1580 			    create_canvas_scalability (),
1581 			    gtk_label_new ("Scalability"));
1582 #endif
1583 #if 1
1584   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1585 			    create_grabs_page (),
1586 			    gtk_label_new ("Grabs"));
1587 #endif
1588 #if 1
1589   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1590 			    create_events_page (),
1591 			    gtk_label_new ("Events"));
1592 #endif
1593 #if 1
1594   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1595 			    create_paths_page (),
1596 			    gtk_label_new ("Paths"));
1597 #endif
1598 #if 1
1599   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1600 			    create_focus_page (),
1601 			    gtk_label_new ("Focus"));
1602 #endif
1603 #if 1
1604   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1605 			    create_animation_page (),
1606 			    gtk_label_new ("Animation"));
1607 #endif
1608 #if 1
1609   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1610 			    create_clipping_page (),
1611 			    gtk_label_new ("Clipping"));
1612 #endif
1613 #if 1
1614   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1615 			    create_table_page (),
1616 			    gtk_label_new ("Table"));
1617 #endif
1618 #if 1
1619   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1620 			    create_large_items_page (),
1621 			    gtk_label_new ("Large Items"));
1622 #endif
1623 
1624   return window;
1625 }
1626 
1627 
1628 int
main(int argc,char * argv[])1629 main (int argc, char *argv[])
1630 {
1631   GtkWidget *window G_GNUC_UNUSED;
1632 
1633   gtk_init (&argc, &argv);
1634 
1635   window = create_window ();
1636 
1637   gtk_main ();
1638   return 0;
1639 }
1640