diff options
-rw-r--r-- | ganv/Box.hpp | 5 | ||||
-rw-r--r-- | ganv/Canvas.hpp | 73 | ||||
-rw-r--r-- | ganv/Edge.hpp | 8 | ||||
-rw-r--r-- | ganv/Item.hpp | 19 | ||||
-rw-r--r-- | ganv/Module.hpp | 6 | ||||
-rw-r--r-- | ganv/Node.hpp | 20 | ||||
-rw-r--r-- | ganv/box.h | 2 | ||||
-rw-r--r-- | ganv/canvas.h | 129 | ||||
-rw-r--r-- | ganv/circle.h | 17 | ||||
-rw-r--r-- | ganv/edge.h | 19 | ||||
-rw-r--r-- | ganv/group.h | 10 | ||||
-rw-r--r-- | ganv/item.h | 30 | ||||
-rw-r--r-- | ganv/module.h | 12 | ||||
-rw-r--r-- | ganv/node.h | 49 | ||||
-rw-r--r-- | ganv/port.h | 6 | ||||
-rw-r--r-- | ganv/text.h | 2 | ||||
-rw-r--r-- | ganv/widget.h | 18 | ||||
-rw-r--r-- | ganv/wrap.hpp | 10 | ||||
-rw-r--r-- | src/Canvas.cpp | 169 | ||||
-rw-r--r-- | src/boilerplate.h | 2 | ||||
-rw-r--r-- | src/box.c | 6 | ||||
-rw-r--r-- | src/circle.c | 71 | ||||
-rw-r--r-- | src/edge.c | 62 | ||||
-rw-r--r-- | src/ganv-private.h | 91 | ||||
-rw-r--r-- | src/group.c | 93 | ||||
-rw-r--r-- | src/item.c | 130 | ||||
-rw-r--r-- | src/module.c | 14 | ||||
-rw-r--r-- | src/node.c | 108 | ||||
-rw-r--r-- | src/port.c | 30 | ||||
-rw-r--r-- | src/text.c | 12 | ||||
-rw-r--r-- | src/widget.c | 173 |
31 files changed, 782 insertions, 614 deletions
diff --git a/ganv/Box.hpp b/ganv/Box.hpp index 6d75d23..aa88f0e 100644 --- a/ganv/Box.hpp +++ b/ganv/Box.hpp @@ -30,10 +30,15 @@ public: RW_PROPERTY(const char*, label); + METHODRET0(ganv_box, double, get_x1) + METHODRET0(ganv_box, double, get_y1) + METHODRET0(ganv_box, double, get_x2) + METHODRET0(ganv_box, double, get_y2) METHODRET0(ganv_box, double, get_width) METHOD1(ganv_box, set_width, double, width) METHODRET0(ganv_box, double, get_height) METHOD1(ganv_box, set_height, double, height) + METHODRET0(ganv_box, double, get_border_width) GanvBox* gobj() { return GANV_BOX(_gobj); } const GanvBox* gobj() const { return GANV_BOX(_gobj); } diff --git a/ganv/Canvas.hpp b/ganv/Canvas.hpp index 2139e93..88211d4 100644 --- a/ganv/Canvas.hpp +++ b/ganv/Canvas.hpp @@ -34,6 +34,7 @@ GANV_GLIB_WRAP(Canvas) namespace Ganv { class Edge; +class Item; class Node; class Port; @@ -55,42 +56,64 @@ public: Canvas(double width, double height); virtual ~Canvas(); + GanvItem* root() { return ganv_canvas_root(gobj()); } + METHOD0(ganv_canvas, clear); - METHOD0(ganv_canvas, clear_selection); - METHOD0(ganv_canvas, select_all); - METHODRET0(ganv_canvas, double, get_zoom); - METHOD1(ganv_canvas, set_zoom, double, pix_per_unit); - METHOD1(ganv_canvas, set_font_size, double, points); - METHOD0(ganv_canvas, zoom_full); - METHODRET0(ganv_canvas, double, get_font_size) - METHODRET0(ganv_canvas, double, get_default_font_size) - METHOD1(ganv_canvas, export_dot, const char*, filename); - METHOD0(ganv_canvas, arrange); - METHOD2(ganv_canvas, move_contents_to, double, x, double, y); + METHODRET0(ganv_canvas, gboolean, empty) METHOD2(ganv_canvas, resize, double, width, double, height); + METHOD4(ganv_canvas, set_scroll_region, double, x1, double, y1, double, x2, double, y2); + METHOD4(ganv_canvas, get_scroll_region, double*, x1, double*, y1, double*, x2, double*, y2); + METHOD1(ganv_canvas, set_center_scroll_region, gboolean, c); + METHODRET0(ganv_canvas, gboolean, get_center_scroll_region); + METHOD2(ganv_canvas, scroll_to, int, x, int, y); + + void get_scroll_offsets(int& cx, int& cy) const { + ganv_canvas_get_scroll_offsets(gobj(), &cx, &cy); + } + + METHOD1(ganv_canvas, w2c_affine, cairo_matrix_t*, matrix); + METHOD4(ganv_canvas, w2c, double, wx, double, wy, int*, cx, int*, cy); + METHOD4(ganv_canvas, w2c_d, double, wx, double, wy, double*, cx, double*, cy); + METHOD4(ganv_canvas, c2w, int, cx, int, cy, double*, wx, double*, wy); + METHOD4(ganv_canvas, window_to_world, double, winx, double, winy, double*, worldx, double*, worldy); + METHOD4(ganv_canvas, world_to_window, double, worldx, double, worldy, double*, winx, double*, winy); + + Item* get_item_at(double x, double y) const; + Edge* get_edge(Node* tail, Node* head) const; + void remove_edge_between(Node* tail, Node* head); + void remove_edge(Edge* edge); + + METHOD0(ganv_canvas, arrange); + METHOD1(ganv_canvas, export_dot, const char*, filename); + METHODRET0(ganv_canvas, gboolean, supports_sprung_layout); + METHODRET1(ganv_canvas, gboolean, set_sprung_layout, gboolean, sprung_layout); METHOD2(ganv_canvas, for_each_node, GanvNodeFunc, f, void*, data) METHOD2(ganv_canvas, for_each_selected_node, GanvNodeFunc, f, void*, data) METHOD2(ganv_canvas, for_each_edge, GanvEdgeFunc, f, void*, data) - METHOD2(ganv_canvas, for_each_selected_edge, GanvEdgeFunc, f, void*, data) - METHODRET0(ganv_canvas, gboolean, empty) - METHOD2(ganv_canvas, scroll_to, int, x, int, y); - METHOD3(ganv_canvas, for_each_edge_from, const GanvNode*, tail, GanvEdgeFunc, f, void*, data); - METHOD3(ganv_canvas, for_each_edge_to, const GanvNode*, head, GanvEdgeFunc, f, void*, data); - METHOD3(ganv_canvas, for_each_edge_on, const GanvNode*, node, GanvEdgeFunc, f, void*, data); + METHOD2(ganv_canvas, for_each_selected_edge, GanvEdgeFunc, f, void*, data) + METHOD0(ganv_canvas, select_all); + METHOD0(ganv_canvas, clear_selection); + METHODRET0(ganv_canvas, double, get_zoom); + METHOD1(ganv_canvas, set_zoom, double, pix_per_unit); + METHOD0(ganv_canvas, zoom_full); + METHODRET0(ganv_canvas, double, get_default_font_size) + METHODRET0(ganv_canvas, double, get_font_size) + METHOD1(ganv_canvas, set_font_size, double, points); METHOD0(ganv_canvas, get_move_cursor); + METHOD2(ganv_canvas, move_contents_to, double, x, double, y); RW_PROPERTY(gboolean, locked); RW_PROPERTY(double, width) @@ -101,24 +124,8 @@ public: return *Glib::wrap(&_gobj->layout); } - /** Get the edge from @c tail to @c head if one exists. */ - Edge* get_edge(Node* tail, Node* head) const; - - /** Delete the edge from @c tail to @c head. */ - void remove_edge(Node* tail, Node* head); - - void remove_edge(Edge* edge); - - void get_scroll_offsets(int& cx, int& cy) const { - ganv_canvas_get_scroll_offsets(gobj(), &cx, &cy); - } - GQuark wrapper_key(); - GanvItem* root() { - return ganv_canvas_root(gobj()); - } - GanvCanvas* gobj() { return GANV_CANVAS(_gobj); } const GanvCanvas* gobj() const { return GANV_CANVAS(_gobj); } diff --git a/ganv/Edge.hpp b/ganv/Edge.hpp index e220d95..350a617 100644 --- a/ganv/Edge.hpp +++ b/ganv/Edge.hpp @@ -61,14 +61,12 @@ public: {} virtual ~Edge() { - if (_gobj && _gobj->parent) { + if (_gobj && ganv_item_get_parent(_gobj)) { g_object_unref(_gobj); } } - /** Return true iff the handle is within the given rectangle. */ - virtual gboolean is_within(double x1, double y1, - double x2, double y2) const { + gboolean is_within(double x1, double y1, double x2, double y2) const { return ganv_edge_is_within(gobj(), x1, y1, x2, y2); } @@ -81,8 +79,6 @@ public: METHODRETWRAP0(ganv_edge, Node*, get_tail); METHODRETWRAP0(ganv_edge, Node*, get_head); - METHOD1(ganv_edge, tick, double, seconds); - GanvEdge* gobj() { return (GanvEdge*)_gobj; } const GanvEdge* gobj() const { return (GanvEdge*)_gobj; } diff --git a/ganv/Item.hpp b/ganv/Item.hpp index 2ba4de0..fb2667d 100644 --- a/ganv/Item.hpp +++ b/ganv/Item.hpp @@ -27,6 +27,8 @@ #include "ganv/item.h" #include "ganv/wrap.hpp" +GANV_GLIB_WRAP(Item) + namespace Ganv { class Canvas; @@ -39,7 +41,7 @@ public: : _gobj(gobj) { GQuark wrapper_key = g_quark_from_string("ganvmm"); - if (gobj && gobj->parent) { + if (gobj && ganv_item_get_parent(gobj)) { g_object_set_qdata(G_OBJECT(_gobj), wrapper_key, this); g_signal_connect( G_OBJECT(_gobj), "event", G_CALLBACK(on_item_event), this); @@ -53,18 +55,17 @@ public: RW_PROPERTY(double, x) RW_PROPERTY(double, y) + METHOD0(ganv_item, raise); + METHOD0(ganv_item, lower); + METHOD2(ganv_item, move, double, dx, double, dy); METHOD0(ganv_item, show); METHOD0(ganv_item, hide); - METHOD2(ganv_item, move, double, dx, double, dy); - - GanvItem* property_parent() const { - GanvItem* parent; - g_object_get(G_OBJECT(_gobj), "parent", &parent, NULL); - return parent; - } + METHOD2(ganv_item, i2w, double*, x, double*, y); + METHOD2(ganv_item, w2i, double*, x, double*, y); + METHOD0(ganv_item, grab_focus); Canvas* canvas() const { - return Glib::wrap(GANV_CANVAS(_gobj->canvas)); + return Glib::wrap(ganv_item_get_canvas(_gobj)); } GanvItem* gobj() const { return _gobj; } diff --git a/ganv/Module.hpp b/ganv/Module.hpp index 21deb91..ef73621 100644 --- a/ganv/Module.hpp +++ b/ganv/Module.hpp @@ -105,11 +105,7 @@ public: const_iterator back() const { return iterator(const_cast<GanvModule*>(gobj()), num_ports() - 1); } void embed(Gtk::Widget* widget) { - if (widget) { - ganv_module_embed(gobj(), widget->gobj()); - } else { - ganv_module_embed(gobj(), NULL); - } + ganv_module_embed(gobj(), widget ? widget->gobj() : NULL); } Port* get_port(guint index) { diff --git a/ganv/Node.hpp b/ganv/Node.hpp index 9a3e56b..a6f47e8 100644 --- a/ganv/Node.hpp +++ b/ganv/Node.hpp @@ -44,15 +44,20 @@ public: g_object_unref(_gobj); } + RW_PROPERTY(gboolean, can_tail) + RW_PROPERTY(gboolean, can_head) + RW_PROPERTY(gboolean, is_source) + + gboolean is_within(double x1, double y1, double x2, double y2) const { + return ganv_node_is_within(gobj(), x1, y1, x2, y2); + } + RW_PROPERTY(const char*, label) + RW_PROPERTY(double, border_width) RW_PROPERTY(double, dash_length) RW_PROPERTY(double, dash_offset) - RW_PROPERTY(double, border_width) RW_PROPERTY(guint, fill_color) RW_PROPERTY(guint, border_color) - RW_PROPERTY(gboolean, can_tail) - RW_PROPERTY(gboolean, can_head) - RW_PROPERTY(gboolean, is_source) RW_PROPERTY(gboolean, selected) RW_PROPERTY(gboolean, highlighted) RW_PROPERTY(gboolean, draggable) @@ -60,13 +65,6 @@ public: RW_OBJECT_PROPERTY(Node*, partner); - METHOD1(ganv_node, tick, double, seconds); - - virtual gboolean is_within(double x1, double y1, - double x2, double y2) const { - return ganv_node_is_within(gobj(), x1, y1, x2, y2); - } - GanvNode* gobj() { return GANV_NODE(_gobj); } const GanvNode* gobj() const { return GANV_NODE(_gobj); } @@ -50,7 +50,7 @@ struct _GanvBoxClass { double height); /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_box_get_type(void) G_GNUC_CONST; diff --git a/ganv/canvas.h b/ganv/canvas.h index a3444dc..02219c1 100644 --- a/ganv/canvas.h +++ b/ganv/canvas.h @@ -60,7 +60,7 @@ struct _GanvCanvasClass { GtkLayoutClass parent_class; /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_canvas_get_type(void) G_GNUC_CONST; @@ -94,6 +94,28 @@ GanvCanvas* ganv_canvas_new(double width, double height); /** + * ganv_canvas_clear: + * Remove all items from the canvas. + */ +void +ganv_canvas_clear(GanvCanvas* canvas); + +/** + * ganv_canvas_empty: + * + * Return value: True if there are no items on the canvas. + */ +gboolean +ganv_canvas_empty(const GanvCanvas* canvas); + +/** + * ganv_canvas_resize: + * Resize the canvas to the given dimensions. + */ +void +ganv_canvas_resize(GanvCanvas* canvas, double width, double height); + +/** * ganv_canvas_root: * @canvas: A canvas. * @@ -158,7 +180,7 @@ ganv_canvas_set_center_scroll_region(GanvCanvas* canvas, * Returns: Whether the scroll region is being centered in the canvas window. */ gboolean -ganv_canvas_get_center_scroll_region(GanvCanvas* canvas); +ganv_canvas_get_center_scroll_region(const GanvCanvas* canvas); /** * ganv_canvas_scroll_to: @@ -187,21 +209,6 @@ void ganv_canvas_get_scroll_offsets(const GanvCanvas* canvas, int* cx, int* cy); /** - * ganv_canvas_get_item_at: - * @canvas: A canvas. - * @x: X position in world coordinates. - * @y: Y position in world coordinates. - * - * Looks for the item that is under the specified position, which must be - * specified in world coordinates. - * - * Returns: (transfer none): The sought item, or NULL if no item is at the - * specified coordinates. - */ -GanvItem* -ganv_canvas_get_item_at(GanvCanvas* canvas, double x, double y); - -/** * ganv_canvas_w2c_affine: * @canvas: A canvas. * @matrix: An affine transformation matrix (return value). @@ -293,11 +300,19 @@ ganv_canvas_world_to_window(GanvCanvas* canvas, double* winy); /** - * ganv_canvas_resize: - * Resize the canvas to the given dimensions. + * ganv_canvas_get_item_at: + * @canvas: A canvas. + * @x: X position in world coordinates. + * @y: Y position in world coordinates. + * + * Looks for the item that is under the specified position, which must be + * specified in world coordinates. + * + * Returns: (transfer none): The sought item, or NULL if no item is at the + * specified coordinates. */ -void -ganv_canvas_resize(GanvCanvas* canvas, double width, double height); +GanvItem* +ganv_canvas_get_item_at(GanvCanvas* canvas, double x, double y); /** * ganv_canvas_get_edge: @@ -311,6 +326,15 @@ ganv_canvas_get_edge(GanvCanvas* canvas, GanvNode* head); /** + * ganv_canvas_remove_edge: + * + * Remove @edge from the canvas. + */ +void +ganv_canvas_remove_edge(GanvCanvas* canvas, + GanvEdge* edge); + +/** * ganv_canvas_remove_edge_between: * * Remove the edge from @tail to @head if one exists. @@ -321,14 +345,6 @@ ganv_canvas_remove_edge_between(GanvCanvas* canvas, GanvNode* head); /** - * ganv_canvas_get_default_font_size: - * - * Get the default font size in points. - */ -double -ganv_canvas_get_default_font_size(const GanvCanvas* canvas); - -/** * ganv_canvas_get_direction: * * Return the direction of signal flow. @@ -345,14 +361,6 @@ void ganv_canvas_set_direction(GanvCanvas* canvas, GanvDirection dir); /** - * ganv_canvas_clear_selection: - * - * Deselect any selected items on the canvas. - */ -void -ganv_canvas_clear_selection(GanvCanvas* canvas); - -/** * ganv_canvas_arrange: * * Automatically arrange the canvas contents. @@ -374,7 +382,7 @@ ganv_canvas_export_dot(GanvCanvas* canvas, const char* filename); * Returns: true iff ganv is compiled with sprung layout support. */ gboolean -ganv_canvas_supports_sprung_layout(GanvCanvas* canvas); +ganv_canvas_supports_sprung_layout(const GanvCanvas* canvas); /** * ganv_canvas_set_sprung_layout: @@ -392,7 +400,7 @@ ganv_canvas_set_sprung_layout(GanvCanvas* canvas, gboolean sprung_layout); * Return true iff the canvas is locked and nodes may not move. */ gboolean -ganv_canvas_get_locked(GanvCanvas* canvas); +ganv_canvas_get_locked(const GanvCanvas* canvas); /** * ganv_canvas_for_each_node: @@ -417,14 +425,6 @@ ganv_canvas_for_each_selected_node(GanvCanvas* canvas, void* data); /** - * ganv_canvas_empty: - * - * Return value: True if there are no items on the canvas. - */ -gboolean -ganv_canvas_empty(const GanvCanvas* canvas); - -/** * ganv_canvas_for_each_edge: * @canvas: The canvas. * @f: (scope call): A function to call on every edge on @canvas. @@ -483,18 +483,19 @@ ganv_canvas_for_each_selected_edge(GanvCanvas* canvas, void* data); /** - * ganv_canvas_clear: - * Remove all items from the canvas. + * ganv_canvas_select_all: + * Select all items on the canvas. */ void -ganv_canvas_clear(GanvCanvas* canvas); +ganv_canvas_select_all(GanvCanvas* canvas); /** - * ganv_canvas_select_all: - * Select all items on the canvas. + * ganv_canvas_clear_selection: + * + * Deselect any selected items on the canvas. */ void -ganv_canvas_select_all(GanvCanvas* canvas); +ganv_canvas_clear_selection(GanvCanvas* canvas); /** * ganv_canvas_get_zoom: @@ -520,6 +521,21 @@ void ganv_canvas_set_zoom(GanvCanvas* canvas, double zoom); /** + * ganv_canvas_zoom_full: + * Zoom so all canvas contents are visible. + */ +void +ganv_canvas_zoom_full(GanvCanvas* canvas); + +/** + * ganv_canvas_get_default_font_size: + * + * Get the default font size in points. + */ +double +ganv_canvas_get_default_font_size(const GanvCanvas* canvas); + +/** * ganv_canvas_get_font_size: * Get the current font size in points. */ @@ -534,13 +550,6 @@ void ganv_canvas_set_font_size(GanvCanvas* canvas, double points); /** - * ganv_canvas_zoom_full: - * Zoom so all canvas contents are visible. - */ -void -ganv_canvas_zoom_full(GanvCanvas* canvas); - -/** * ganv_canvas_get_move_cursor: * Return the cursor to use while dragging canvas objects. */ diff --git a/ganv/circle.h b/ganv/circle.h index 859bb29..bf562b9 100644 --- a/ganv/circle.h +++ b/ganv/circle.h @@ -46,7 +46,7 @@ struct _GanvCircleClass { GanvNodeClass parent_class; /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_circle_get_type(void) G_GNUC_CONST; @@ -58,6 +58,21 @@ ganv_circle_new(GanvCanvas* canvas, double ganv_circle_get_radius(const GanvCircle* circle); +void +ganv_circle_set_radius(GanvCircle* circle, double radius); + +double +ganv_circle_get_radius_ems(const GanvCircle* circle); + +void +ganv_circle_set_radius_ems(GanvCircle* circle, double radius); + +gboolean +ganv_circle_get_fit_label(const GanvCircle* circle); + +void +ganv_circle_set_fit_label(GanvCircle* circle, gboolean fit_label); + G_END_DECLS #endif /* GANV_CIRCLE_H */ diff --git a/ganv/edge.h b/ganv/edge.h index d5c0c59..c36e0ed 100644 --- a/ganv/edge.h +++ b/ganv/edge.h @@ -41,7 +41,7 @@ struct _GanvEdgeClass { GanvItemClass parent_class; /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_edge_get_type(void) G_GNUC_CONST; @@ -59,20 +59,23 @@ ganv_edge_is_within(const GanvEdge* edge, double x2, double y2); +gboolean +ganv_edge_get_curved(const GanvEdge* edge); + void -ganv_edge_update_location(GanvEdge* edge); +ganv_edge_set_curved(GanvEdge* edge, gboolean curved); void -ganv_edge_select(GanvEdge* edge); +ganv_edge_set_selected(GanvEdge* edge, gboolean selected); void -ganv_edge_unselect(GanvEdge* edge); +ganv_edge_set_highlighted(GanvEdge* edge, gboolean highlighted); void -ganv_edge_highlight(GanvEdge* edge); +ganv_edge_select(GanvEdge* edge); void -ganv_edge_unhighlight(GanvEdge* edge); +ganv_edge_unselect(GanvEdge* edge); /** * ganv_edge_disconnect: @@ -91,10 +94,6 @@ ganv_edge_disconnect(GanvEdge* edge); void ganv_edge_remove(GanvEdge* edge); -void -ganv_edge_tick(GanvEdge* edge, - double seconds); - /** * ganv_edge_get_tail: * diff --git a/ganv/group.h b/ganv/group.h index 0d77ee6..1979d6f 100644 --- a/ganv/group.h +++ b/ganv/group.h @@ -33,21 +33,19 @@ G_BEGIN_DECLS #define GANV_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GANV_TYPE_GROUP, GanvGroupClass)) typedef struct _GanvGroup GanvGroup; +typedef struct _GanvGroupImpl GanvGroupImpl; typedef struct _GanvGroupClass GanvGroupClass; struct _GanvGroup { - GanvItem item; - - /* Children of the group */ - GList* item_list; - GList* item_list_end; + GanvItem item; + GanvGroupImpl* impl; }; struct _GanvGroupClass { GanvItemClass parent_class; /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_group_get_type(void) G_GNUC_CONST; diff --git a/ganv/item.h b/ganv/item.h index 83b5f3c..3e57662 100644 --- a/ganv/item.h +++ b/ganv/item.h @@ -28,7 +28,10 @@ G_BEGIN_DECLS +struct _GanvCanvas; + typedef struct _GanvItem GanvItem; +typedef struct _GanvItemImpl GanvItemImpl; typedef struct _GanvItemClass GanvItemClass; /* Object flags for items */ @@ -49,25 +52,8 @@ enum { #define GANV_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GANV_TYPE_ITEM, GanvItemClass)) struct _GanvItem { - GtkObject object; - - /* Parent canvas for this item */ - struct _GanvCanvas* canvas; - - /* Parent for this item */ - GanvItem* parent; - - /* Layer (z order), higher values are on top */ - guint layer; - - /* Position in parent-relative coordinates. */ - double x, y; - - /* Bounding box for this item (in world coordinates) */ - double x1, y1, x2, y2; - - /* True if parent manages this item (don't call add/remove) */ - gboolean managed; + GtkObject object; + GanvItemImpl* impl; }; struct _GanvItemClass { @@ -136,7 +122,7 @@ struct _GanvItemClass { gboolean (*event)(GanvItem* item, GdkEvent* event); /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_item_get_type(void) G_GNUC_CONST; @@ -152,6 +138,10 @@ void ganv_item_set(GanvItem* item, const gchar* first_arg_name, ...); void ganv_item_set_valist(GanvItem* item, const gchar* first_arg_name, va_list args); +struct _GanvCanvas* ganv_item_get_canvas(GanvItem* item); + +GanvItem* ganv_item_get_parent(GanvItem* item); + void ganv_item_raise(GanvItem* item); void ganv_item_lower(GanvItem* item); diff --git a/ganv/module.h b/ganv/module.h index 3ee94b5..4eab012 100644 --- a/ganv/module.h +++ b/ganv/module.h @@ -44,7 +44,7 @@ struct _GanvModuleClass { GanvBoxClass parent_class; /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_module_get_type(void) G_GNUC_CONST; @@ -73,16 +73,10 @@ double ganv_module_get_empty_port_depth(const GanvModule* module); void -ganv_module_set_icon(GanvModule* module, - GdkPixbuf* icon); +ganv_module_embed(GanvModule* module, GtkWidget* widget); void -ganv_module_embed(GanvModule* module, - GtkWidget* widget); - -void -ganv_module_set_direction(GanvModule* module, - GanvDirection direction); +ganv_module_set_direction(GanvModule* module, GanvDirection direction); /** * ganv_module_for_each_port: diff --git a/ganv/node.h b/ganv/node.h index 583d608..2784937 100644 --- a/ganv/node.h +++ b/ganv/node.h @@ -78,7 +78,7 @@ struct _GanvNodeClass { double* dy); /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_node_get_type(void) G_GNUC_CONST; @@ -119,44 +119,27 @@ ganv_node_is_within(const GanvNode* node, double x2, double y2); -void -ganv_node_tick(GanvNode* self, - double seconds); +const char* ganv_node_get_label(const GanvNode* node); -void -ganv_node_tail_vector(const GanvNode* self, - const GanvNode* head, - double* x1, - double* y1, - double* x2, - double* y2); +double ganv_node_get_border_width(const GanvNode* node); -void -ganv_node_head_vector(const GanvNode* self, - const GanvNode* tail, - double* x1, - double* y1, - double* x2, - double* y2); +void ganv_node_set_border_width(const GanvNode* node, double border_width); -/** - * ganv_node_get_draw_properties: - * - * Get the colours that should currently be used for drawing this node. Note - * these may not be identical to the property values because of highlighting - * and selection. - */ -void -ganv_node_get_draw_properties(const GanvNode* node, - double* dash_length, - double* border_color, - double* fill_color); +double ganv_node_get_dash_length(const GanvNode* node); -const char* ganv_node_get_label(const GanvNode* node); +void ganv_node_set_dash_length(const GanvNode* node, double dash_length); -double ganv_node_get_border_width(const GanvNode* node); +double ganv_node_get_dash_offset(const GanvNode* node); -double ganv_node_get_dash_length(const GanvNode* node); +void ganv_node_set_dash_offset(const GanvNode* node, double dash_offset); + +guint ganv_node_get_fill_color(const GanvNode* node); + +void ganv_node_set_fill_color(const GanvNode* node, guint fill_color); + +guint ganv_node_get_border_color(const GanvNode* node); + +void ganv_node_set_border_color(const GanvNode* node, guint border_color); /** * ganv_node_get_partner: diff --git a/ganv/port.h b/ganv/port.h index a4c43ef..3b04db5 100644 --- a/ganv/port.h +++ b/ganv/port.h @@ -41,7 +41,7 @@ struct _GanvPortClass { GanvBoxClass parent_class; /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethods[4]; }; GType ganv_port_get_type(void) G_GNUC_CONST; @@ -52,10 +52,6 @@ ganv_port_new(GanvModule* module, const char* first_prop_name, ...); void -ganv_port_set_direction(GanvPort* port, - GanvDirection direction); - -void ganv_port_set_value_label(GanvPort* port, const char* str); diff --git a/ganv/text.h b/ganv/text.h index 7429fcc..96a95c0 100644 --- a/ganv/text.h +++ b/ganv/text.h @@ -40,7 +40,7 @@ struct _GanvTextClass { GanvItemClass parent_class; /* Reserved for future expansion */ - gpointer spare_vmethods [4]; + gpointer spare_vmethodsx[4]; }; GType ganv_text_get_type(void) G_GNUC_CONST; diff --git a/ganv/widget.h b/ganv/widget.h index f9134ce..d3d63d1 100644 --- a/ganv/widget.h +++ b/ganv/widget.h @@ -32,24 +32,12 @@ G_BEGIN_DECLS #define GANV_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GANV_TYPE_WIDGET, GanvWidgetClass)) typedef struct _GanvWidget GanvWidget; +typedef struct _GanvWidgetImpl GanvWidgetImpl; typedef struct _GanvWidgetClass GanvWidgetClass; struct _GanvWidget { - GanvItem item; - - GtkWidget* widget; /* The child widget */ - - double x, y; /* Position at anchor */ - double width, height; /* Dimensions of widget */ - GtkAnchorType anchor; /* Anchor side for widget */ - - int cx, cy; /* Top-left canvas coordinates for widget */ - int cwidth, cheight; /* Size of widget in pixels */ - - guint destroy_id; /* Signal connection id for destruction of child widget */ - - guint size_pixels : 1; /* Is size specified in (unchanging) pixels or units (get scaled)? */ - guint in_destroy : 1; /* Is child widget being destroyed? */ + GanvItem item; + GanvWidgetImpl* impl; }; struct _GanvWidgetClass { diff --git a/ganv/wrap.hpp b/ganv/wrap.hpp index d0cdfa4..f4f2e9c 100644 --- a/ganv/wrap.hpp +++ b/ganv/wrap.hpp @@ -71,6 +71,11 @@ private: \ return prefix##_##name(gobj()); \ } +#define METHODRET1(prefix, ret, name, t1, a1) \ + virtual ret name(t1 a1) { \ + return prefix##_##name(gobj(), a1); \ + } + #define METHODRETWRAP0(prefix, ret, name) \ virtual ret name() const { \ if (gobj()) { \ @@ -90,6 +95,11 @@ private: \ prefix##_##name(gobj(), a1, a2, a3); \ } +#define METHOD4(prefix, name, t1, a1, t2, a2, t3, a3, t4, a4) \ + virtual void name(t1 a1, t2 a2, t3 a3, t4 a4) { \ + prefix##_##name(gobj(), a1, a2, a3, a4); \ + } + #define GANV_GLIB_WRAP(Name) \ namespace Ganv { \ class Name; \ diff --git a/src/Canvas.cpp b/src/Canvas.cpp index 7e4fec3..5e0605b 100644 --- a/src/Canvas.cpp +++ b/src/Canvas.cpp @@ -195,8 +195,8 @@ struct GanvCanvasImpl { , _select_start_y(0.0) , _drag_state(NOT_DRAGGING) { - this->root = GANV_ITEM(g_object_new(ganv_group_get_type(), NULL)); - this->root->canvas = canvas; + this->root = GANV_ITEM(g_object_new(ganv_group_get_type(), NULL)); + this->root->impl->canvas = canvas; g_object_ref_sink(this->root); this->direction = GANV_DIRECTION_RIGHT; @@ -514,7 +514,7 @@ select_if_head_is_selected(GanvEdge* edge, void* data) } if (selected) { - ganv_edge_select(edge); + ganv_edge_set_selected(edge, TRUE); } } @@ -774,8 +774,8 @@ get_region(GanvNode* node) ganv_item_get_bounds(item, ®.pos.x, ®.pos.y, ®.area.x, ®.area.y); reg.area.x = x2 - x1; reg.area.y = y2 - y1; - reg.pos.x = item->x + (reg.area.x / 2.0); - reg.pos.y = item->y + (reg.area.y / 2.0); + reg.pos.x = item->impl->x + (reg.area.x / 2.0); + reg.pos.y = item->impl->y + (reg.area.y / 2.0); // No need for i2w here since we only care about top-level items return reg; @@ -923,19 +923,19 @@ GanvCanvasImpl::layout_calculate(double dur, bool update) // Update position GanvItem* item = &node->item; - const double x0 = item->x; - const double y0 = item->y; + const double x0 = item->impl->x; + const double y0 = item->impl->y; const Vector dpos = vec_mult(node->impl->vel, dur); - item->x = std::max(MIN_COORD, item->x + dpos.x); - item->y = std::max(MIN_COORD, item->y + dpos.y); + item->impl->x = std::max(MIN_COORD, item->impl->x + dpos.x); + item->impl->y = std::max(MIN_COORD, item->impl->y + dpos.y); if (update) { ganv_item_request_update(item); - item->canvas->impl->need_repick = TRUE; + item->impl->canvas->impl->need_repick = TRUE; } - if (lrint(x0) != lrint(item->x) || lrint(y0) != lrint(item->y)) { + if (lrint(x0) != lrint(item->impl->x) || lrint(y0) != lrint(item->impl->y)) { ++n_moved; } } @@ -1073,7 +1073,7 @@ GanvCanvasImpl::get_node_at(double x, double y) if (GANV_IS_NODE(item)) { return GANV_NODE(item); } else { - item = item->parent; + item = item->impl->parent; } } @@ -1698,7 +1698,7 @@ Canvas::~Canvas() } void -Canvas::remove_edge(Node* item1, Node* item2) +Canvas::remove_edge_between(Node* item1, Node* item2) { GanvEdge* edge = ganv_canvas_get_edge(_gobj, item1->gobj(), item2->gobj()); if (edge) { @@ -1712,15 +1712,24 @@ Canvas::remove_edge(Edge* edge) ganv_canvas_remove_edge(_gobj, edge->gobj()); } +Item* +Canvas::get_item_at(double x, double y) const +{ + GanvItem* item = ganv_canvas_get_item_at(_gobj, x, y); + if (item) { + return Glib::wrap(item); + } + return NULL; +} + Edge* Canvas::get_edge(Node* tail, Node* head) const { GanvEdge* e = ganv_canvas_get_edge(_gobj, tail->gobj(), head->gobj()); if (e) { return Glib::wrap(e); - } else { - return NULL; } + return NULL; } GQuark @@ -1766,7 +1775,7 @@ ganv_canvas_init(GanvCanvas* canvas) canvas->impl = new GanvCanvasImpl(canvas); - g_signal_connect(G_OBJECT(ganv_canvas_root(GANV_CANVAS(canvas))), + g_signal_connect(G_OBJECT(ganv_canvas_root(canvas)), "event", G_CALLBACK(on_canvas_event), canvas->impl); } @@ -1839,6 +1848,8 @@ ganv_canvas_class_init(GanvCanvasClass* klass) canvas_parent_class = GTK_LAYOUT_CLASS(g_type_class_peek_parent(klass)); + g_type_class_add_private(klass, sizeof(GanvCanvasImpl)); + gobject_class->set_property = ganv_canvas_set_property; gobject_class->get_property = ganv_canvas_get_property; @@ -1951,8 +1962,7 @@ ganv_canvas_resize(GanvCanvas* canvas, double width, double height) if (width != canvas->impl->width || height != canvas->impl->height) { canvas->impl->width = width; canvas->impl->height = height; - ganv_canvas_set_scroll_region( - GANV_CANVAS(canvas), 0.0, 0.0, width, height); + ganv_canvas_set_scroll_region(canvas, 0.0, 0.0, width, height); } } @@ -2049,7 +2059,7 @@ ganv_canvas_zoom_full(GanvCanvas* canvas) int win_width, win_height; GdkWindow* win = gtk_widget_get_window( - GTK_WIDGET(GANV_CANVAS(canvas->impl->_gcanvas))); + GTK_WIDGET(canvas->impl->_gcanvas)); gdk_window_get_size(win, &win_width, &win_height); // Box containing all canvas items @@ -2060,8 +2070,8 @@ ganv_canvas_zoom_full(GanvCanvas* canvas) FOREACH_ITEM(canvas->impl->_items, i) { GanvItem* const item = GANV_ITEM(*i); - const double x = item->x; - const double y = item->y; + const double x = item->impl->x; + const double y = item->impl->y; if (GANV_IS_CIRCLE(*i)) { const double r = GANV_CIRCLE(*i)->impl->coords.radius; left = MIN(left, x - r); @@ -2085,11 +2095,11 @@ ganv_canvas_zoom_full(GanvCanvas* canvas) ganv_canvas_set_zoom(canvas, new_zoom); int scroll_x, scroll_y; - ganv_canvas_w2c(GANV_CANVAS(canvas->impl->_gcanvas), + ganv_canvas_w2c(canvas->impl->_gcanvas, lrintf(left - pad), lrintf(bottom - pad), &scroll_x, &scroll_y); - ganv_canvas_scroll_to(GANV_CANVAS(canvas->impl->_gcanvas), + ganv_canvas_scroll_to(canvas->impl->_gcanvas, scroll_x, scroll_y); } @@ -2140,7 +2150,7 @@ ganv_canvas_move_selected_items(GanvCanvas* canvas, double dy) { FOREACH_ITEM(canvas->impl->_selected_items, i) { - if ((*i)->item.parent == canvas->impl->root) { + if ((*i)->item.impl->parent == canvas->impl->root) { ganv_node_move(*i, dx, dy); } } @@ -2150,8 +2160,8 @@ void ganv_canvas_selection_move_finished(GanvCanvas* canvas) { FOREACH_ITEM(canvas->impl->_selected_items, i) { - const double x = GANV_ITEM(*i)->x; - const double y = GANV_ITEM(*i)->y; + const double x = GANV_ITEM(*i)->impl->x; + const double y = GANV_ITEM(*i)->impl->y; g_signal_emit(*i, signal_moved, 0, x, y, NULL); } } @@ -2161,7 +2171,7 @@ select_if_ends_are_selected(GanvEdge* edge, void* data) { if (ganv_node_is_selected(ganv_edge_get_tail(edge)) && ganv_node_is_selected(ganv_edge_get_head(edge))) { - ganv_edge_select(edge); + ganv_edge_set_selected(edge, TRUE); } } @@ -2221,7 +2231,7 @@ ganv_canvas_add_node(GanvCanvas* canvas, GanvNode* node) { GanvItem* item = GANV_ITEM(node); - if (item->parent == ganv_canvas_root(canvas)) { + if (item->impl->parent == ganv_canvas_root(canvas)) { canvas->impl->_items.insert(node); } } @@ -2468,8 +2478,8 @@ ganv_canvas_move_contents_to(GanvCanvas* canvas, double x, double y) { double min_x=HUGE_VAL, min_y=HUGE_VAL; FOREACH_ITEM(canvas->impl->_items, i) { - const double x = GANV_ITEM(*i)->x; - const double y = GANV_ITEM(*i)->y; + const double x = GANV_ITEM(*i)->impl->x; + const double y = GANV_ITEM(*i)->impl->y; min_x = std::min(min_x, x); min_y = std::min(min_y, y); } @@ -2493,7 +2503,7 @@ ganv_canvas_arrange(GanvCanvas* canvas) // Arrange to graphviz coordinates for (GVNodes::iterator i = nodes.begin(); i != nodes.end(); ++i) { - if (GANV_ITEM(i->first)->parent != GANV_ITEM(ganv_canvas_root(canvas))) { + if (GANV_ITEM(i->first)->impl->parent != GANV_ITEM(ganv_canvas_root(canvas))) { continue; } const std::string pos = agget(i->second, (char*)"pos"); @@ -2549,11 +2559,11 @@ ganv_canvas_arrange(GanvCanvas* canvas) static const double border_width = GANV_CANVAS_PAD; canvas->impl->move_contents_to_internal(border_width, border_width, least_x, least_y); - ganv_canvas_scroll_to(GANV_CANVAS(canvas->impl->_gcanvas), 0, 0); + ganv_canvas_scroll_to(canvas->impl->_gcanvas, 0, 0); FOREACH_ITEM(canvas->impl->_items, i) { - const double x = GANV_ITEM(*i)->x; - const double y = GANV_ITEM(*i)->y; + const double x = GANV_ITEM(*i)->impl->x; + const double y = GANV_ITEM(*i)->impl->y; g_signal_emit(*i, signal_moved, 0, x, y, NULL); } #endif @@ -2569,7 +2579,7 @@ ganv_canvas_export_dot(GanvCanvas* canvas, const char* filename) } gboolean -ganv_canvas_supports_sprung_layout(GanvCanvas* canvas) +ganv_canvas_supports_sprung_layout(const GanvCanvas* canvas) { #ifdef GANV_FDGL return TRUE; @@ -2591,7 +2601,7 @@ ganv_canvas_set_sprung_layout(GanvCanvas* canvas, gboolean sprung_layout) } gboolean -ganv_canvas_get_locked(GanvCanvas* canvas) +ganv_canvas_get_locked(const GanvCanvas* canvas) { return canvas->impl->locked; } @@ -2672,8 +2682,7 @@ ganv_canvas_new(double width, double height) "height", height, NULL)); - ganv_canvas_set_scroll_region(GANV_CANVAS(canvas), - 0.0, 0.0, width, height); + ganv_canvas_set_scroll_region(canvas, 0.0, 0.0, width, height); return canvas; } @@ -2682,8 +2691,6 @@ ganv_canvas_new(double width, double height) static void ganv_canvas_map(GtkWidget* widget) { - GanvCanvas* canvas; - g_return_if_fail(GANV_IS_CANVAS(widget)); /* Normal widget mapping stuff */ @@ -2692,7 +2699,7 @@ ganv_canvas_map(GtkWidget* widget) (*GTK_WIDGET_CLASS(canvas_parent_class)->map)(widget); } - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); if (canvas->impl->need_update) { add_idle(canvas); @@ -2709,11 +2716,9 @@ ganv_canvas_map(GtkWidget* widget) static void ganv_canvas_unmap(GtkWidget* widget) { - GanvCanvas* canvas; - g_return_if_fail(GANV_IS_CANVAS(widget)); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); shutdown_transients(canvas); @@ -2734,8 +2739,6 @@ ganv_canvas_unmap(GtkWidget* widget) static void ganv_canvas_realize(GtkWidget* widget) { - GanvCanvas* canvas; - g_return_if_fail(GANV_IS_CANVAS(widget)); /* Normal widget realization stuff */ @@ -2744,7 +2747,7 @@ ganv_canvas_realize(GtkWidget* widget) (*GTK_WIDGET_CLASS(canvas_parent_class)->realize)(widget); } - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); gdk_window_set_events( canvas->layout.bin_window, @@ -2770,11 +2773,9 @@ ganv_canvas_realize(GtkWidget* widget) static void ganv_canvas_unrealize(GtkWidget* widget) { - GanvCanvas* canvas; - g_return_if_fail(GANV_IS_CANVAS(widget)); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); shutdown_transients(canvas); @@ -2889,8 +2890,6 @@ scroll_to(GanvCanvas* canvas, int cx, int cy) static void ganv_canvas_size_allocate(GtkWidget* widget, GtkAllocation* allocation) { - GanvCanvas* canvas; - g_return_if_fail(GANV_IS_CANVAS(widget)); g_return_if_fail(allocation != NULL); @@ -2898,7 +2897,7 @@ ganv_canvas_size_allocate(GtkWidget* widget, GtkAllocation* allocation) (*GTK_WIDGET_CLASS(canvas_parent_class)->size_allocate)(widget, allocation); } - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); /* Recenter the view, if appropriate */ @@ -2920,7 +2919,7 @@ ganv_canvas_size_allocate(GtkWidget* widget, GtkAllocation* allocation) static gboolean is_descendant(GanvItem* item, GanvItem* parent) { - for (; item; item = item->parent) { + for (; item; item = item->impl->parent) { if (item == parent) { return TRUE; } @@ -3050,7 +3049,7 @@ ganv_canvas_emit_event(GanvCanvas* canvas, GdkEvent* event) ganv_item_emit_event(item, ev, &finished); - parent = item->parent; + parent = item->impl->parent; g_object_unref(G_OBJECT(item)); item = parent; @@ -3143,9 +3142,9 @@ int ganv_canvas_grab_item(GanvItem* item, guint event_mask, GdkCursor* cursor, guint32 etime) { g_return_val_if_fail(GANV_IS_ITEM(item), GDK_GRAB_NOT_VIEWABLE); - g_return_val_if_fail(GTK_WIDGET_MAPPED(item->canvas), GDK_GRAB_NOT_VIEWABLE); + g_return_val_if_fail(GTK_WIDGET_MAPPED(item->impl->canvas), GDK_GRAB_NOT_VIEWABLE); - if (item->canvas->impl->grabbed_item) { + if (item->impl->canvas->impl->grabbed_item) { return GDK_GRAB_ALREADY_GRABBED; } @@ -3153,7 +3152,7 @@ ganv_canvas_grab_item(GanvItem* item, guint event_mask, GdkCursor* cursor, guint return GDK_GRAB_NOT_VIEWABLE; } - int retval = gdk_pointer_grab(item->canvas->layout.bin_window, + int retval = gdk_pointer_grab(item->impl->canvas->layout.bin_window, FALSE, (GdkEventMask)event_mask, NULL, @@ -3164,9 +3163,9 @@ ganv_canvas_grab_item(GanvItem* item, guint event_mask, GdkCursor* cursor, guint return retval; } - item->canvas->impl->grabbed_item = item; - item->canvas->impl->grabbed_event_mask = event_mask; - item->canvas->impl->current_item = item; /* So that events go to the grabbed item */ + item->impl->canvas->impl->grabbed_item = item; + item->impl->canvas->impl->grabbed_event_mask = event_mask; + item->impl->canvas->impl->current_item = item; /* So that events go to the grabbed item */ return retval; } @@ -3184,11 +3183,11 @@ ganv_canvas_ungrab_item(GanvItem* item, guint32 etime) { g_return_if_fail(GANV_IS_ITEM(item)); - if (item->canvas->impl->grabbed_item != item) { + if (item->impl->canvas->impl->grabbed_item != item) { return; } - item->canvas->impl->grabbed_item = NULL; + item->impl->canvas->impl->grabbed_item = NULL; gdk_pointer_ungrab(etime); } @@ -3285,7 +3284,7 @@ pick_current_item(GanvCanvas* canvas, GdkEvent* event) if (canvas->impl->root->object.flags & GANV_ITEM_VISIBLE) { GANV_ITEM_GET_CLASS(canvas->impl->root)->point( canvas->impl->root, - x - canvas->impl->root->x, y - canvas->impl->root->y, + x - canvas->impl->root->impl->x, y - canvas->impl->root->impl->y, &canvas->impl->new_current_item); } else { canvas->impl->new_current_item = NULL; @@ -3344,16 +3343,15 @@ pick_current_item(GanvCanvas* canvas, GdkEvent* event) static gint ganv_canvas_button(GtkWidget* widget, GdkEventButton* event) { - GanvCanvas* canvas; - int mask; - int retval; + int mask; + int retval; g_return_val_if_fail(GANV_IS_CANVAS(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); retval = FALSE; - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); /* * dispatch normally regardless of the event's window if an item has @@ -3419,12 +3417,10 @@ ganv_canvas_button(GtkWidget* widget, GdkEventButton* event) static gint ganv_canvas_motion(GtkWidget* widget, GdkEventMotion* event) { - GanvCanvas* canvas; - g_return_val_if_fail(GANV_IS_CANVAS(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); if (event->window != canvas->layout.bin_window) { return FALSE; @@ -3438,12 +3434,10 @@ ganv_canvas_motion(GtkWidget* widget, GdkEventMotion* event) static gboolean ganv_canvas_scroll(GtkWidget* widget, GdkEventScroll* event) { - GanvCanvas* canvas; - g_return_val_if_fail(GANV_IS_CANVAS(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); if (event->window != canvas->layout.bin_window) { return FALSE; @@ -3458,12 +3452,10 @@ ganv_canvas_scroll(GtkWidget* widget, GdkEventScroll* event) static gboolean ganv_canvas_key(GtkWidget* widget, GdkEventKey* event) { - GanvCanvas* canvas; - g_return_val_if_fail(GANV_IS_CANVAS(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); if (!ganv_canvas_emit_event(canvas, (GdkEvent*)event)) { GtkWidgetClass* widget_class; @@ -3492,12 +3484,10 @@ ganv_canvas_key(GtkWidget* widget, GdkEventKey* event) static gint ganv_canvas_crossing(GtkWidget* widget, GdkEventCrossing* event) { - GanvCanvas* canvas; - g_return_val_if_fail(GANV_IS_CANVAS(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); if (event->window != canvas->layout.bin_window) { return FALSE; @@ -3511,11 +3501,9 @@ ganv_canvas_crossing(GtkWidget* widget, GdkEventCrossing* event) static gint ganv_canvas_focus_in(GtkWidget* widget, GdkEventFocus* event) { - GanvCanvas* canvas; - GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); if (canvas->impl->focused_item) { return ganv_canvas_emit_event(canvas, (GdkEvent*)event); @@ -3528,11 +3516,9 @@ ganv_canvas_focus_in(GtkWidget* widget, GdkEventFocus* event) static gint ganv_canvas_focus_out(GtkWidget* widget, GdkEventFocus* event) { - GanvCanvas* canvas; - GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS); - canvas = GANV_CANVAS(widget); + GanvCanvas* canvas = GANV_CANVAS(widget); if (canvas->impl->focused_item) { return ganv_canvas_emit_event(canvas, (GdkEvent*)event); @@ -3695,11 +3681,9 @@ update_again: static gboolean idle_handler(gpointer data) { - GanvCanvas* canvas; - GDK_THREADS_ENTER(); - canvas = GANV_CANVAS(data); + GanvCanvas* canvas = GANV_CANVAS(data); do_update(canvas); @@ -3809,7 +3793,7 @@ ganv_canvas_set_center_scroll_region(GanvCanvas* canvas, gboolean center_scroll_ } gboolean -ganv_canvas_get_center_scroll_region(GanvCanvas* canvas) +ganv_canvas_get_center_scroll_region(const GanvCanvas* canvas) { g_return_val_if_fail(GANV_IS_CANVAS(canvas), FALSE); @@ -3841,14 +3825,13 @@ ganv_canvas_get_scroll_offsets(const GanvCanvas* canvas, int* cx, int* cy) GanvItem* ganv_canvas_get_item_at(GanvCanvas* canvas, double x, double y) { - g_return_val_if_fail(GANV_IS_CANVAS(canvas), NULL); GanvItem* item = NULL; double dist = GANV_ITEM_GET_CLASS(canvas->impl->root)->point( canvas->impl->root, - x - canvas->impl->root->x, - y - canvas->impl->root->y, + x - canvas->impl->root->impl->x, + y - canvas->impl->root->impl->y, &item); if ((int)(dist * canvas->impl->pixels_per_unit + 0.5) <= GANV_CLOSE_ENOUGH) { return item; diff --git a/src/boilerplate.h b/src/boilerplate.h index 33c09df..a6be001 100644 --- a/src/boilerplate.h +++ b/src/boilerplate.h @@ -27,7 +27,7 @@ typedef gpointer gobject; if (field != tmp) { \ field = tmp; \ GanvItem* item = GANV_ITEM(object); \ - if (item->canvas) { \ + if (item->impl->canvas) { \ ganv_item_request_update(item); \ } \ } \ @@ -153,7 +153,7 @@ ganv_box_request_redraw(GanvItem* item, ganv_item_i2w_pair(item, &x1, &y1, &x2, &y2); } - ganv_canvas_request_redraw_w(item->canvas, x1, y1, x2, y2); + ganv_canvas_request_redraw_w(item->impl->canvas, x1, y1, x2, y2); } static void @@ -193,8 +193,8 @@ ganv_box_update(GanvItem* item, int flags) ganv_box_normalize(box); // Update world-relative bounding box - ganv_box_bounds(item, &item->x1, &item->y1, &item->x2, &item->y2); - ganv_item_i2w_pair(item, &item->x1, &item->y1, &item->x2, &item->y2); + ganv_box_bounds(item, &item->impl->x1, &item->impl->y1, &item->impl->x2, &item->impl->y2); + ganv_item_i2w_pair(item, &item->impl->x1, &item->impl->y1, &item->impl->x2, &item->impl->y2); // Request redraw of new location ganv_box_request_redraw(item, &impl->coords, FALSE); diff --git a/src/circle.c b/src/circle.c index 789ebb0..b16accd 100644 --- a/src/circle.c +++ b/src/circle.c @@ -61,15 +61,6 @@ ganv_circle_destroy(GtkObject* object) } static void -set_radius_ems(GanvCircle* circle, - double ems) -{ - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(circle)->canvas); - const double points = ganv_canvas_get_font_size(canvas); - circle->impl->coords.radius = points * ems; -} - -static void ganv_circle_set_property(GObject* object, guint prop_id, const GValue* value, @@ -90,7 +81,7 @@ ganv_circle_set_property(GObject* object, } if (prop_id == PROP_RADIUS_EMS) { - set_radius_ems(circle, circle->impl->coords.radius_ems); + ganv_circle_set_radius_ems(circle, circle->impl->coords.radius_ems); } } @@ -120,7 +111,7 @@ ganv_circle_resize(GanvNode* self) { GanvNode* node = GANV_NODE(self); GanvCircle* circle = GANV_CIRCLE(self); - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); + GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->impl->canvas); if (node->impl->label) { if (node->impl->label->impl->needs_layout) { @@ -159,7 +150,7 @@ ganv_circle_redraw_text(GanvNode* self) { GanvCircle* circle = GANV_CIRCLE(self); if (circle->impl->coords.radius_ems) { - set_radius_ems(circle, circle->impl->coords.radius_ems); + ganv_circle_set_radius_ems(circle, circle->impl->coords.radius_ems); } if (parent_class->redraw_text) { @@ -174,8 +165,8 @@ ganv_circle_is_within(const GanvNode* self, double x2, double y2) { - const double x = GANV_ITEM(self)->x; - const double y = GANV_ITEM(self)->y; + const double x = GANV_ITEM(self)->impl->x; + const double y = GANV_ITEM(self)->impl->y; return x >= x1 && x <= x2 @@ -193,10 +184,10 @@ ganv_circle_vector(const GanvNode* self, { GanvCircle* circle = GANV_CIRCLE(self); - const double cx = GANV_ITEM(self)->x; - const double cy = GANV_ITEM(self)->y; - const double other_x = GANV_ITEM(other)->x; - const double other_y = GANV_ITEM(other)->y; + const double cx = GANV_ITEM(self)->impl->x; + const double cy = GANV_ITEM(self)->impl->y; + const double other_x = GANV_ITEM(other)->impl->x; + const double other_y = GANV_ITEM(other)->impl->y; const double xdist = other_x - cx; const double ydist = other_y - cy; @@ -212,7 +203,7 @@ ganv_circle_vector(const GanvNode* self, *dx = 0.0; *dy = 0.0; - ganv_item_i2w(GANV_ITEM(circle)->parent, x, y); + ganv_item_i2w(GANV_ITEM(circle)->impl->parent, x, y); } static void @@ -232,7 +223,7 @@ request_redraw(GanvItem* item, ganv_item_i2w_pair(item, &x1, &y1, &x2, &y2); } - ganv_canvas_request_redraw_w(item->canvas, x1, y1, x2, y2); + ganv_canvas_request_redraw_w(item->impl->canvas, x1, y1, x2, y2); } static void @@ -283,8 +274,8 @@ ganv_circle_update(GanvItem* item, int flags) coords_i2w(item, &impl->old_coords); // Update world-relative bounding box - ganv_circle_bounds(item, &item->x1, &item->y1, &item->x2, &item->y2); - ganv_item_i2w_pair(item, &item->x1, &item->y1, &item->x2, &item->y2); + ganv_circle_bounds(item, &item->impl->x1, &item->impl->y1, &item->impl->x2, &item->impl->y2); + ganv_item_i2w_pair(item, &item->impl->x1, &item->impl->y1, &item->impl->x2, &item->impl->y2); // Request redraw of new location request_redraw(item, &impl->coords, FALSE); @@ -437,3 +428,39 @@ ganv_circle_get_radius(const GanvCircle* circle) { return circle->impl->coords.radius; } + +void +ganv_circle_set_radius(GanvCircle* circle, double radius) +{ + circle->impl->coords.radius = radius; + ganv_item_request_update(GANV_ITEM(circle)); +} + +double +ganv_circle_get_radius_ems(const GanvCircle* circle) +{ + return circle->impl->coords.radius_ems; +} + +void +ganv_circle_set_radius_ems(GanvCircle* circle, double ems) +{ + GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(circle)->impl->canvas); + const double points = ganv_canvas_get_font_size(canvas); + circle->impl->coords.radius_ems = ems; + circle->impl->coords.radius = points * ems; + ganv_item_request_update(GANV_ITEM(circle)); +} + +gboolean +ganv_circle_get_fit_label(const GanvCircle* circle) +{ + return circle->impl->fit_label; +} + +void +ganv_circle_set_fit_label(GanvCircle* circle, gboolean fit_label) +{ + circle->impl->fit_label = fit_label; + ganv_item_request_update(GANV_ITEM(circle)); +} @@ -88,11 +88,11 @@ ganv_edge_destroy(GtkObject* object) g_return_if_fail(GANV_IS_EDGE(object)); GanvEdge* edge = GANV_EDGE(object); - GanvCanvas* canvas = GANV_CANVAS(edge->item.canvas); + GanvCanvas* canvas = GANV_CANVAS(edge->item.impl->canvas); if (canvas && !edge->impl->ghost) { - edge->item.canvas = NULL; + edge->item.impl->canvas = NULL; } - edge->item.parent = NULL; + edge->item.impl->parent = NULL; if (GTK_OBJECT_CLASS(parent_class)->destroy) { (*GTK_OBJECT_CLASS(parent_class)->destroy)(object); @@ -166,7 +166,7 @@ void ganv_edge_request_redraw(GanvItem* item, const GanvEdgeCoords* coords) { - GanvCanvas* canvas = item->canvas; + GanvCanvas* canvas = item->impl->canvas; const double w = coords->width; if (coords->curved) { const double src_x = coords->x1; @@ -308,11 +308,11 @@ ganv_edge_update(GanvItem* item, int flags) } // Update world-relative bounding box - item->x1 = x1; - item->y1 = y1; - item->x2 = x2; - item->y2 = y2; - ganv_item_i2w_pair(item, &item->x1, &item->y1, &item->x2, &item->y2); + item->impl->x1 = x1; + item->impl->y1 = y1; + item->impl->x2 = x2; + item->impl->y2 = y2; + ganv_item_i2w_pair(item, &item->impl->x1, &item->impl->y1, &item->impl->x2, &item->impl->y2); // Request redraw of new location ganv_edge_request_redraw(item, &impl->coords); @@ -638,37 +638,51 @@ ganv_edge_update_location(GanvEdge* edge) ganv_item_request_update(GANV_ITEM(edge)); } +gboolean +ganv_edge_get_curved(const GanvEdge* edge) +{ + return edge->impl->coords.curved; +} + void -ganv_edge_select(GanvEdge* edge) +ganv_edge_set_curved(GanvEdge* edge, gboolean curved) { - GanvCanvas* canvas = GANV_CANVAS(edge->item.canvas); - ganv_canvas_select_edge(canvas, edge); + edge->impl->coords.curved = curved; + ganv_edge_request_redraw(GANV_ITEM(edge), &edge->impl->coords); } void -ganv_edge_unselect(GanvEdge* edge) +ganv_edge_set_selected(GanvEdge* edge, gboolean selected) +{ + GanvCanvas* canvas = GANV_CANVAS(edge->item.impl->canvas); + if (selected) { + ganv_canvas_select_edge(canvas, edge); + } else { + ganv_canvas_unselect_edge(canvas, edge); + } +} + +void +ganv_edge_select(GanvEdge* edge) { - GanvCanvas* canvas = GANV_CANVAS(edge->item.canvas); - ganv_canvas_unselect_edge(canvas, edge); + ganv_edge_set_selected(edge, TRUE); } void -ganv_edge_highlight(GanvEdge* edge) +ganv_edge_unselect(GanvEdge* edge) { - edge->impl->highlighted = TRUE; - ganv_edge_request_redraw(GANV_ITEM(edge), &edge->impl->coords); + ganv_edge_set_selected(edge, FALSE); } void -ganv_edge_unhighlight(GanvEdge* edge) +ganv_edge_set_highlighted(GanvEdge* edge, gboolean highlighted) { - edge->impl->highlighted = FALSE; + edge->impl->highlighted = highlighted; ganv_edge_request_redraw(GANV_ITEM(edge), &edge->impl->coords); } void -ganv_edge_tick(GanvEdge* edge, - double seconds) +ganv_edge_tick(GanvEdge* edge, double seconds) { ganv_item_set(GANV_ITEM(edge), "dash-offset", seconds * 8.0, @@ -680,7 +694,7 @@ ganv_edge_disconnect(GanvEdge* edge) { if (!edge->impl->ghost) { ganv_canvas_disconnect_edge( - GANV_CANVAS(edge->item.canvas), + GANV_CANVAS(edge->item.impl->canvas), edge); } } @@ -690,7 +704,7 @@ ganv_edge_remove(GanvEdge* edge) { if (!edge->impl->ghost) { ganv_canvas_remove_edge( - GANV_CANVAS(edge->item.canvas), + GANV_CANVAS(edge->item.impl->canvas), edge); } } diff --git a/src/ganv-private.h b/src/ganv-private.h index 870dcec..8f32480 100644 --- a/src/ganv-private.h +++ b/src/ganv-private.h @@ -130,6 +130,83 @@ struct _GanvNodeImpl { #endif }; +/* Widget */ + +struct _GanvWidgetImpl { + GtkWidget* widget; /* The child widget */ + + double x, y; /* Position at anchor */ + double width, height; /* Dimensions of widget */ + GtkAnchorType anchor; /* Anchor side for widget */ + + int cx, cy; /* Top-left canvas coordinates for widget */ + int cwidth, cheight; /* Size of widget in pixels */ + + guint destroy_id; /* Signal connection id for destruction of child widget */ + + guint size_pixels : 1; /* Is size specified in (unchanging) pixels or units (get scaled)? */ + guint in_destroy : 1; /* Is child widget being destroyed? */ +}; + +/* Group */ +struct _GanvGroupImpl { + GList* item_list; + GList* item_list_end; +}; + +/* Item */ +struct _GanvItemImpl { + /* Parent canvas for this item */ + struct _GanvCanvas* canvas; + + /* Parent for this item */ + GanvItem* parent; + + /* Layer (z order), higher values are on top */ + guint layer; + + /* Position in parent-relative coordinates. */ + double x, y; + + /* Bounding box for this item (in world coordinates) */ + double x1, y1, x2, y2; + + /* True if parent manages this item (don't call add/remove) */ + gboolean managed; +}; + +void +ganv_node_tick(GanvNode* self, double seconds); + +void +ganv_node_tail_vector(const GanvNode* self, + const GanvNode* head, + double* x1, + double* y1, + double* x2, + double* y2); + +void +ganv_node_head_vector(const GanvNode* self, + const GanvNode* tail, + double* x1, + double* y1, + double* x2, + double* y2); + +/** + * ganv_node_get_draw_properties: + * + * Get the colours that should currently be used for drawing this node. Note + * these may not be identical to the property values because of highlighting + * and selection. + */ +void +ganv_node_get_draw_properties(const GanvNode* node, + double* dash_length, + double* border_color, + double* fill_color); + /* Port */ typedef struct { @@ -199,10 +276,6 @@ ganv_canvas_add_edge(GanvCanvas* canvas, GanvEdge* edge); void -ganv_canvas_remove_edge(GanvCanvas* canvas, - GanvEdge* edge); - -void ganv_canvas_select_edge(GanvCanvas* canvas, GanvEdge* edge); @@ -271,12 +344,18 @@ ganv_canvas_request_redraw_w(GanvCanvas* canvas, /* Edge */ void +ganv_edge_update_location(GanvEdge* edge); + +void ganv_edge_get_coords(const GanvEdge* edge, GanvEdgeCoords* coords); void ganv_edge_request_redraw(GanvItem* item, const GanvEdgeCoords* coords); +void +ganv_edge_tick(GanvEdge* edge, double seconds); + /* Box */ void @@ -290,6 +369,10 @@ void ganv_port_set_control_value_internal(GanvPort* port, float value); +void +ganv_port_set_direction(GanvPort* port, + GanvDirection direction); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/group.c b/src/group.c index fdcb1f6..4e7731a 100644 --- a/src/group.c +++ b/src/group.c @@ -37,6 +37,12 @@ static GanvItemClass* group_parent_class; static void ganv_group_init(GanvGroup* group) { + GanvGroupImpl* impl = G_TYPE_INSTANCE_GET_PRIVATE( + group, GANV_TYPE_GROUP, GanvGroupImpl); + + group->impl = impl; + group->impl->item_list = NULL; + group->impl->item_list_end = NULL; } static void @@ -74,9 +80,9 @@ ganv_group_destroy(GtkObject* object) group = GANV_GROUP(object); - while (group->item_list) { + while (group->impl->item_list) { // child is unref'ed by the child's group_remove(). - gtk_object_destroy(GTK_OBJECT(group->item_list->data)); + gtk_object_destroy(GTK_OBJECT(group->impl->item_list->data)); } if (GTK_OBJECT_CLASS(group_parent_class)->destroy) { (*GTK_OBJECT_CLASS(group_parent_class)->destroy)(object); @@ -86,11 +92,7 @@ ganv_group_destroy(GtkObject* object) static void ganv_group_update(GanvItem* item, int flags) { - GanvGroup* group; - GList* list; - GanvItem* i; - - group = GANV_GROUP(item); + GanvGroup* group = GANV_GROUP(item); (*group_parent_class->update)(item, flags); @@ -99,20 +101,20 @@ ganv_group_update(GanvItem* item, int flags) double max_x = 0.0; double max_y = 0.0; - for (list = group->item_list; list; list = list->next) { - i = (GanvItem*)list->data; + for (GList* list = group->impl->item_list; list; list = list->next) { + GanvItem* i = (GanvItem*)list->data; ganv_item_invoke_update(i, flags); - min_x = fmin(min_x, fmin(i->x1, i->x2)); - min_y = fmin(min_y, fmin(i->y1, i->y2)); - max_x = fmax(max_x, fmax(i->x1, i->x2)); - max_y = fmax(max_y, fmax(i->y2, i->y2)); + min_x = fmin(min_x, fmin(i->impl->x1, i->impl->x2)); + min_y = fmin(min_y, fmin(i->impl->y1, i->impl->y2)); + max_x = fmax(max_x, fmax(i->impl->x1, i->impl->x2)); + max_y = fmax(max_y, fmax(i->impl->y2, i->impl->y2)); } - item->x1 = min_x; - item->y1 = min_y; - item->x2 = max_x; - item->y2 = max_y; + item->impl->x1 = min_x; + item->impl->y1 = min_y; + item->impl->x2 = max_x; + item->impl->y2 = max_y; } static void @@ -124,7 +126,7 @@ ganv_group_realize(GanvItem* item) group = GANV_GROUP(item); - for (list = group->item_list; list; list = list->next) { + for (list = group->impl->item_list; list; list = list->next) { i = (GanvItem*)list->data; if (!(i->object.flags & GANV_ITEM_REALIZED)) { @@ -144,7 +146,7 @@ ganv_group_unrealize(GanvItem* item) group = GANV_GROUP(item); - for (list = group->item_list; list; list = list->next) { + for (list = group->impl->item_list; list; list = list->next) { i = (GanvItem*)list->data; if (i->object.flags & GANV_ITEM_REALIZED) { @@ -164,7 +166,7 @@ ganv_group_map(GanvItem* item) group = GANV_GROUP(item); - for (list = group->item_list; list; list = list->next) { + for (list = group->impl->item_list; list; list = list->next) { i = (GanvItem*)list->data; if (!(i->object.flags & GANV_ITEM_MAPPED)) { @@ -184,7 +186,7 @@ ganv_group_unmap(GanvItem* item) group = GANV_GROUP(item); - for (list = group->item_list; list; list = list->next) { + for (list = group->impl->item_list; list; list = list->next) { i = (GanvItem*)list->data; if (i->object.flags & GANV_ITEM_MAPPED) { @@ -200,7 +202,6 @@ ganv_group_draw(GanvItem* item, cairo_t* cr, double cx, double cy, double cw, double ch) { GanvGroup* group = GANV_GROUP(item); - GanvItem* child = NULL; // Draw background cairo_set_source_rgba(cr, 0, 0, 0, 1.0); @@ -209,14 +210,14 @@ ganv_group_draw(GanvItem* item, // TODO: Layered drawing - for (GList* list = group->item_list; list; list = list->next) { - child = (GanvItem*)list->data; + for (GList* list = group->impl->item_list; list; list = list->next) { + GanvItem* child = (GanvItem*)list->data; if (((child->object.flags & GANV_ITEM_VISIBLE) - && ((child->x1 < (cx + cw)) - && (child->y1 < (cy + ch)) - && (child->x2 > cx) - && (child->y2 > cy)))) { + && ((child->impl->x1 < (cx + cw)) + && (child->impl->y1 < (cy + ch)) + && (child->impl->x2 > cx) + && (child->impl->y2 > cy)))) { if (GANV_ITEM_GET_CLASS(child)->draw) { (*GANV_ITEM_GET_CLASS(child)->draw)( child, cr, cx, cy, cw, ch); @@ -240,9 +241,9 @@ ganv_group_point(GanvItem* item, double x, double y, GanvItem** actual_item) *actual_item = NULL; - for (GList* list = group->item_list; list; list = list->next) { + for (GList* list = group->impl->item_list; list; list = list->next) { GanvItem* child = (GanvItem*)list->data; - if ((child->x1 > x2) || (child->y1 > y2) || (child->x2 < x1) || (child->y2 < y1)) { + if ((child->impl->x1 > x2) || (child->impl->y1 > y2) || (child->impl->x2 < x1) || (child->impl->y2 < y1)) { continue; } @@ -253,7 +254,7 @@ ganv_group_point(GanvItem* item, double x, double y, GanvItem** actual_item) && GANV_ITEM_GET_CLASS(child)->point) { dist = GANV_ITEM_GET_CLASS(child)->point( child, - x - child->x, y - child->y, + x - child->impl->x, y - child->impl->y, &point_item); has_point = TRUE; } @@ -281,10 +282,10 @@ get_child_bounds(GanvItem* child, double* x1, double* y1, double* x2, double* y2 ganv_item_get_bounds(child, x1, y1, x2, y2); // Make bounds relative to the item's parent coordinate system - *x1 -= child->x; - *y1 -= child->y; - *x2 -= child->x; - *y2 -= child->y; + *x1 -= child->impl->x; + *y1 -= child->impl->y; + *x2 -= child->impl->x; + *y2 -= child->impl->y; } static void @@ -305,7 +306,7 @@ ganv_group_bounds(GanvItem* item, double* x1, double* y1, double* x2, double* y2 set = FALSE; - for (list = group->item_list; list; list = list->next) { + for (list = group->impl->item_list; list; list = list->next) { child = (GanvItem*)list->data; if (child->object.flags & GANV_ITEM_VISIBLE) { @@ -364,11 +365,11 @@ ganv_group_add(GanvItem* parent, GanvItem* item) GanvGroup* group = GANV_GROUP(parent); g_object_ref_sink(G_OBJECT(item)); - if (!group->item_list) { - group->item_list = g_list_append(group->item_list, item); - group->item_list_end = group->item_list; + if (!group->impl->item_list) { + group->impl->item_list = g_list_append(group->impl->item_list, item); + group->impl->item_list_end = group->impl->item_list; } else { - group->item_list_end = g_list_append(group->item_list_end, item)->next; + group->impl->item_list_end = g_list_append(group->impl->item_list_end, item)->next; } if (group->item.object.flags & GANV_ITEM_REALIZED) { @@ -391,7 +392,7 @@ ganv_group_remove(GanvItem* parent, GanvItem* item) g_return_if_fail(GANV_IS_GROUP(group)); g_return_if_fail(GANV_IS_ITEM(item)); - for (children = group->item_list; children; children = children->next) { + for (children = group->impl->item_list; children; children = children->next) { if (children->data == item) { if (item->object.flags & GANV_ITEM_MAPPED) { (*GANV_ITEM_GET_CLASS(item)->unmap)(item); @@ -403,16 +404,16 @@ ganv_group_remove(GanvItem* parent, GanvItem* item) /* Unparent the child */ - item->parent = NULL; + item->impl->parent = NULL; g_object_unref(G_OBJECT(item)); /* Remove it from the list */ - if (children == group->item_list_end) { - group->item_list_end = children->prev; + if (children == group->impl->item_list_end) { + group->impl->item_list_end = children->prev; } - group->item_list = g_list_remove_link(group->item_list, children); + group->impl->item_list = g_list_remove_link(group->impl->item_list, children); g_list_free(children); break; } @@ -432,6 +433,8 @@ ganv_group_class_init(GanvGroupClass* klass) group_parent_class = (GanvItemClass*)g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(GanvGroupImpl)); + gobject_class->set_property = ganv_group_set_property; gobject_class->get_property = ganv_group_get_property; @@ -72,8 +72,12 @@ static GtkObjectClass* item_parent_class; static void ganv_item_init(GanvItem* item) { + GanvItemImpl* impl = G_TYPE_INSTANCE_GET_PRIVATE( + item, GANV_TYPE_ITEM, GanvItemImpl); + item->object.flags |= GANV_ITEM_VISIBLE; - item->managed = FALSE; + item->impl = impl; + item->impl->managed = FALSE; } /** @@ -98,13 +102,11 @@ ganv_item_init(GanvItem* item) GanvItem* ganv_item_new(GanvItem* parent, GType type, const gchar* first_arg_name, ...) { - GanvItem* item; - va_list args; - g_return_val_if_fail(g_type_is_a(type, ganv_item_get_type()), NULL); - item = GANV_ITEM(g_object_new(type, NULL)); + GanvItem* item = GANV_ITEM(g_object_new(type, NULL)); + va_list args; va_start(args, first_arg_name); ganv_item_construct(item, parent, first_arg_name, args); va_end(args); @@ -118,18 +120,18 @@ ganv_item_new(GanvItem* parent, GType type, const gchar* first_arg_name, ...) static void item_post_create_setup(GanvItem* item) { - GanvItemClass* parent_class = GANV_ITEM_GET_CLASS(item->parent); - if (!item->managed) { + GanvItemClass* parent_class = GANV_ITEM_GET_CLASS(item->impl->parent); + if (!item->impl->managed) { if (parent_class->add) { - parent_class->add(item->parent, item); + parent_class->add(item->impl->parent, item); } else { g_warning("item added to non-parent item\n"); } } - ganv_canvas_request_redraw_w(item->canvas, - item->x1, item->y1, - item->x2 + 1, item->y2 + 1); - ganv_canvas_set_need_repick(item->canvas); + ganv_canvas_request_redraw_w(item->impl->canvas, + item->impl->x1, item->impl->y1, + item->impl->x2 + 1, item->impl->y2 + 1); + ganv_canvas_set_need_repick(item->impl->canvas); } static void @@ -145,25 +147,25 @@ ganv_item_set_property(GObject* object, switch (prop_id) { case ITEM_PROP_PARENT: - if (item->parent != NULL) { + if (item->impl->parent != NULL) { g_warning("Cannot set `parent' argument after item has " "already been constructed."); } else if (g_value_get_object(value)) { - item->parent = GANV_ITEM(g_value_get_object(value)); - item->canvas = item->parent->canvas; + item->impl->parent = GANV_ITEM(g_value_get_object(value)); + item->impl->canvas = item->impl->parent->impl->canvas; item_post_create_setup(item); } break; case ITEM_PROP_X: - item->x = g_value_get_double(value); + item->impl->x = g_value_get_double(value); ganv_item_request_update(item); break; case ITEM_PROP_Y: - item->y = g_value_get_double(value); + item->impl->y = g_value_get_double(value); ganv_item_request_update(item); break; case ITEM_PROP_MANAGED: - item->managed = g_value_get_boolean(value); + item->impl->managed = g_value_get_boolean(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -184,16 +186,16 @@ ganv_item_get_property(GObject* object, switch (prop_id) { case ITEM_PROP_PARENT: - g_value_set_object(value, item->parent); + g_value_set_object(value, item->impl->parent); break; case ITEM_PROP_X: - g_value_set_double(value, item->x); + g_value_set_double(value, item->impl->x); break; case ITEM_PROP_Y: - g_value_set_double(value, item->y); + g_value_set_double(value, item->impl->y); break; case ITEM_PROP_MANAGED: - g_value_set_boolean(value, item->managed); + g_value_set_boolean(value, item->impl->managed); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -216,9 +218,9 @@ ganv_item_construct(GanvItem* item, GanvItem* parent, { g_return_if_fail(GANV_IS_ITEM(item)); - item->parent = parent; - item->canvas = item->parent->canvas; - item->layer = 0; + item->impl->parent = parent; + item->impl->canvas = item->impl->parent->impl->canvas; + item->impl->layer = 0; g_object_set_valist(G_OBJECT(item), first_arg_name, args); @@ -230,9 +232,9 @@ static void redraw_if_visible(GanvItem* item) { if (item->object.flags & GANV_ITEM_VISIBLE) { - ganv_canvas_request_redraw_w(item->canvas, - item->x1, item->y1, - item->x2 + 1, item->y2 + 1); + ganv_canvas_request_redraw_w(item->impl->canvas, + item->impl->x1, item->impl->y1, + item->impl->x2 + 1, item->impl->y2 + 1); } } @@ -246,9 +248,9 @@ ganv_item_dispose(GObject* object) item = GANV_ITEM(object); - if (item->canvas) { + if (item->impl->canvas) { redraw_if_visible(item); - ganv_canvas_forget_item(item->canvas, item); + ganv_canvas_forget_item(item->impl->canvas, item); } /* Normal destroy stuff */ @@ -261,18 +263,18 @@ ganv_item_dispose(GObject* object) (*GANV_ITEM_GET_CLASS(item)->unrealize)(item); } - if (!item->managed && item->parent) { - if (GANV_ITEM_GET_CLASS(item->parent)->remove) { - GANV_ITEM_GET_CLASS(item->parent)->remove(item->parent, item); + if (!item->impl->managed && item->impl->parent) { + if (GANV_ITEM_GET_CLASS(item->impl->parent)->remove) { + GANV_ITEM_GET_CLASS(item->impl->parent)->remove(item->impl->parent, item); } else { fprintf(stderr, "warning: Item parent has no remove method\n"); } } G_OBJECT_CLASS(item_parent_class)->dispose(object); - /* items should remove any reference to item->canvas after the + /* items should remove any reference to item->impl->canvas after the first ::destroy */ - item->canvas = NULL; + item->impl->canvas = NULL; } /* Realize handler for canvas items */ @@ -380,19 +382,31 @@ ganv_item_set_valist(GanvItem* item, const gchar* first_arg_name, va_list args) g_object_set_valist(G_OBJECT(item), first_arg_name, args); - ganv_canvas_set_need_repick(item->canvas); + ganv_canvas_set_need_repick(item->impl->canvas); +} + +GanvCanvas* +ganv_item_get_canvas(GanvItem* item) +{ + return item->impl->canvas; +} + +GanvItem* +ganv_item_get_parent(GanvItem* item) +{ + return item->impl->parent; } void ganv_item_raise(GanvItem* item) { - ++item->layer; + ++item->impl->layer; } void ganv_item_lower(GanvItem* item) { - --item->layer; + --item->impl->layer; } /** @@ -408,11 +422,11 @@ ganv_item_move(GanvItem* item, double dx, double dy) return; } - item->x += dx; - item->y += dy; + item->impl->x += dx; + item->impl->y += dy; ganv_item_request_update(item); - ganv_canvas_set_need_repick(item->canvas); + ganv_canvas_set_need_repick(item->impl->canvas); } /** @@ -428,10 +442,10 @@ ganv_item_show(GanvItem* item) if (!(item->object.flags & GANV_ITEM_VISIBLE)) { item->object.flags |= GANV_ITEM_VISIBLE; - ganv_canvas_request_redraw_w(item->canvas, - item->x1, item->y1, - item->x2 + 1, item->y2 + 1); - ganv_canvas_set_need_repick(item->canvas); + ganv_canvas_request_redraw_w(item->impl->canvas, + item->impl->x1, item->impl->y1, + item->impl->x2 + 1, item->impl->y2 + 1); + ganv_canvas_set_need_repick(item->impl->canvas); } } @@ -449,10 +463,10 @@ ganv_item_hide(GanvItem* item) if (item->object.flags & GANV_ITEM_VISIBLE) { item->object.flags &= ~GANV_ITEM_VISIBLE; - ganv_canvas_request_redraw_w(item->canvas, - item->x1, item->y1, - item->x2 + 1, item->y2 + 1); - ganv_canvas_set_need_repick(item->canvas); + ganv_canvas_request_redraw_w(item->impl->canvas, + item->impl->x1, item->impl->y1, + item->impl->x2 + 1, item->impl->y2 + 1); + ganv_canvas_set_need_repick(item->impl->canvas); } } @@ -462,9 +476,9 @@ ganv_item_i2w_offset(GanvItem* item, double* px, double* py) double x = 0.0; double y = 0.0; while (item) { - x += item->x; - y += item->y; - item = item->parent; + x += item->impl->x; + y += item->impl->y; + item = item->impl->parent; } *px = x; *py = y; @@ -538,7 +552,7 @@ ganv_item_w2i(GanvItem* item, double* x, double* y) void ganv_item_grab_focus(GanvItem* item) { - ganv_canvas_grab_focus(item->canvas, item); + ganv_canvas_grab_focus(item->impl->canvas, item); } void @@ -587,19 +601,19 @@ ganv_item_request_update(GanvItem* item) return; } - if (!item->canvas) { + if (!item->impl->canvas) { /* Item is being / has been destroyed, ignore */ return; } item->object.flags |= GANV_ITEM_NEED_UPDATE; - if (item->parent != NULL) { + if (item->impl->parent != NULL) { /* Recurse up the tree */ - ganv_item_request_update(item->parent); + ganv_item_request_update(item->impl->parent); } else { /* Have reached the top of the tree, make sure the update call gets scheduled. */ - ganv_canvas_request_update(item->canvas); + ganv_canvas_request_update(item->impl->canvas); } } @@ -629,6 +643,8 @@ ganv_item_class_init(GanvItemClass* klass) item_parent_class = (GtkObjectClass*)g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(GanvItemImpl)); + gobject_class->set_property = ganv_item_set_property; gobject_class->get_property = ganv_item_get_property; diff --git a/src/module.c b/src/module.c index c8da4d2..d630ec8 100644 --- a/src/module.c +++ b/src/module.c @@ -148,7 +148,7 @@ measure(GanvModule* module, Metrics* m) double title_w, title_h; title_size(module, &title_w, &title_h); - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(module)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module)); GanvText* canvas_title = GANV_NODE(module)->impl->label; GanvModuleImpl* impl = module->impl; @@ -253,7 +253,7 @@ place_title(GanvModule* module, GanvDirection dir) static void resize_right(GanvModule* module) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(module)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module)); GanvModuleImpl* impl = module->impl; Metrics m; @@ -331,7 +331,7 @@ resize_right(GanvModule* module) static void resize_down(GanvModule* module) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(module)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module)); GanvModuleImpl* impl = module->impl; Metrics m; @@ -414,7 +414,7 @@ layout(GanvNode* self) GanvModule* module = GANV_MODULE(self); GanvModuleImpl* impl = module->impl; GanvNode* node = GANV_NODE(self); - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(module)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module)); double label_w = 0.0; double label_h = 0.0; @@ -468,7 +468,7 @@ static void ganv_module_add_port(GanvModule* module, GanvPort* port) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(module)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module)); GanvModuleImpl* impl = module->impl; const double width = ganv_port_get_natural_width(port); @@ -640,7 +640,7 @@ ganv_module_point(GanvItem* item, double x, double y, GanvItem** actual_item) *actual_item = NULL; d = GANV_ITEM_GET_CLASS(port)->point( - port, x - port->x, y - port->y, actual_item); + port, x - port->impl->x, y - port->impl->y, actual_item); if (*actual_item) { // Point is inside a port @@ -719,7 +719,7 @@ ganv_module_get_empty_port_breadth(const GanvModule* module) double ganv_module_get_empty_port_depth(const GanvModule* module) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(module)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(module)); return ganv_canvas_get_font_size(canvas) * 1.1; } @@ -84,8 +84,7 @@ static void ganv_node_realize(GanvItem* item) { GANV_ITEM_CLASS(parent_class)->realize(item); - ganv_canvas_add_node(GANV_CANVAS(item->canvas), - GANV_NODE(item)); + ganv_canvas_add_node(ganv_item_get_canvas(item), GANV_NODE(item)); } static void @@ -103,16 +102,16 @@ ganv_node_destroy(GtkObject* object) GanvItem* item = GANV_ITEM(object); ganv_node_disconnect(node); - if (item->canvas) { - ganv_canvas_remove_node(GANV_CANVAS(item->canvas), node); + if (item->impl->canvas) { + ganv_canvas_remove_node(item->impl->canvas, node); } if (GTK_OBJECT_CLASS(parent_class)->destroy) { (*GTK_OBJECT_CLASS(parent_class)->destroy)(object); } - impl->partner = NULL; - item->canvas = NULL; + impl->partner = NULL; + item->impl->canvas = NULL; } static void @@ -154,21 +153,21 @@ ganv_node_set_property(GObject* object, if (impl->selected != g_value_get_boolean(value)) { GanvItem* item = GANV_ITEM(object); impl->selected = g_value_get_boolean(value); - if (item->canvas) { + if (item->impl->canvas) { if (impl->selected) { - ganv_canvas_select_node(GANV_CANVAS(item->canvas), node); + ganv_canvas_select_node(ganv_item_get_canvas(item), node); } else { - ganv_canvas_unselect_node(GANV_CANVAS(item->canvas), node); + ganv_canvas_unselect_node(ganv_item_get_canvas(item), node); } ganv_item_request_update(item); } } break; case PROP_CANVAS: - if (!GANV_ITEM(object)->parent) { + if (!GANV_ITEM(object)->impl->parent) { GanvCanvas* canvas = GANV_CANVAS(g_value_get_object(value)); g_object_set(object, "parent", ganv_canvas_root(canvas), NULL); - ganv_canvas_add_node(GANV_CANVAS(canvas), node); + ganv_canvas_add_node(canvas, node); } else { g_warning("Cannot change `canvas' property after construction"); } @@ -213,7 +212,7 @@ ganv_node_get_property(GObject* object, GET_CASE(DRAGGABLE, boolean, impl->draggable); GET_CASE(GRABBED, boolean, impl->grabbed); case PROP_CANVAS: - g_value_set_object(value, GANV_ITEM(object)->canvas); + g_value_set_object(value, ganv_item_get_canvas(GANV_ITEM(object))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -229,10 +228,10 @@ ganv_node_default_tail_vector(const GanvNode* self, double* dx, double* dy) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(self)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(self)); - *x = GANV_ITEM(self)->x; - *y = GANV_ITEM(self)->y; + *x = GANV_ITEM(self)->impl->x; + *y = GANV_ITEM(self)->impl->y; switch (ganv_canvas_get_direction(canvas)) { case GANV_DIRECTION_RIGHT: @@ -245,7 +244,7 @@ ganv_node_default_tail_vector(const GanvNode* self, break; } - ganv_item_i2w(GANV_ITEM(self)->parent, x, y); + ganv_item_i2w(GANV_ITEM(self)->impl->parent, x, y); } static void @@ -256,10 +255,10 @@ ganv_node_default_head_vector(const GanvNode* self, double* dx, double* dy) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(self)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(self)); - *x = GANV_ITEM(self)->x; - *y = GANV_ITEM(self)->y; + *x = GANV_ITEM(self)->impl->x; + *y = GANV_ITEM(self)->impl->y; switch (ganv_canvas_get_direction(canvas)) { case GANV_DIRECTION_RIGHT: @@ -272,7 +271,7 @@ ganv_node_default_head_vector(const GanvNode* self, break; } - ganv_item_i2w(GANV_ITEM(self)->parent, x, y); + ganv_item_i2w(GANV_ITEM(self)->impl->parent, x, y); } void @@ -355,7 +354,7 @@ ganv_node_default_tick(GanvNode* self, static void ganv_node_default_disconnect(GanvNode* node) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(node)); if (canvas) { ganv_canvas_for_each_edge_on( canvas, node, (GanvEdgeFunc)ganv_edge_disconnect, NULL); @@ -367,7 +366,7 @@ ganv_node_default_move(GanvNode* node, double dx, double dy) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(node)); ganv_item_move(GANV_ITEM(node), dx, dy); ganv_canvas_for_each_edge_on( canvas, node, (GanvEdgeFunc)ganv_edge_update_location, NULL); @@ -378,7 +377,7 @@ ganv_node_default_move_to(GanvNode* node, double x, double y) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(node)); ganv_item_set(GANV_ITEM(node), "x", x, "y", y, @@ -396,8 +395,8 @@ static void ganv_node_default_resize(GanvNode* node) { GanvItem* item = GANV_ITEM(node); - if (GANV_IS_NODE(item->parent)) { - ganv_node_resize(GANV_NODE(item->parent)); + if (GANV_IS_NODE(item->impl->parent)) { + ganv_node_resize(GANV_NODE(item->impl->parent)); } } @@ -415,7 +414,7 @@ ganv_node_default_event(GanvItem* item, GdkEvent* event) { GanvNode* node = GANV_NODE(item); - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(node)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(node)); // FIXME: put these somewhere better static double last_x, last_y; @@ -462,8 +461,8 @@ ganv_node_default_event(GanvItem* item, if (selected) { ganv_canvas_selection_move_finished(canvas); } else { - const double x = GANV_ITEM(node)->x; - const double y = GANV_ITEM(node)->y; + const double x = GANV_ITEM(node)->impl->x; + const double y = GANV_ITEM(node)->impl->y; g_signal_emit(node, signal_moved, 0, x, y, NULL); } } else { @@ -771,12 +770,65 @@ ganv_node_get_border_width(const GanvNode* node) return node->impl->border_width; } +void +ganv_node_set_border_width(const GanvNode* node, double border_width) +{ + node->impl->border_width = border_width; + ganv_item_request_update(GANV_ITEM(node)); +} + double ganv_node_get_dash_length(const GanvNode* node) { return node->impl->dash_length; } +void +ganv_node_set_dash_length(const GanvNode* node, double dash_length) +{ + node->impl->dash_length = dash_length; + ganv_item_request_update(GANV_ITEM(node)); +} + +double +ganv_node_get_dash_offset(const GanvNode* node) +{ + return node->impl->dash_offset; +} + +void +ganv_node_set_dash_offset(const GanvNode* node, double dash_offset) +{ + node->impl->dash_offset = dash_offset; + ganv_item_request_update(GANV_ITEM(node)); +} + +guint +ganv_node_get_fill_color(const GanvNode* node) +{ + return node->impl->fill_color; +} + +void +ganv_node_set_fill_color(const GanvNode* node, guint fill_color) +{ + node->impl->fill_color = fill_color; + ganv_item_request_update(GANV_ITEM(node)); +} + +guint +ganv_node_get_border_color(const GanvNode* node) +{ + return node->impl->border_color; +} + +void +ganv_node_set_border_color(const GanvNode* node, guint border_color) +{ + node->impl->border_color = border_color; + ganv_item_request_update(GANV_ITEM(node)); +} + GanvNode* ganv_node_get_partner(const GanvNode* node) { @@ -69,7 +69,7 @@ ganv_port_destroy(GtkObject* object) GanvItem* item = GANV_ITEM(object); GanvPort* port = GANV_PORT(object); - GanvCanvas* canvas = GANV_CANVAS(item->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(item); if (canvas) { if (port->impl->is_input) { ganv_canvas_for_each_edge_to( @@ -130,7 +130,7 @@ ganv_port_draw(GanvItem* item, cairo_t* cr, double cx, double cy, double cw, double ch) { GanvPort* port = GANV_PORT(item); - GanvCanvas* canvas = GANV_CANVAS(item->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(item); // Draw Box GanvItemClass* item_class = GANV_ITEM_CLASS(parent_class); @@ -168,10 +168,10 @@ ganv_port_tail_vector(const GanvNode* self, { GanvPort* port = GANV_PORT(self); GanvItem* item = &port->box.node.item; - GanvCanvas* canvas = GANV_CANVAS(item->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(item); - const double px = item->x; - const double py = item->y; + const double px = item->impl->x; + const double py = item->impl->y; switch (ganv_canvas_get_direction(canvas)) { case GANV_DIRECTION_RIGHT: @@ -188,7 +188,7 @@ ganv_port_tail_vector(const GanvNode* self, break; } - ganv_item_i2w(item->parent, x, y); + ganv_item_i2w(item->impl->parent, x, y); } static void @@ -201,10 +201,10 @@ ganv_port_head_vector(const GanvNode* self, { GanvPort* port = GANV_PORT(self); GanvItem* item = &port->box.node.item; - GanvCanvas* canvas = GANV_CANVAS(item->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(item); - const double px = item->x; - const double py = item->y; + const double px = item->impl->x; + const double py = item->impl->y; switch (ganv_canvas_get_direction(canvas)) { case GANV_DIRECTION_RIGHT: @@ -221,7 +221,7 @@ ganv_port_head_vector(const GanvNode* self, break; } - ganv_item_i2w(item->parent, x, y); + ganv_item_i2w(item->impl->parent, x, y); } static void @@ -229,7 +229,7 @@ ganv_port_place_value_label(GanvPort* port) { GanvPortControl* control = port->impl->control; if (control && control->label) { - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(port)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(port)); const double port_w = ganv_box_get_width(&port->box); const double label_w = control->label->impl->coords.width; if (ganv_canvas_get_direction(canvas) == GANV_DIRECTION_RIGHT) { @@ -327,7 +327,7 @@ ganv_port_set_height(GanvBox* box, static gboolean ganv_port_event(GanvItem* item, GdkEvent* event) { - GanvCanvas* canvas = GANV_CANVAS(item->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(item); return ganv_canvas_port_event(canvas, GANV_PORT(item), event); } @@ -414,7 +414,7 @@ ganv_port_new(GanvModule* module, node->impl->draggable = FALSE; node->impl->border_width = 1.0; - GanvCanvas* canvas = GANV_CANVAS(GANV_ITEM(port)->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(GANV_ITEM(port)); ganv_port_set_direction(port, ganv_canvas_get_direction(canvas)); return port; @@ -633,7 +633,7 @@ ganv_port_set_control_max(GanvPort* port, double ganv_port_get_natural_width(const GanvPort* port) { - GanvCanvas* const canvas = GANV_CANVAS(GANV_ITEM(port)->canvas); + GanvCanvas* const canvas = ganv_item_get_canvas(GANV_ITEM(port)); GanvText* const label = port->box.node.impl->label; double w = 0.0; if (ganv_canvas_get_direction(canvas) == GANV_DIRECTION_DOWN) { @@ -658,7 +658,7 @@ ganv_port_get_natural_width(const GanvPort* port) GanvModule* ganv_port_get_module(const GanvPort* port) { - return GANV_MODULE(GANV_ITEM(port)->parent); + return GANV_MODULE(GANV_ITEM(port)->impl->parent); } float @@ -90,7 +90,7 @@ ganv_text_layout(GanvText* text) { GanvTextImpl* impl = text->impl; GanvItem* item = GANV_ITEM(text); - GanvCanvas* canvas = GANV_CANVAS(item->canvas); + GanvCanvas* canvas = ganv_item_get_canvas(item); GtkWidget* widget = GTK_WIDGET(canvas); double font_size = ganv_canvas_get_font_size(canvas); guint color = 0xFFFFFFFF; @@ -164,8 +164,8 @@ ganv_text_set_property(GObject* object, free(impl->text); impl->text = g_value_dup_string(value); impl->needs_layout = TRUE; - if (GANV_IS_NODE(GANV_ITEM(text)->parent)) { - ganv_node_resize(GANV_NODE(GANV_ITEM(text)->parent)); + if (GANV_IS_NODE(GANV_ITEM(text)->impl->parent)) { + ganv_node_resize(GANV_NODE(GANV_ITEM(text)->impl->parent)); } break; default: @@ -236,11 +236,11 @@ ganv_text_update(GanvItem* item, int flags) parent_class->update(item, flags); // Update world-relative bounding box - ganv_text_bounds(item, &item->x1, &item->y1, &item->x2, &item->y2); - ganv_item_i2w_pair(item, &item->x1, &item->y1, &item->x2, &item->y2); + ganv_text_bounds(item, &item->impl->x1, &item->impl->y1, &item->impl->x2, &item->impl->y2); + ganv_item_i2w_pair(item, &item->impl->x1, &item->impl->y1, &item->impl->x2, &item->impl->y2); ganv_canvas_request_redraw_w( - item->canvas, item->x1, item->y1, item->x2, item->y2); + item->impl->canvas, item->impl->x1, item->impl->y1, item->impl->x2, item->impl->y2); } static double diff --git a/src/widget.c b/src/widget.c index ca391d6..0702ca5 100644 --- a/src/widget.c +++ b/src/widget.c @@ -45,27 +45,30 @@ enum { static void ganv_widget_init(GanvWidget* witem) { - witem->x = 0.0; - witem->y = 0.0; - witem->width = 0.0; - witem->height = 0.0; - witem->anchor = GTK_ANCHOR_NW; - witem->size_pixels = FALSE; + GanvWidgetImpl* impl = G_TYPE_INSTANCE_GET_PRIVATE( + witem, GANV_TYPE_WIDGET, GanvWidgetImpl); + + witem->impl = impl; + witem->impl->x = 0.0; + witem->impl->y = 0.0; + witem->impl->width = 0.0; + witem->impl->height = 0.0; + witem->impl->anchor = GTK_ANCHOR_NW; + witem->impl->size_pixels = FALSE; } static void ganv_widget_destroy(GtkObject* object) { - g_return_if_fail(object != NULL); g_return_if_fail(GANV_IS_WIDGET(object)); GanvWidget* witem = GANV_WIDGET(object); - if (witem->widget && !witem->in_destroy) { - g_signal_handler_disconnect(witem->widget, witem->destroy_id); - gtk_widget_destroy(witem->widget); - witem->widget = NULL; + if (witem->impl->widget && !witem->impl->in_destroy) { + g_signal_handler_disconnect(witem->impl->widget, witem->impl->destroy_id); + gtk_widget_destroy(witem->impl->widget); + witem->impl->widget = NULL; } if (GTK_OBJECT_CLASS(parent_class)->destroy) { @@ -80,44 +83,44 @@ recalc_bounds(GanvWidget* witem) /* Get world coordinates */ - double wx = witem->x; - double wy = witem->y; + double wx = witem->impl->x; + double wy = witem->impl->y; ganv_item_i2w(item, &wx, &wy); /* Get canvas pixel coordinates */ - ganv_canvas_w2c(item->canvas, wx, wy, &witem->cx, &witem->cy); + ganv_canvas_w2c(item->impl->canvas, wx, wy, &witem->impl->cx, &witem->impl->cy); /* Anchor widget item */ - switch (witem->anchor) { + switch (witem->impl->anchor) { case GTK_ANCHOR_N: case GTK_ANCHOR_CENTER: case GTK_ANCHOR_S: - witem->cx -= witem->cwidth / 2; + witem->impl->cx -= witem->impl->cwidth / 2; break; case GTK_ANCHOR_NE: case GTK_ANCHOR_E: case GTK_ANCHOR_SE: - witem->cx -= witem->cwidth; + witem->impl->cx -= witem->impl->cwidth; break; default: break; } - switch (witem->anchor) { + switch (witem->impl->anchor) { case GTK_ANCHOR_W: case GTK_ANCHOR_CENTER: case GTK_ANCHOR_E: - witem->cy -= witem->cheight / 2; + witem->impl->cy -= witem->impl->cheight / 2; break; case GTK_ANCHOR_SW: case GTK_ANCHOR_S: case GTK_ANCHOR_SE: - witem->cy -= witem->cheight; + witem->impl->cy -= witem->impl->cheight; break; default: @@ -126,17 +129,17 @@ recalc_bounds(GanvWidget* witem) /* Bounds */ - item->x1 = witem->cx; - item->y1 = witem->cy; - item->x2 = witem->cx + witem->cwidth; - item->y2 = witem->cy + witem->cheight; + item->impl->x1 = witem->impl->cx; + item->impl->y1 = witem->impl->cy; + item->impl->x2 = witem->impl->cx + witem->impl->cwidth; + item->impl->y2 = witem->impl->cy + witem->impl->cheight; int zoom_xofs, zoom_yofs; - ganv_canvas_get_zoom_offsets(item->canvas, &zoom_xofs, &zoom_yofs); - if (witem->widget) { - gtk_layout_move(GTK_LAYOUT(item->canvas), witem->widget, - witem->cx + zoom_xofs, - witem->cy + zoom_yofs); + ganv_canvas_get_zoom_offsets(item->impl->canvas, &zoom_xofs, &zoom_yofs); + if (witem->impl->widget) { + gtk_layout_move(GTK_LAYOUT(item->impl->canvas), witem->impl->widget, + witem->impl->cx + zoom_xofs, + witem->impl->cy + zoom_yofs); } } @@ -145,7 +148,7 @@ do_destroy(GtkObject* object, gpointer data) { GanvWidget* witem = GANV_WIDGET(data); - witem->in_destroy = TRUE; + witem->impl->in_destroy = TRUE; gtk_object_destroy(GTK_OBJECT(data)); } @@ -163,66 +166,66 @@ ganv_widget_set_property(GObject* object, switch (param_id) { case PROP_WIDGET: - if (witem->widget) { - g_signal_handler_disconnect(witem->widget, witem->destroy_id); - gtk_container_remove(GTK_CONTAINER(item->canvas), witem->widget); + if (witem->impl->widget) { + g_signal_handler_disconnect(witem->impl->widget, witem->impl->destroy_id); + gtk_container_remove(GTK_CONTAINER(item->impl->canvas), witem->impl->widget); } obj = (GObject*)g_value_get_object(value); if (obj) { - witem->widget = GTK_WIDGET(obj); - witem->destroy_id = g_signal_connect(obj, "destroy", + witem->impl->widget = GTK_WIDGET(obj); + witem->impl->destroy_id = g_signal_connect(obj, "destroy", G_CALLBACK(do_destroy), witem); int zoom_xofs, zoom_yofs; - ganv_canvas_get_zoom_offsets(item->canvas, &zoom_xofs, &zoom_yofs); + ganv_canvas_get_zoom_offsets(item->impl->canvas, &zoom_xofs, &zoom_yofs); - gtk_layout_put(GTK_LAYOUT(item->canvas), witem->widget, - witem->cx + zoom_xofs, - witem->cy + zoom_yofs); + gtk_layout_put(GTK_LAYOUT(item->impl->canvas), witem->impl->widget, + witem->impl->cx + zoom_xofs, + witem->impl->cy + zoom_yofs); } update = TRUE; break; case PROP_X: - if (witem->x != g_value_get_double(value)) { - witem->x = g_value_get_double(value); + if (witem->impl->x != g_value_get_double(value)) { + witem->impl->x = g_value_get_double(value); calc_bounds = TRUE; } break; case PROP_Y: - if (witem->y != g_value_get_double(value)) { - witem->y = g_value_get_double(value); + if (witem->impl->y != g_value_get_double(value)) { + witem->impl->y = g_value_get_double(value); calc_bounds = TRUE; } break; case PROP_WIDTH: - if (witem->width != fabs(g_value_get_double(value))) { - witem->width = fabs(g_value_get_double(value)); + if (witem->impl->width != fabs(g_value_get_double(value))) { + witem->impl->width = fabs(g_value_get_double(value)); update = TRUE; } break; case PROP_HEIGHT: - if (witem->height != fabs(g_value_get_double(value))) { - witem->height = fabs(g_value_get_double(value)); + if (witem->impl->height != fabs(g_value_get_double(value))) { + witem->impl->height = fabs(g_value_get_double(value)); update = TRUE; } break; case PROP_ANCHOR: - if (witem->anchor != (GtkAnchorType)g_value_get_enum(value)) { - witem->anchor = g_value_get_enum(value); + if (witem->impl->anchor != (GtkAnchorType)g_value_get_enum(value)) { + witem->impl->anchor = g_value_get_enum(value); update = TRUE; } break; case PROP_SIZE_PIXELS: - if (witem->size_pixels != g_value_get_boolean(value)) { - witem->size_pixels = g_value_get_boolean(value); + if (witem->impl->size_pixels != g_value_get_boolean(value)) { + witem->impl->size_pixels = g_value_get_boolean(value); update = TRUE; } break; @@ -254,31 +257,31 @@ ganv_widget_get_property(GObject* object, switch (param_id) { case PROP_WIDGET: - g_value_set_object(value, (GObject*)witem->widget); + g_value_set_object(value, (GObject*)witem->impl->widget); break; case PROP_X: - g_value_set_double(value, witem->x); + g_value_set_double(value, witem->impl->x); break; case PROP_Y: - g_value_set_double(value, witem->y); + g_value_set_double(value, witem->impl->y); break; case PROP_WIDTH: - g_value_set_double(value, witem->width); + g_value_set_double(value, witem->impl->width); break; case PROP_HEIGHT: - g_value_set_double(value, witem->height); + g_value_set_double(value, witem->impl->height); break; case PROP_ANCHOR: - g_value_set_enum(value, witem->anchor); + g_value_set_enum(value, witem->impl->anchor); break; case PROP_SIZE_PIXELS: - g_value_set_boolean(value, witem->size_pixels); + g_value_set_boolean(value, witem->impl->size_pixels); break; default: @@ -296,20 +299,20 @@ ganv_widget_update(GanvItem* item, int flags) (*parent_class->update)(item, flags); } - if (witem->widget) { - const double pixels_per_unit = ganv_canvas_get_zoom(item->canvas); - if (witem->size_pixels) { - witem->cwidth = (int)(witem->width + 0.5); - witem->cheight = (int)(witem->height + 0.5); + if (witem->impl->widget) { + const double pixels_per_unit = ganv_canvas_get_zoom(item->impl->canvas); + if (witem->impl->size_pixels) { + witem->impl->cwidth = (int)(witem->impl->width + 0.5); + witem->impl->cheight = (int)(witem->impl->height + 0.5); } else { - witem->cwidth = (int)(witem->width * pixels_per_unit + 0.5); - witem->cheight = (int)(witem->height * pixels_per_unit + 0.5); + witem->impl->cwidth = (int)(witem->impl->width * pixels_per_unit + 0.5); + witem->impl->cheight = (int)(witem->impl->height * pixels_per_unit + 0.5); } - gtk_widget_set_size_request(witem->widget, witem->cwidth, witem->cheight); + gtk_widget_set_size_request(witem->impl->widget, witem->impl->cwidth, witem->impl->cheight); } else { - witem->cwidth = 0.0; - witem->cheight = 0.0; + witem->impl->cwidth = 0.0; + witem->impl->cheight = 0.0; } recalc_bounds(witem); @@ -321,8 +324,8 @@ ganv_widget_draw(GanvItem* item, { GanvWidget* witem = GANV_WIDGET(item); - if (witem->widget) { - gtk_widget_queue_draw(witem->widget); + if (witem->impl->widget) { + gtk_widget_queue_draw(witem->impl->widget); } } @@ -334,12 +337,12 @@ ganv_widget_point(GanvItem* item, double x, double y, GanvItem** actual_item) *actual_item = item; double x1, y1; - ganv_canvas_c2w(item->canvas, witem->cx, witem->cy, &x1, &y1); + ganv_canvas_c2w(item->impl->canvas, witem->impl->cx, witem->impl->cy, &x1, &y1); - const double pixels_per_unit = ganv_canvas_get_zoom(item->canvas); + const double pixels_per_unit = ganv_canvas_get_zoom(item->impl->canvas); - double x2 = x1 + (witem->cwidth - 1) / pixels_per_unit; - double y2 = y1 + (witem->cheight - 1) / pixels_per_unit; + double x2 = x1 + (witem->impl->cwidth - 1) / pixels_per_unit; + double y2 = y1 + (witem->impl->cheight - 1) / pixels_per_unit; /* Is point inside widget bounds? */ @@ -375,10 +378,10 @@ ganv_widget_bounds(GanvItem* item, double* x1, double* y1, double* x2, double* y { GanvWidget* witem = GANV_WIDGET(item); - *x1 = witem->x; - *y1 = witem->y; + *x1 = witem->impl->x; + *y1 = witem->impl->y; - switch (witem->anchor) { + switch (witem->impl->anchor) { case GTK_ANCHOR_NW: case GTK_ANCHOR_W: case GTK_ANCHOR_SW: @@ -387,20 +390,20 @@ ganv_widget_bounds(GanvItem* item, double* x1, double* y1, double* x2, double* y case GTK_ANCHOR_N: case GTK_ANCHOR_CENTER: case GTK_ANCHOR_S: - *x1 -= witem->width / 2.0; + *x1 -= witem->impl->width / 2.0; break; case GTK_ANCHOR_NE: case GTK_ANCHOR_E: case GTK_ANCHOR_SE: - *x1 -= witem->width; + *x1 -= witem->impl->width; break; default: break; } - switch (witem->anchor) { + switch (witem->impl->anchor) { case GTK_ANCHOR_NW: case GTK_ANCHOR_N: case GTK_ANCHOR_NE: @@ -409,21 +412,21 @@ ganv_widget_bounds(GanvItem* item, double* x1, double* y1, double* x2, double* y case GTK_ANCHOR_W: case GTK_ANCHOR_CENTER: case GTK_ANCHOR_E: - *y1 -= witem->height / 2.0; + *y1 -= witem->impl->height / 2.0; break; case GTK_ANCHOR_SW: case GTK_ANCHOR_S: case GTK_ANCHOR_SE: - *y1 -= witem->height; + *y1 -= witem->impl->height; break; default: break; } - *x2 = *x1 + witem->width; - *y2 = *y1 + witem->height; + *x2 = *x1 + witem->impl->width; + *y2 = *y1 + witem->impl->height; } static void @@ -435,6 +438,8 @@ ganv_widget_class_init(GanvWidgetClass* klass) parent_class = g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(GanvWidgetImpl)); + gobject_class->set_property = ganv_widget_set_property; gobject_class->get_property = ganv_widget_get_property; |