1 /* This file is part of Ganv.
2  * Copyright 2007-2015 David Robillard <http://drobilla.net>
3  *
4  * Ganv is free software: you can redistribute it and/or modify it under the
5  * terms of the GNU General Public License as published by the Free Software
6  * Foundation, either version 3 of the License, or any later version.
7  *
8  * Ganv is distributed in the hope that it will be useful, but WITHOUT ANY
9  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
11  *
12  * You should have received a copy of the GNU General Public License along
13  * with Ganv.  If not, see <http://www.gnu.org/licenses/>.
14  */
15 
16 #ifndef GANV_CANVAS_H
17 #define GANV_CANVAS_H
18 
19 #include "ganv/item.h"
20 #include "ganv/types.h"
21 
22 #include <cairo.h>
23 #include <gdk/gdk.h>
24 #include <glib-object.h>
25 #include <glib.h>
26 #include <gtk/gtk.h>
27 
28 G_BEGIN_DECLS
29 
30 #define GANV_TYPE_CANVAS            (ganv_canvas_get_type())
31 #define GANV_CANVAS(obj)            (GTK_CHECK_CAST((obj), GANV_TYPE_CANVAS, GanvCanvas))
32 #define GANV_CANVAS_CLASS(klass)    (GTK_CHECK_CLASS_CAST((klass), GANV_TYPE_CANVAS, GanvCanvasClass))
33 #define GANV_IS_CANVAS(obj)         (GTK_CHECK_TYPE((obj), GANV_TYPE_CANVAS))
34 #define GANV_IS_CANVAS_CLASS(klass) (GTK_CHECK_CLASS_TYPE((klass), GANV_TYPE_CANVAS))
35 #define GANV_CANVAS_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS((obj), GANV_TYPE_CANVAS, GanvCanvasClass))
36 
37 struct _GanvCanvasClass;
38 
39 typedef struct GanvCanvasImpl   GanvCanvasPrivate;
40 typedef struct _GanvCanvasClass GanvCanvasClass;
41 
42 /**
43  * GanvDirection:
44  * @GANV_DIRECTION_DOWN: Signal flows from top to bottom.
45  * @GANV_DIRECTION_RIGHT: Signal flows from left to right.
46  *
47  * Specifies the direction of signal flow on the canvas, which affects the
48  * appearance of modules and how the canvas is auto-arranged.
49  */
50 typedef enum {
51 	GANV_DIRECTION_DOWN,
52 	GANV_DIRECTION_RIGHT
53 } GanvDirection;
54 
55 struct _GanvCanvas {
56 	GtkLayout          layout;
57 	GanvCanvasPrivate* impl;
58 };
59 
60 struct _GanvCanvasClass {
61 	GtkLayoutClass parent_class;
62 
63 	/* Reserved for future expansion */
64 	gpointer spare_vmethods[4];
65 };
66 
67 GType ganv_canvas_get_type(void) G_GNUC_CONST;
68 
69 /**
70  * GanvEdgeFunc:
71  * @edge: Canvas edge.
72  * @data: User callback data.
73  *
74  * A node function that takes a user data argument (for callbacks).
75  *
76  * Note that in the Gtk world it is considered safe to cast a function to a
77  * function with more arguments and call the resulting pointer, so functions
78  * like ganv_edge_select can safely be used where a GanvEdgeFunc is expected.
79  */
80 typedef void (*GanvEdgeFunc)(GanvEdge* edge, void* data);
81 
82 /**
83  * GanvNodeFunc:
84  * @node: Canvas node.
85  * @data: User callback data.
86  *
87  * A node function that takes a user data argument (for callbacks).
88  *
89  * Note that in the Gtk world it is considered safe to cast a function to a
90  * function with more arguments and call the resulting pointer, so functions
91  * like ganv_node_select can safely be used where a GanvNodeFunc is expected.
92  */
93 typedef void (*GanvNodeFunc)(GanvNode* node, void* data);
94 
95 typedef int (*GanvPortOrderFunc)(const GanvPort*, const GanvPort*, void* data);
96 
97 /**
98  * ganv_canvas_new:
99  *
100  * Return value: A newly-created canvas.
101  */
102 GanvCanvas*
103 ganv_canvas_new(double width, double height);
104 
105 /**
106  * ganv_canvas_set_wrapper:
107  *
108  * Set the opaque wrapper object for the canvas.
109  */
110 void
111 ganv_canvas_set_wrapper(GanvCanvas* canvas, void* wrapper);
112 
113 /**
114  * ganv_canvas_get_wrapper:
115  *
116  * Return an opaque pointer to the wrapper for the canvas.
117  */
118 void*
119 ganv_canvas_get_wrapper(GanvCanvas* canvas);
120 
121 /**
122  * ganv_canvas_clear:
123  *
124  * Remove all items from the canvas.
125  */
126 void
127 ganv_canvas_clear(GanvCanvas* canvas);
128 
129 /**
130  * ganv_canvas_empty:
131  *
132  * Return value: True if there are no items on the canvas.
133  */
134 gboolean
135 ganv_canvas_empty(const GanvCanvas* canvas);
136 
137 /**
138  * ganv_canvas_get_size:
139  *
140  * Gets the width and height of the canvas.
141  */
142 void
143 ganv_canvas_get_size(GanvCanvas* canvas, double* width, double* height);
144 
145 /**
146  * ganv_canvas_resize:
147  *
148  * Resize the canvas to the given dimensions.
149  */
150 void
151 ganv_canvas_resize(GanvCanvas* canvas, double width, double height);
152 
153 /**
154  * ganv_canvas_root:
155  * @canvas: A canvas.
156  *
157  * Return value: (transfer none): The root group of the canvas.
158  */
159 GanvItem*
160 ganv_canvas_root(GanvCanvas* canvas);
161 
162 /**
163  * ganv_canvas_set_scroll_region:
164  * @canvas: A canvas.
165  * @x1: Leftmost limit of the scrolling region.
166  * @y1: Upper limit of the scrolling region.
167  * @x2: Rightmost limit of the scrolling region.
168  * @y2: Lower limit of the scrolling region.
169  *
170  * Sets the scrolling region of a canvas to the specified rectangle.  The
171  * canvas will then be able to scroll only within this region.  The view of the
172  * canvas is adjusted as appropriate to display as much of the new region as
173  * possible.
174  */
175 void
176 ganv_canvas_set_scroll_region(GanvCanvas* canvas,
177                               double x1, double y1, double x2, double y2);
178 
179 /**
180  * ganv_canvas_get_scroll_region:
181  * @canvas: A canvas.
182  * @x1: Leftmost limit of the scrolling region (return value).
183  * @y1: Upper limit of the scrolling region (return value).
184  * @x2: Rightmost limit of the scrolling region (return value).
185  * @y2: Lower limit of the scrolling region (return value).
186  *
187  * Queries the scrolling region of a canvas.
188  */
189 void
190 ganv_canvas_get_scroll_region(GanvCanvas* canvas,
191                               double* x1, double* y1, double* x2, double* y2);
192 
193 /**
194  * ganv_canvas_set_center_scroll_region:
195  * @canvas: A canvas.
196  * @center_scroll_region: Whether to center the scrolling region in the canvas
197  * window when it is smaller than the canvas' allocation.
198  *
199  * When the scrolling region of the canvas is smaller than the canvas window,
200  * e.g.  the allocation of the canvas, it can be either centered on the window
201  * or simply made to be on the upper-left corner on the window.  This function
202  * lets you configure this property.
203  */
204 void
205 ganv_canvas_set_center_scroll_region(GanvCanvas* canvas,
206                                      gboolean    center_scroll_region);
207 
208 /**
209  * ganv_canvas_get_center_scroll_region:
210  * @canvas: A canvas.
211  *
212  * Returns whether the canvas is set to center the scrolling region in the
213  * window if the former is smaller than the canvas' allocation.
214  *
215  * Returns: Whether the scroll region is being centered in the canvas window.
216  */
217 gboolean
218 ganv_canvas_get_center_scroll_region(const GanvCanvas* canvas);
219 
220 /**
221  * ganv_canvas_scroll_to:
222  * @canvas: A canvas.
223  * @cx: Horizontal scrolling offset in canvas pixel units.
224  * @cy: Vertical scrolling offset in canvas pixel units.
225  *
226  * Makes a canvas scroll to the specified offsets, given in canvas pixel units.
227  * The canvas will adjust the view so that it is not outside the scrolling
228  * region.  This function is typically not used, as it is better to hook
229  * scrollbars to the canvas layout's scrolling adjusments.
230  */
231 void
232 ganv_canvas_scroll_to(GanvCanvas* canvas, int cx, int cy);
233 
234 /**
235  * ganv_canvas_get_scroll_offsets:
236  * @canvas: A canvas.
237  * @cx: Horizontal scrolling offset (return value).
238  * @cy: Vertical scrolling offset (return value).
239  *
240  * Queries the scrolling offsets of a canvas.  The values are returned in canvas
241  * pixel units.
242  */
243 void
244 ganv_canvas_get_scroll_offsets(const GanvCanvas* canvas, int* cx, int* cy);
245 
246 /**
247  * ganv_canvas_w2c_affine:
248  * @canvas: A canvas.
249  * @matrix: An affine transformation matrix (return value).
250  *
251  * Gets the affine transform that converts from world coordinates to canvas
252  * pixel coordinates.
253  */
254 void
255 ganv_canvas_w2c_affine(GanvCanvas* canvas, cairo_matrix_t* matrix);
256 
257 /**
258  * ganv_canvas_w2c:
259  * @canvas: A canvas.
260  * @wx: World X coordinate.
261  * @wy: World Y coordinate.
262  * @cx: X pixel coordinate (return value).
263  * @cy: Y pixel coordinate (return value).
264  *
265  * Converts world coordinates into canvas pixel coordinates.
266  */
267 void
268 ganv_canvas_w2c(GanvCanvas* canvas, double wx, double wy, int* cx, int* cy);
269 
270 /**
271  * ganv_canvas_w2c_d:
272  * @canvas: A canvas.
273  * @wx: World X coordinate.
274  * @wy: World Y coordinate.
275  * @cx: X pixel coordinate (return value).
276  * @cy: Y pixel coordinate (return value).
277  *
278  * Converts world coordinates into canvas pixel coordinates.  This version
279  * uses floating point coordinates for greater precision.
280  */
281 void
282 ganv_canvas_w2c_d(GanvCanvas* canvas,
283                   double      wx,
284                   double      wy,
285                   double*     cx,
286                   double*     cy);
287 
288 /**
289  * ganv_canvas_c2w:
290  * @canvas: A canvas.
291  * @cx: Canvas pixel X coordinate.
292  * @cy: Canvas pixel Y coordinate.
293  * @wx: X world coordinate (return value).
294  * @wy: Y world coordinate (return value).
295  *
296  * Converts canvas pixel coordinates to world coordinates.
297  */
298 void
299 ganv_canvas_c2w(GanvCanvas* canvas, int cx, int cy, double* wx, double* wy);
300 
301 /**
302  * ganv_canvas_window_to_world:
303  * @canvas: A canvas.
304  * @winx: Window-relative X coordinate.
305  * @winy: Window-relative Y coordinate.
306  * @worldx: X world coordinate (return value).
307  * @worldy: Y world coordinate (return value).
308  *
309  * Converts window-relative coordinates into world coordinates.  You can use
310  * this when you need to convert mouse coordinates into world coordinates, for
311  * example.
312  */
313 void
314 ganv_canvas_window_to_world(GanvCanvas* canvas,
315                             double      winx,
316                             double      winy,
317                             double*     worldx,
318                             double*     worldy);
319 
320 /**
321  * ganv_canvas_world_to_window:
322  * @canvas: A canvas.
323  * @worldx: World X coordinate.
324  * @worldy: World Y coordinate.
325  * @winx: X window-relative coordinate.
326  * @winy: Y window-relative coordinate.
327  *
328  * Converts world coordinates into window-relative coordinates.
329  */
330 void
331 ganv_canvas_world_to_window(GanvCanvas* canvas,
332                             double      worldx,
333                             double      worldy,
334                             double*     winx,
335                             double*     winy);
336 
337 /**
338  * ganv_canvas_get_item_at:
339  * @canvas: A canvas.
340  * @x: X position in world coordinates.
341  * @y: Y position in world coordinates.
342  *
343  * Looks for the item that is under the specified position, which must be
344  * specified in world coordinates.
345  *
346  * Returns: (transfer none): The sought item, or NULL if no item is at the
347  * specified coordinates.
348  */
349 GanvItem*
350 ganv_canvas_get_item_at(GanvCanvas* canvas, double x, double y);
351 
352 /**
353  * ganv_canvas_get_edge:
354  *
355  * Get the edge between two nodes, or NULL if none exists.
356  *
357  * Return value: (transfer none): The root group of @canvas.
358  */
359 GanvEdge*
360 ganv_canvas_get_edge(GanvCanvas* canvas,
361                      GanvNode*   tail,
362                      GanvNode*   head);
363 
364 /**
365  * ganv_canvas_remove_edge:
366  *
367  * Remove @edge from the canvas.
368  */
369 void
370 ganv_canvas_remove_edge(GanvCanvas* canvas,
371                         GanvEdge*   edge);
372 
373 /**
374  * ganv_canvas_remove_edge_between:
375  *
376  * Remove the edge from @tail to @head if one exists.
377  */
378 void
379 ganv_canvas_remove_edge_between(GanvCanvas* canvas,
380                                 GanvNode*   tail,
381                                 GanvNode*   head);
382 
383 /**
384  * ganv_canvas_get_direction:
385  *
386  * Return the direction of signal flow.
387  */
388 GanvDirection
389 ganv_canvas_get_direction(GanvCanvas* canvas);
390 
391 /**
392  * ganv_canvas_set_direction:
393  *
394  * Set the direction of signal flow.
395  */
396 void
397 ganv_canvas_set_direction(GanvCanvas* canvas, GanvDirection dir);
398 
399 /**
400  * ganv_canvas_arrange:
401  *
402  * Automatically arrange the canvas contents.
403  */
404 void
405 ganv_canvas_arrange(GanvCanvas* canvas);
406 
407 /**
408  * ganv_canvas_export_image:
409  *
410  * Draw the canvas to an image file.  The file type is determined by extension,
411  * currently supported: pdf, ps, svg, dot.
412  *
413  * Returns: 0 on success.
414  */
415 int
416 ganv_canvas_export_image(GanvCanvas* canvas,
417                          const char* filename,
418                          gboolean    draw_background);
419 
420 /**
421  * ganv_canvas_export_dot:
422  *
423  * Write a Graphviz DOT description of the canvas to a file.
424  */
425 void
426 ganv_canvas_export_dot(GanvCanvas* canvas, const char* filename);
427 
428 /**
429  * ganv_canvas_supports_sprung_layout:
430  *
431  * Returns: true iff ganv is compiled with sprung layout support.
432  */
433 gboolean
434 ganv_canvas_supports_sprung_layout(const GanvCanvas* canvas);
435 
436 /**
437  * ganv_canvas_set_sprung_layout:
438  *
439  * Enable or disable "live" force-directed canvas layout.
440  *
441  * Returns: true iff sprung layout was enabled.
442  */
443 gboolean
444 ganv_canvas_set_sprung_layout(GanvCanvas* canvas, gboolean sprung_layout);
445 
446 /**
447  * ganv_canvas_get_locked:
448  *
449  * Return true iff the canvas is locked and nodes may not move.
450  */
451 gboolean
452 ganv_canvas_get_locked(const GanvCanvas* canvas);
453 
454 /**
455  * ganv_canvas_for_each_node:
456  * @canvas: The canvas.
457  * @f: (scope call): A function to call on every node on @canvas.
458  * @data: Data to pass to @f.
459  */
460 void
461 ganv_canvas_for_each_node(GanvCanvas*  canvas,
462                           GanvNodeFunc f,
463                           void*        data);
464 
465 /**
466  * ganv_canvas_for_each_selected_node:
467  * @canvas: The canvas.
468  * @f: (scope call): A function to call on every selected node on @canvas.
469  * @data: Data to pass to @f.
470  */
471 void
472 ganv_canvas_for_each_selected_node(GanvCanvas*  canvas,
473                                    GanvNodeFunc f,
474                                    void*        data);
475 
476 /**
477  * ganv_canvas_for_each_edge:
478  * @canvas: The canvas.
479  * @f: (scope call): A function to call on every edge on @canvas.
480  * @data: Data to pass to @f.
481  */
482 void
483 ganv_canvas_for_each_edge(GanvCanvas*  canvas,
484                           GanvEdgeFunc f,
485                           void*        data);
486 
487 /**
488  * ganv_canvas_for_each_edge_from:
489  * @canvas: The canvas.
490  * @tail: The tail to enumerate every edge for.
491  * @f: (scope call): A function to call on every edge leaving @tail.
492  */
493 void
494 ganv_canvas_for_each_edge_from(GanvCanvas*     canvas,
495                                const GanvNode* tail,
496                                GanvEdgeFunc    f,
497                                void*           data);
498 
499 /**
500  * ganv_canvas_for_each_edge_to:
501  * @canvas: The canvas.
502  * @head: The head to enumerate every edge for.
503  * @f: (scope call): A function to call on every edge entering @head.
504  */
505 void
506 ganv_canvas_for_each_edge_to(GanvCanvas*     canvas,
507                              const GanvNode* head,
508                              GanvEdgeFunc    f,
509                              void*           data);
510 
511 /**
512  * ganv_canvas_for_each_edge_on:
513  * @canvas: The canvas.
514  * @node: The node to enumerate every edge for.
515  * @f: (scope call): A function to call on every edge attached to @node.
516  */
517 void
518 ganv_canvas_for_each_edge_on(GanvCanvas*     canvas,
519                              const GanvNode* node,
520                              GanvEdgeFunc    f,
521                              void*           data);
522 
523 /**
524  * ganv_canvas_for_each_selected_edge:
525  * @canvas: The canvas.
526  * @f: (scope call): A function to call on every edge attached to @node.
527  * @data: Data to pass to @f.
528  */
529 void
530 ganv_canvas_for_each_selected_edge(GanvCanvas*  canvas,
531                                    GanvEdgeFunc f,
532                                    void*        data);
533 
534 /**
535  * ganv_canvas_select_all:
536  *
537  * Select all items on the canvas.
538  */
539 void
540 ganv_canvas_select_all(GanvCanvas* canvas);
541 
542 /**
543  * ganv_canvas_clear_selection:
544  *
545  * Deselect any selected items on the canvas.
546  */
547 void
548 ganv_canvas_clear_selection(GanvCanvas* canvas);
549 
550 /**
551  * ganv_canvas_get_zoom:
552  *
553  * Return the current zoom factor (pixels per unit).
554  */
555 double
556 ganv_canvas_get_zoom(const GanvCanvas* canvas);
557 
558 /**
559  * ganv_canvas_set_zoom:
560  * @canvas: A canvas.
561  * @zoom: The number of pixels that correspond to one canvas unit.
562  *
563  * The anchor point for zooming, i.e. the point that stays fixed and all others
564  * zoom inwards or outwards from it, depends on whether the canvas is set to
565  * center the scrolling region or not.  You can control this using the
566  * ganv_canvas_set_center_scroll_region() function.  If the canvas is set to
567  * center the scroll region, then the center of the canvas window is used as
568  * the anchor point for zooming.  Otherwise, the upper-left corner of the
569  * canvas window is used as the anchor point.
570  */
571 void
572 ganv_canvas_set_zoom(GanvCanvas* canvas, double zoom);
573 
574 /**
575  * ganv_canvas_zoom_full:
576  *
577  * Zoom so all canvas contents are visible.
578  */
579 void
580 ganv_canvas_zoom_full(GanvCanvas* canvas);
581 
582 /**
583  * ganv_canvas_get_default_font_size:
584  *
585  * Get the default font size in points.
586  */
587 double
588 ganv_canvas_get_default_font_size(const GanvCanvas* canvas);
589 
590 /**
591  * ganv_canvas_get_font_size:
592  *
593  * Get the current font size in points.
594  */
595 double
596 ganv_canvas_get_font_size(const GanvCanvas* canvas);
597 
598 /**
599  * ganv_canvas_set_font_size:
600  *
601  * Set the current font size in points.
602  */
603 void
604 ganv_canvas_set_font_size(GanvCanvas* canvas, double points);
605 
606 /**
607  * ganv_canvas_get_move_cursor:
608  *
609  * Return the cursor to use while dragging canvas objects.
610  */
611 GdkCursor*
612 ganv_canvas_get_move_cursor(const GanvCanvas* canvas);
613 
614 /**
615  * ganv_canvas_move_contents_to:
616  *
617  * Shift all canvas contents so the top-left object is at (x, y).
618  */
619 void
620 ganv_canvas_move_contents_to(GanvCanvas* canvas, double x, double y);
621 
622 /**
623  * ganv_canvas_set_port_order:
624  * @canvas The canvas to set the default port order on.
625  * @port_cmp Port comparison function.
626  * @data Data to be passed to order.
627  *
628  * Set a comparator function to use as the default order for ports on modules.
629  * If left unset, ports are shown in the order they are added.
630  */
631 void
632 ganv_canvas_set_port_order(GanvCanvas*       canvas,
633                            GanvPortOrderFunc port_cmp,
634                            void*             data);
635 
636 
637 G_END_DECLS
638 
639 #endif  /* GANV_CANVAS_H */
640