[anjuta-extras/class-inherit-refactor] class-inheritance: Initial rewrite of class inheritance
- From: Naba Kumar <naba src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta-extras/class-inherit-refactor] class-inheritance: Initial rewrite of class inheritance
- Date: Tue, 2 Mar 2010 21:01:23 +0000 (UTC)
commit f209744505ef933477da3f780f66c386addf0e68
Author: Naba Kumar <naba gnome org>
Date: Tue Mar 2 23:00:37 2010 +0200
class-inheritance: Initial rewrite of class inheritance
Optimized class expansion and collapse, group member variables and member
methods into separate sections. Separate indication for methods. Merged
method prototypes and definitions into single entry, navigating to definition.
plugins/class-inheritance/class-callbacks.c | 189 ++--
plugins/class-inheritance/class-callbacks.h | 25 +-
plugins/class-inheritance/class-inherit.c | 1552 +++++++++++++--------------
plugins/class-inheritance/class-inherit.h | 103 ++-
plugins/class-inheritance/plugin.c | 28 +-
plugins/class-inheritance/plugin.h | 9 +-
6 files changed, 914 insertions(+), 992 deletions(-)
---
diff --git a/plugins/class-inheritance/class-callbacks.c b/plugins/class-inheritance/class-callbacks.c
index eb3f77b..c0535aa 100644
--- a/plugins/class-inheritance/class-callbacks.c
+++ b/plugins/class-inheritance/class-callbacks.c
@@ -52,130 +52,122 @@ on_canvas_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
}
gint
-on_nodedata_expanded_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
+on_expanded_class_title_event (GnomeCanvasItem *item, GdkEvent *event,
+ ClsNode *cls_node)
{
- AnjutaClassInheritance *plugin;
- NodeData *nodedata;
- nodedata = (NodeData*)data;
- plugin = nodedata->plugin;
-
switch (event->type)
{
- case GDK_2BUTTON_PRESS: /* double click */
- break;
-
case GDK_BUTTON_PRESS: /* single click */
- if (event->button.button == 1) {
- NodeExpansionStatus *node_status;
- if ((node_status =
- (NodeExpansionStatus*) g_tree_lookup (plugin->expansion_node_list,
- GINT_TO_POINTER (nodedata->klass_id)))
- == NULL)
- {
- break;
- }
- else if (strcmp (nodedata->sub_item, NODE_SHOW_ALL_MEMBERS_STR) == 0)
- {
- node_status->expansion_status = NODE_FULL_EXPANDED;
- class_inheritance_update_graph (plugin);
- }
- else /* it's a class member. Take line && uri of definition */
- { /* and reach them */
- const gchar *file;
- gint line;
-
- file = g_object_get_data (G_OBJECT (item), "__filepath");
- line = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "__line"));
-
- if (file)
- {
- GFile* gfile;
-
- gfile = g_file_new_for_path (file);
-
- /* Goto uri line */
- IAnjutaDocumentManager *dm;
- dm = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
- IAnjutaDocumentManager, NULL);
- if (dm)
- {
- ianjuta_document_manager_goto_file_line (dm, gfile, line, NULL);
- }
-
- if (gfile)
- g_object_unref (gfile);
- }
- }
+ if (event->button.button == 1 &&
+ cls_node->expansion_status != CLS_NODE_COLLAPSED &&
+ cls_node_collapse (cls_node))
+ {
+ cls_inherit_layout (cls_node->plugin);
+ cls_inherit_draw(cls_node->plugin);
+ return TRUE;
}
break;
case GDK_ENTER_NOTIFY: /* mouse entered in item's area */
- gnome_canvas_item_set (nodedata->canvas_item,
+ /* Make the outline wide */
+ gnome_canvas_item_set (item,
"fill_color_gdk",
- &plugin->canvas->style->base[GTK_STATE_SELECTED],
+ &cls_node->canvas->style->bg[GTK_STATE_PRELIGHT],
NULL);
return TRUE;
case GDK_LEAVE_NOTIFY: /* mouse exited item's area */
- gnome_canvas_item_set (nodedata->canvas_item,
+ /* Make the outline thin */
+ gnome_canvas_item_set (item,
"fill_color_gdk",
- &plugin->canvas->style->base[GTK_STATE_NORMAL],
+ &cls_node->canvas->style->bg[GTK_STATE_ACTIVE],
NULL);
return TRUE;
default:
break;
}
-
return FALSE;
-
}
-
gint
-on_collapsed_class_nodedata_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
+on_expanded_class_item_event (GnomeCanvasItem *item, GdkEvent *event,
+ gpointer data)
{
AnjutaClassInheritance *plugin;
- NodeData *nodedata;
+ ClsNodeItem *node_item;
- nodedata = (NodeData*)data;
- plugin = nodedata->plugin;
+ node_item = (ClsNodeItem*)data;
+ plugin = node_item->cls_node->plugin;
switch (event->type)
{
case GDK_BUTTON_PRESS: /* single click */
- if (event->button.button == 1 && !nodedata->anchored)
+ if (event->button.button == 1)
{
- NodeExpansionStatus *node_status;
- nodedata->anchored = TRUE;
+ /* Goto uri line */
+ if (node_item->file)
+ {
+ IAnjutaDocumentManager *dm;
+ dm = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
+ IAnjutaDocumentManager, NULL);
+ if (dm)
+ ianjuta_document_manager_goto_file_line (dm,
+ node_item->file,
+ node_item->line,
+ NULL);
+ }
+ }
+ break;
+
+ case GDK_ENTER_NOTIFY: /* mouse entered in item's area */
+ gnome_canvas_item_set (node_item->canvas_node_item,
+ "fill_color_gdk",
+ &node_item->cls_node->canvas->style->base[GTK_STATE_SELECTED],
+ NULL);
+ return TRUE;
- node_status = g_new0 (NodeExpansionStatus, 1);
- node_status->klass_id = nodedata->klass_id;
- /* set to half. This will display at least NODE_HALF_DISPLAY_ELEM_NUM.
- * User will decide whether to show all elements or not. */
- node_status->expansion_status = NODE_HALF_EXPANDED;
+ case GDK_LEAVE_NOTIFY: /* mouse exited item's area */
+ gnome_canvas_item_set (node_item->canvas_node_item,
+ "fill_color_gdk",
+ &node_item->cls_node->canvas->style->base[GTK_STATE_NORMAL],
+ NULL);
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
- /* insert the class name to the hash_table */
- g_tree_insert (nodedata->plugin->expansion_node_list,
- GINT_TO_POINTER (nodedata->klass_id),
- node_status);
- class_inheritance_update_graph (nodedata->plugin);
- return TRUE;
+gint
+on_expanded_class_more_event (GnomeCanvasItem *item, GdkEvent *event,
+ ClsNode *cls_node)
+{
+ switch (event->type)
+ {
+ case GDK_2BUTTON_PRESS: /* double click */
+ break;
+
+ case GDK_BUTTON_PRESS: /* single click */
+ if (event->button.button == 1 &&
+ cls_node->expansion_status == CLS_NODE_SEMI_EXPANDED &&
+ cls_node_expand (cls_node, CLS_NODE_FULL_EXPANDED))
+ {
+ cls_inherit_layout (cls_node->plugin);
+ cls_inherit_draw(cls_node->plugin);
}
break;
case GDK_ENTER_NOTIFY: /* mouse entered in item's area */
- /* Make the outline wide */
- gnome_canvas_item_set (nodedata->canvas_item,
+ gnome_canvas_item_set (item,
"fill_color_gdk",
- &plugin->canvas->style->base[GTK_STATE_SELECTED],
+ &cls_node->canvas->style->bg[GTK_STATE_PRELIGHT],
NULL);
return TRUE;
case GDK_LEAVE_NOTIFY: /* mouse exited item's area */
- /* Make the outline thin */
- gnome_canvas_item_set (nodedata->canvas_item,
+ gnome_canvas_item_set (item,
"fill_color_gdk",
- &plugin->canvas->style->base[GTK_STATE_NORMAL],
+ &cls_node->canvas->style->bg[GTK_STATE_ACTIVE],
NULL);
return TRUE;
default:
@@ -186,46 +178,41 @@ on_collapsed_class_nodedata_event (GnomeCanvasItem *item, GdkEvent *event, gpoin
}
gint
-on_expanded_class_nodedata_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
+on_collapsed_class_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
{
AnjutaClassInheritance *plugin;
- NodeData *nodedata;
+ ClsNode *cls_node;
- nodedata = (NodeData*)data;
- plugin = nodedata->plugin;
+ cls_node = (ClsNode*)data;
+ plugin = cls_node->plugin;
switch (event->type)
{
case GDK_BUTTON_PRESS: /* single click */
- if (event->button.button == 1 && nodedata->anchored)
+ if (event->button.button == 1)
{
- nodedata->anchored = FALSE;
-
- /* remove the key from the hash table, if present */
- if (g_tree_lookup (nodedata->plugin->expansion_node_list,
- GINT_TO_POINTER (nodedata->klass_id)))
+ if (cls_node_expand (cls_node, CLS_NODE_SEMI_EXPANDED))
{
- g_tree_remove (nodedata->plugin->expansion_node_list,
- GINT_TO_POINTER (nodedata->klass_id));
- }
- class_inheritance_update_graph (nodedata->plugin);
+ cls_inherit_layout (plugin);
+ cls_inherit_draw(plugin);
+ }
return TRUE;
}
break;
case GDK_ENTER_NOTIFY: /* mouse entered in item's area */
/* Make the outline wide */
- gnome_canvas_item_set (nodedata->canvas_item,
+ gnome_canvas_item_set (item,
"fill_color_gdk",
- &plugin->canvas->style->bg[GTK_STATE_PRELIGHT],
+ &plugin->canvas->style->base[GTK_STATE_SELECTED],
NULL);
return TRUE;
case GDK_LEAVE_NOTIFY: /* mouse exited item's area */
/* Make the outline thin */
- gnome_canvas_item_set (nodedata->canvas_item,
+ gnome_canvas_item_set (item,
"fill_color_gdk",
- &plugin->canvas->style->bg[GTK_STATE_ACTIVE],
+ &plugin->canvas->style->base[GTK_STATE_NORMAL],
NULL);
return TRUE;
default:
@@ -242,7 +229,7 @@ void
on_update_menu_item_selected (GtkMenuItem *item,
AnjutaClassInheritance *plugin)
{
- class_inheritance_update_graph (plugin);
+ cls_inherit_update (plugin);
}
/*----------------------------------------------------------------------------
@@ -252,5 +239,5 @@ void
on_style_set (GtkWidget *widget, GtkStyle *previous_style,
AnjutaClassInheritance *plugin)
{
- class_inheritance_update_graph (plugin);
+ cls_inherit_update (plugin);
}
diff --git a/plugins/class-inheritance/class-callbacks.h b/plugins/class-inheritance/class-callbacks.h
index e51bff7..3ba96d2 100644
--- a/plugins/class-inheritance/class-callbacks.h
+++ b/plugins/class-inheritance/class-callbacks.h
@@ -23,21 +23,22 @@
#include "class-inherit.h"
gint on_canvas_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data);
-
-gint on_collapsed_class_nodedata_event (GnomeCanvasItem *item, GdkEvent *event,
- gpointer data);
-gint on_expanded_class_nodedata_event (GnomeCanvasItem *item, GdkEvent *event,
- gpointer data);
-
-gint on_nodedata_expanded_event (GnomeCanvasItem *item, GdkEvent *event,
- gpointer data);
-
-gint on_nodedata_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data);
-
void on_update_menu_item_selected (GtkMenuItem *item,
AnjutaClassInheritance *plugin);
-
void on_style_set (GtkWidget *widget, GtkStyle *previous_style,
AnjutaClassInheritance *plugin);
+
+/* Callbacks for expanded class node */
+gint on_expanded_class_title_event (GnomeCanvasItem *item, GdkEvent *event,
+ ClsNode *cls_node);
+gint on_expanded_class_item_event (GnomeCanvasItem *item, GdkEvent *event,
+ gpointer data);
+gint on_expanded_class_more_event (GnomeCanvasItem *item, GdkEvent *event,
+ ClsNode *cls_node);
+
+/* Callback for collapsed class node */
+gint on_collapsed_class_event (GnomeCanvasItem *item, GdkEvent *event,
+ gpointer data);
+
#endif /* _CLASS_CALLBACKS_H */
diff --git a/plugins/class-inheritance/class-inherit.c b/plugins/class-inheritance/class-inherit.c
index cd211b4..f847f33 100644
--- a/plugins/class-inheritance/class-inherit.c
+++ b/plugins/class-inheritance/class-inherit.c
@@ -1,6 +1,7 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
* Copyright (C) Massimo Cora' 2005 <maxcvs email it>
+ * 2009 Naba Kumar <naba gnome org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -46,6 +47,7 @@
#define NODE_NTH_TEXT(node,main_index,rec_index) \
((field_t*)ND_shape_info (node))->fld[main_index]->fld[rec_index]->lp->text
+#define GRAPH_TO_CANVAS_Y(y) (-y)
#define INCH_TO_PIXELS_CONVERSION_FACTOR 72
#define INCH_TO_PIXELS(inch_size) \
@@ -54,15 +56,22 @@
/* TODO: check for symbol_updated event, and check in the nodestatus's hashtable
for the nodes that are gone. In case remove them.
*/
+
typedef enum {
- CANVAS_ARROW_DIR_UP,
- CANVAS_ARROW_DIR_DOWN,
- CANVAS_ARROW_DIR_LEFT,
- CANVAS_ARROW_DIR_RIGHT
+ CLS_ARROW_DIR_UP,
+ CLS_ARROW_DIR_DOWN,
+ CLS_ARROW_DIR_LEFT,
+ CLS_ARROW_DIR_RIGHT
} CanvasArrowDir;
+typedef struct {
+ gdouble x1, y1, x2, y2;
+} ClsBox;
+
static GnomeCanvasItem*
-create_canvas_arrow_item (GtkWidget *canvas, CanvasArrowDir direction,
+create_canvas_arrow_item (GnomeCanvasGroup *canvas_group,
+ CanvasArrowDir direction,
+ const GdkColor *fill_color,
/* Bounding box */
gint x1, gint y1, gint x2, gint y2)
{
@@ -81,864 +90,779 @@ create_canvas_arrow_item (GtkWidget *canvas, CanvasArrowDir direction,
triangle->coords[6] = x1 + offset;
triangle->coords[7] = y1 + offset;
- item = gnome_canvas_item_new (gnome_canvas_root
- (GNOME_CANVAS (canvas)),
+ item = gnome_canvas_item_new (canvas_group,
gnome_canvas_polygon_get_type (),
"points", triangle,
"fill_color_gdk",
- &canvas->style->fg[GTK_STATE_NORMAL],
+ fill_color,
NULL);
gnome_canvas_points_unref (triangle);
return item;
}
-static void
-cls_inherit_nodestatus_destroy (NodeExpansionStatus *node) {
- g_free (node);
-}
-
-static gint
-gtree_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
+static GnomeCanvasItem*
+create_canvas_line_item (GnomeCanvasGroup *canvas_group, GdkColor *fill_color,
+ gint x1, gint y1, gint x2, gint y2)
{
- return GPOINTER_TO_INT(a) - GPOINTER_TO_INT(b);
+ GnomeCanvasItem *item;
+ GnomeCanvasPoints *points;
+
+ points = gnome_canvas_points_new (2);
+ points->coords[0] = x1;
+ points->coords[1] = y1;
+ points->coords[2] = x2;
+ points->coords[3] = y2;
+
+ item =
+ gnome_canvas_item_new (canvas_group,
+ gnome_canvas_line_get_type(),
+ "points", points,
+ "fill_color_gdk",
+ fill_color,
+ "width_units", 1.0,
+ NULL);
+ gnome_canvas_points_unref (points);
+ return item;
}
-gchar *
-class_inheritance_create_agnode_key_name (const IAnjutaSymbol* symbol)
+static void
+cls_node_item_free (ClsNodeItem *cls_item)
{
- const gchar *node_sym_name;
- gint node_sym_id;
- gchar *graph_node_name;
-
- g_return_val_if_fail (symbol != NULL, NULL);
-
-
- /* begin the key of a Agnode only a char, we should provide some hack
- * to make sure that each node can be different fom each other, even if it has
- * the same name as another node
- *
- * Let's concatenate the IAnjutaSymbol id with its name in such form:
- * 'id:name'.
- */
- node_sym_name = ianjuta_symbol_get_name (IANJUTA_SYMBOL (symbol), NULL);
- node_sym_id = ianjuta_symbol_get_id (IANJUTA_SYMBOL (symbol), NULL);
- graph_node_name = g_strdup_printf ("%d:%s", node_sym_id, node_sym_name);
-
- return graph_node_name;
+ g_free (cls_item->sym_name);
+ g_free (cls_item->args);
+ if (cls_item->file)
+ g_object_unref (cls_item->file);
+ if (cls_item->icon)
+ gdk_pixbuf_unref (cls_item->icon);
+ g_free (cls_item);
}
-IAnjutaSymbol *
-class_inheritance_get_symbol_from_agnode_key_name (AnjutaClassInheritance *plugin,
- const gchar *key)
-{
- IAnjutaSymbol * symbol;
- IAnjutaSymbolManager *sm;
-
- gchar **res = g_strsplit (key, ":", -1);
- gint sym_id = atoi (res[0]);
-
-
- g_return_val_if_fail (plugin != NULL, NULL);
-
- sm = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
- IAnjutaSymbolManager, NULL);
-
- symbol = ianjuta_symbol_manager_get_symbol_by_id (sm,
- sym_id,
- IANJUTA_SYMBOL_FIELD_SIMPLE,
- NULL);
-
- g_strfreev (res);
-
- return symbol;
-}
-
-/*----------------------------------------------------------------------------
- * initialize the internal graphviz structure.
- */
static void
-cls_inherit_graph_init (AnjutaClassInheritance *plugin, gchar* graph_label)
+cls_node_edge_free (ClsNodeEdge *cls_edge)
{
- Agsym_t *sym;
- gchar dpi_text[16];
-
- snprintf (dpi_text, 16, "%d", INCH_TO_PIXELS_CONVERSION_FACTOR);
- aginit ();
- plugin->graph = agopen (graph_label, AGDIGRAPH);
- plugin->gvc = gvContext();
-
- if (!(sym = agfindattr(plugin->graph->proto->n, "dpi")))
- sym = agraphattr(plugin->graph, "dpi", dpi_text);
- agxset(plugin->graph, sym->index, dpi_text);
+ /* Delete agedeges here? */
+ gtk_object_destroy (GTK_OBJECT (cls_edge->canvas_line));
+ gtk_object_destroy (GTK_OBJECT (cls_edge->canvas_arrow));
+ agdelete (cls_edge->cls_node_from->graph, cls_edge->agedge);
+ g_free (cls_edge);
}
-/*----------------------------------------------------------------------------
- * Perform a dot_cleanup and a graph closing. Call this function at the end of
- * call to draw_graph.
- */
static void
-cls_inherit_graph_cleanup (AnjutaClassInheritance *plugin)
+cls_node_free (ClsNode *cls_node)
{
- if (plugin->graph != NULL)
- {
- gvFreeLayout (plugin->gvc, plugin->graph);
- agclose (plugin->graph);
- }
-
- if (plugin->gvc != NULL )
- {
- gvFreeContext (plugin->gvc);
- }
-
- plugin->graph = NULL;
- plugin->gvc = NULL;
-
+ g_free (cls_node->sym_name);
+ g_list_foreach (cls_node->edges, (GFunc) cls_node_edge_free, NULL);
+ g_list_free (cls_node->edges);
+ g_hash_table_destroy (cls_node->members);
+ if (cls_node->canvas_group)
+ gtk_object_destroy (GTK_OBJECT (cls_node->canvas_group));
+ agdelete (cls_node->graph, cls_node->agnode);
+ g_free (cls_node);
}
-/*----------------------------------------------------------------------------
- * destroys a NodeData element. All it's resources will be deallocated
- * and setted to null.
- */
-static void
-cls_inherit_nodedata_destroy (NodeData *node_data)
+static gboolean
+cls_node_add_edge (ClsNode *cls_node_from, ClsNode *cls_node_to)
{
- if (node_data->canvas_item)
- {
- gtk_object_destroy (GTK_OBJECT (node_data->canvas_item));
- node_data->canvas_item = NULL;
- }
+ ClsNodeEdge *cls_edge;
+
+ g_return_val_if_fail (cls_node_from->graph != NULL, FALSE);
+
+ cls_edge = g_new0 (ClsNodeEdge, 1);
+ cls_edge->cls_node_from = cls_node_from;
+ cls_edge->cls_node_to = cls_node_to;
- if (node_data->menu)
- {
- gtk_widget_destroy (node_data->menu);
- node_data->menu = NULL;
- }
- if (node_data->sub_item)
+ if ((cls_edge->agedge = agedge (cls_node_from->graph,
+ cls_node_from->agnode,
+ cls_node_to->agnode)) == NULL)
{
- g_free (node_data->sub_item);
- node_data->sub_item = NULL;
+ g_free (cls_edge);
+ return FALSE;
}
- node_data->anchored = FALSE;
-}
-/*----------------------------------------------------------------------------
- * clean the canvas and all its painted objects.
- */
-void
-class_inheritance_clean_canvas (AnjutaClassInheritance *plugin)
-{
- if (plugin->drawable_list == NULL || plugin->node_list == NULL)
- return;
-
- /* destroying a gnome_canvas_item will un-paint automatically from
- * the canvas
- */
- g_list_foreach (plugin->drawable_list, (GFunc)gtk_object_destroy, NULL);
- g_list_free(plugin->drawable_list);
-
- /* the same for the nodes' list */
- g_list_foreach (plugin->node_list, (GFunc)cls_inherit_nodedata_destroy,
- NULL);
- g_list_free(plugin->node_list);
-
- /* re-initializing the g_list */
- plugin->drawable_list = NULL;
- plugin->node_list = NULL;
+ cls_node_from->edges = g_list_prepend (cls_node_from->edges, cls_edge);
+ return TRUE;
}
-
/*----------------------------------------------------------------------------
* add a node to an Agraph. Check also if the node is yet in the hash_table so
* that we can build the label of the node with the class-data.
*/
-static gboolean
-cls_inherit_add_node (AnjutaClassInheritance *plugin, const IAnjutaSymbol *node_sym)
+static ClsNode*
+cls_inherit_create_node (AnjutaClassInheritance *plugin,
+ const IAnjutaSymbol *node_sym)
{
- Agnode_t *graph_node;
+ ClsNode *cls_node;
Agsym_t *sym;
- NodeExpansionStatus *node_status;
- const gchar *node_sym_name;
- gint node_sym_id;
- gchar *graph_node_name;
gint font_size;
-
+ const gchar *font_name;
+
#define FONT_SIZE_STR_LEN 16
gchar font_size_str[FONT_SIZE_STR_LEN];
-
- /* if graph isn't initialized, init it */
- if (!plugin->graph)
- cls_inherit_graph_init (plugin, _(DEFAULT_GRAPH_NAME));
-
- node_sym_name = ianjuta_symbol_get_name (IANJUTA_SYMBOL (node_sym), NULL);
- node_sym_id = ianjuta_symbol_get_id (IANJUTA_SYMBOL (node_sym), NULL);
- /* get an unique char key for an agnode */
- graph_node_name = class_inheritance_create_agnode_key_name (node_sym);
-
+ cls_node = g_new0 (ClsNode, 1);
+ cls_node->graph = plugin->graph;
+ cls_node->canvas = plugin->canvas;
+ cls_node->plugin = plugin;
+ cls_node->sym_manager =
+ anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
+ IAnjutaSymbolManager, NULL);
+
+ cls_node->sym_name =
+ g_strdup (ianjuta_symbol_get_name (IANJUTA_SYMBOL (node_sym), NULL));
+ cls_node->klass_id =
+ ianjuta_symbol_get_id (IANJUTA_SYMBOL (node_sym), NULL);
+ cls_node->members =
+ g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) cls_node_item_free);
+ cls_node->expansion_status = CLS_NODE_COLLAPSED;
+ cls_node->drawn_expansion_status = CLS_NODE_COLLAPSED;
+
/* let's add the node to the graph */
- if ((graph_node = agnode (plugin->graph,
- graph_node_name)) == NULL)
+ if ((cls_node->agnode = agnode (cls_node->graph,
+ cls_node->sym_name)) == NULL)
{
- g_free (graph_node_name);
- return FALSE;
+ cls_node_free (cls_node);
+ return NULL;
}
- g_free (graph_node_name);
- /* check for the node in the gtree */
- if ((node_status =
- (NodeExpansionStatus*)g_tree_lookup (plugin->expansion_node_list,
- GINT_TO_POINTER (node_sym_id))) != NULL &&
- node_status->expansion_status != NODE_NOT_EXPANDED)
- {
- GString *label;
- gint max_label_items = 0;
- gint real_items_length = 0;
- IAnjutaSymbolManager *sm;
-
- if (!(sym = agfindattr(plugin->graph->proto->n, "shape")))
- sym = agnodeattr(plugin->graph, "shape", "");
- agxset (graph_node, sym->index, "record");
-
- if (!(sym = agfindattr(plugin->graph->proto->n, "label")))
- sym = agnodeattr(plugin->graph, "label", "");
-
- label = g_string_new ("");
- g_string_printf (label, "{%s", node_sym_name);
-
- sm = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
- IAnjutaSymbolManager, NULL);
- if (sm)
- {
- IAnjutaIterable *iter;
-
- /* get members from the passed symbol node */
- iter = ianjuta_symbol_manager_get_members (sm, node_sym,
- IANJUTA_SYMBOL_FIELD_SIMPLE|
- IANJUTA_SYMBOL_FIELD_TYPE |
- IANJUTA_SYMBOL_FIELD_ACCESS,
- NULL);
- real_items_length = ianjuta_iterable_get_length (iter, NULL);
-
- /* set the max number of items to draw */
- if (real_items_length <= NODE_HALF_DISPLAY_ELEM_NUM ||
- node_status->expansion_status == NODE_FULL_EXPANDED)
- {
- max_label_items = real_items_length;
- node_status->expansion_status = NODE_FULL_EXPANDED;
- }
- else
- {
- max_label_items = NODE_HALF_DISPLAY_ELEM_NUM;
- }
-
- if (iter && real_items_length > 0)
- {
- gint i;
- i = 0;
- do
- {
- const gchar *name;
- IAnjutaSymbol *symbol = IANJUTA_SYMBOL (iter);
-
- name = ianjuta_symbol_get_name (symbol, NULL);
- g_string_append_printf (label, "|%s", name);
- i++;
- }
- while (ianjuta_iterable_next (iter, NULL) && i < max_label_items);
- }
- if (iter)
- g_object_unref (iter);
- }
-
- if (node_status->expansion_status == NODE_HALF_EXPANDED &&
- real_items_length > NODE_HALF_DISPLAY_ELEM_NUM)
- {
- g_string_append_printf (label, "|%s", NODE_SHOW_ALL_MEMBERS_STR);
- }
-
- g_string_append_printf (label, "}");
- agxset(graph_node, sym->index, label->str);
-
- /* set the margin for icons */
- if (!(sym = agfindattr(plugin->graph->proto->n, "margin")))
- sym = agnodeattr(plugin->graph, "margin", "0.11,0.055");
- agxset(graph_node, sym->index, "0.3,0.03");
-
- g_string_free (label, TRUE);
- }
- else
- { /* the node isn't in an expansion status.
- * Go on setting a regular one */
-
- /* Set an attribute - in this case one that affects the visible rendering */
- if (!(sym = agfindattr(plugin->graph->proto->n, "shape")))
- sym = agnodeattr(plugin->graph, "shape", "");
- agxset(graph_node, sym->index, "box");
-
- if (!(sym = agfindattr(plugin->graph->proto->n, "label")))
- sym = agnodeattr(plugin->graph, "label", "");
- agxset(graph_node, sym->index, graph_node->name);
- }
-
/* set the font */
if (!(sym = agfindattr(plugin->graph->proto->n, "fontname")))
sym = agnodeattr(plugin->graph, "fontname", "");
- const gchar *font_name = pango_font_description_get_family (plugin->canvas->style->font_desc);
- agxset(graph_node, sym->index, (char*)font_name);
+ font_name =
+ pango_font_description_get_family (plugin->canvas->style->font_desc);
+ agxset(cls_node->agnode, sym->index, (char*)font_name);
/* set the font-size */
if (!(sym = agfindattr(plugin->graph->proto->n, "fontsize")))
sym = agnodeattr(plugin->graph, "fontsize", "");
- font_size = pango_font_description_get_size (plugin->canvas->style->font_desc)/ PANGO_SCALE;
+ font_size =
+ pango_font_description_get_size (plugin->canvas->style->font_desc)/
+ PANGO_SCALE;
/* The above font size in points is with real screen DPI, but graphviz
* rendering is done at fixed INCH_TO_PIXELS_CONVERSION_FACTOR dpi. So
* convert to the right font size points for graphviz.
*/
- font_size = font_size * gdk_screen_get_resolution (gdk_screen_get_default ())
+ font_size =
+ font_size * gdk_screen_get_resolution (gdk_screen_get_default ())
/ INCH_TO_PIXELS_CONVERSION_FACTOR;
- /* hack: set canvas_text_fontsize + 4 points or text would oversize the block */
snprintf (font_size_str, FONT_SIZE_STR_LEN, "%d", font_size);
- agxset(graph_node, sym->index, font_size_str);
+ agxset(cls_node->agnode, sym->index, font_size_str);
if (!(sym = agfindattr(plugin->graph->proto->n, "ratio")))
sym = agnodeattr(plugin->graph, "ratio", "");
- agxset(graph_node, sym->index, "expand");
+ agxset(cls_node->agnode, sym->index, "expand");
- return TRUE;
+ /* Set an attribute - in this case one that affects the visible rendering */
+ if (!(sym = agfindattr(plugin->graph->proto->n, "shape")))
+ sym = agnodeattr(plugin->graph, "shape", "");
+ agxset(cls_node->agnode, sym->index, "box");
+
+ if (!(sym = agfindattr(plugin->graph->proto->n, "label")))
+ sym = agnodeattr(plugin->graph, "label", "");
+ agxset(cls_node->agnode, sym->index, cls_node->sym_name);
+
+ return cls_node;
}
-/*----------------------------------------------------------------------------
- * add an edge to an Agraph.
- */
-static gboolean
-cls_inherit_add_edge (AnjutaClassInheritance *plugin,
- const IAnjutaSymbol *node_sym_from,
- const IAnjutaSymbol *node_sym_to)
+gboolean
+cls_node_collapse (ClsNode *cls_node)
{
- Agedge_t *edge;
- Agnode_t *n_from, *n_to;
- gchar *from_key, *to_key;
-
- /* if we hadn't initialized out graph we return FALSE. Edges require
- * two nodes
- */
- if (!plugin->graph)
- return FALSE;
-
- from_key = class_inheritance_create_agnode_key_name (node_sym_from);
-
- if ((n_from = agfindnode (plugin->graph, from_key)) == NULL)
- {
- g_free (from_key);
- return FALSE;
- }
- g_free (from_key);
+ Agsym_t *sym;
- to_key = class_inheritance_create_agnode_key_name (node_sym_to);
- if ((n_to = agfindnode (plugin->graph, to_key)) == NULL)
- {
- g_free (to_key);
- return FALSE;
- }
- g_free (to_key);
-
- if ((edge = agedge (plugin->graph, n_from, n_to)) == NULL)
+ if (cls_node->expansion_status == CLS_NODE_COLLAPSED)
return FALSE;
-
+
+ if (!(sym = agfindattr(cls_node->graph->proto->n, "label")))
+ sym = agnodeattr(cls_node->graph, "label", "");
+ agxset(cls_node->agnode, sym->index, cls_node->sym_name);
+ cls_node->expansion_status = CLS_NODE_COLLAPSED;
+
return TRUE;
}
-
-/*----------------------------------------------------------------------------
- * Draw an expanded node. Function which simplifies cls_inherit_draw_graph().
- */
-static void
-cls_inherit_draw_expanded_node (AnjutaClassInheritance *plugin,
- Agnode_t *graph_node,
- point* node_pos, gdouble node_width,
- gdouble node_height)
+gboolean
+cls_node_expand (ClsNode *cls_node, ClsNodeExpansionType expansion_type)
{
- GnomeCanvasItem *item;
- NodeExpansionStatus *node_status;
- NodeData *node_data;
- gint expansion_status;
- gint i, j;
- IAnjutaSymbolManager *sm;
- IAnjutaIterable *symbol_iter = NULL;
+ Agsym_t *sym;
+ GString *label;
+ gint max_label_items = 0;
+ gint real_items_length = 0;
+ gint var_order = -1000;
+ gint method_order = 0;
IAnjutaSymbol *node_sym;
- gint node_sym_id;
+ IAnjutaIterable *iter;
- sm = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
- IAnjutaSymbolManager, NULL);
- if (!sm)
- return;
-
- node_sym = class_inheritance_get_symbol_from_agnode_key_name (plugin,
- graph_node->name);
+ if (cls_node->expansion_status == expansion_type ||
+ expansion_type == CLS_NODE_COLLAPSED)
+ return FALSE;
+
+ node_sym =
+ ianjuta_symbol_manager_get_symbol_by_id (cls_node->sym_manager,
+ cls_node->klass_id,
+ IANJUTA_SYMBOL_FIELD_SIMPLE,
+ NULL);
+ if (!node_sym)
+ return FALSE;
- node_sym_id = ianjuta_symbol_get_id (node_sym, NULL);
- symbol_iter = ianjuta_symbol_manager_get_members (sm, node_sym,
- IANJUTA_SYMBOL_FIELD_SIMPLE |
- IANJUTA_SYMBOL_FIELD_TYPE |
- IANJUTA_SYMBOL_FIELD_ACCESS |
- IANJUTA_SYMBOL_FIELD_FILE_PATH,
- NULL);
+ if (!(sym = agfindattr(cls_node->graph->proto->n, "shape")))
+ sym = agnodeattr(cls_node->graph, "shape", "");
+ agxset (cls_node->agnode, sym->index, "record");
- g_object_unref (node_sym);
+ if (!(sym = agfindattr(cls_node->graph->proto->n, "label")))
+ sym = agnodeattr(cls_node->graph, "label", "");
- /* we need to know which label to draw, wether only the "show all" or just
- * the "normal view" */
- if ((node_status =
- (NodeExpansionStatus*)g_tree_lookup
- (plugin->expansion_node_list, GINT_TO_POINTER (node_sym_id))) == NULL)
+ label = g_string_new ("");
+ g_string_printf (label, "{%s", cls_node->sym_name);
+
+ /* get members from the passed symbol node */
+ iter = ianjuta_symbol_manager_get_members (cls_node->sym_manager, node_sym,
+ IANJUTA_SYMBOL_FIELD_SIMPLE|
+ IANJUTA_SYMBOL_FIELD_TYPE |
+ IANJUTA_SYMBOL_FIELD_ACCESS |
+ IANJUTA_SYMBOL_FIELD_FILE_PATH,
+ NULL);
+ real_items_length = ianjuta_iterable_get_length (iter, NULL);
+
+ /* set the max number of items to draw */
+ if (real_items_length <= NODE_HALF_DISPLAY_ELEM_NUM ||
+ expansion_type == CLS_NODE_FULL_EXPANDED)
{
- expansion_status = NODE_NOT_EXPANDED;
+ max_label_items = real_items_length;
+ cls_node->expansion_status = CLS_NODE_FULL_EXPANDED;
}
else
- expansion_status = node_status->expansion_status;
+ {
+ max_label_items = NODE_HALF_DISPLAY_ELEM_NUM;
+ cls_node->expansion_status = CLS_NODE_SEMI_EXPANDED;
+ }
- for (i = 0; i < NODE_NUM_FIELDS (graph_node); i++ )
+ g_hash_table_remove_all (cls_node->members);
+ if (iter && real_items_length > 0)
{
- for (j = 0; j < NODE_NTH_FIELD (graph_node, i)->n_flds; j++ )
+ gint i = 0;
+
+ /* First member variables */
+ do
{
+ const gchar *name, *args;
IAnjutaSymbol *symbol;
- gint symbol_id;
- gint y1, y2;
-
- y1 = NODE_LOWER_LEFT (graph_node, i, j).y;
- y2 = NODE_UPPER_RIGHT(graph_node, i, j).y;
-
- node_data = g_new0 (NodeData, 1);
-
- symbol = class_inheritance_get_symbol_from_agnode_key_name (plugin,
- graph_node->name);
-
- symbol_id = ianjuta_symbol_get_id (symbol, NULL);
- g_object_unref (symbol);
-
- /* set the plugin reference */
- node_data->plugin = plugin;
- node_data->anchored = TRUE;
- node_data->klass_id = symbol_id;
-
- node_data->sub_item = g_strdup (NODE_NTH_TEXT (graph_node,i,j));
-
- node_data->canvas_item =
- gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (plugin->canvas)),
- gnome_canvas_rect_get_type (),
- "x1",
- (gdouble) (node_pos->x -INCH_TO_PIXELS (node_width)/2),
- "y1",
- (gdouble) -node_pos->y -INCH_TO_PIXELS (node_height)/2 +
- j*abs(y1-y2),
- "x2",
- (gdouble) (node_pos->x +INCH_TO_PIXELS (node_width)/2),
- "y2",
- (gdouble) -node_pos->y -INCH_TO_PIXELS (node_height)/2 +
- (j+1)*abs(y1-y2),
- "fill_color_gdk",
- &plugin->canvas->style->base[GTK_STATE_NORMAL],
- NULL);
+ GdkPixbuf *icon;
- /* add to the nodelist: we'll set the __uri and __line properites later
- * on this loop, when we'll parse symbols. */
- plugin->node_list = g_list_prepend (plugin->node_list, node_data);
-
- /* --- texts --- */
- item = gnome_canvas_item_new (gnome_canvas_root
- (GNOME_CANVAS (plugin->canvas)),
- gnome_canvas_text_get_type (),
- "text", NODE_NTH_TEXT (graph_node, i, j),
- "justification", GTK_JUSTIFY_CENTER,
- "anchor", GTK_ANCHOR_CENTER,
- "x",
- (gdouble) (node_pos->x -
- INCH_TO_PIXELS (node_width)/2 + 20),
- "y", (gdouble) -node_pos->y -
- INCH_TO_PIXELS (node_height)/2+(j+0.5)*abs(y1-y2),
- "fill_color_gdk",
- &plugin->canvas->style->text[GTK_STATE_NORMAL],
- "anchor", GTK_ANCHOR_W,
- NULL);
- plugin->drawable_list = g_list_prepend (plugin->drawable_list, item);
+ symbol = IANJUTA_SYMBOL (iter);
+ name = g_strdup (ianjuta_symbol_get_name (symbol, NULL));
+ args = ianjuta_symbol_get_args (symbol, NULL);
+ icon = (GdkPixbuf*) ianjuta_symbol_get_icon (symbol, NULL);
- if (j == 0) /* the Class' name case */
- {
- gnome_canvas_item_set (node_data->canvas_item,
- "fill_color_gdk",
- &plugin->canvas->style->bg[GTK_STATE_ACTIVE],
- NULL);
- g_signal_connect (GTK_OBJECT (node_data->canvas_item), "event",
- G_CALLBACK (on_expanded_class_nodedata_event),
- node_data);
- /* Arrow */
- item = create_canvas_arrow_item (plugin->canvas,
- CANVAS_ARROW_DIR_DOWN,
- node_pos->x +INCH_TO_PIXELS (node_width)/2 - abs(y1-y2),
- -node_pos->y -INCH_TO_PIXELS (node_height)/2,
- node_pos->x +INCH_TO_PIXELS (node_width)/2,
- -node_pos->y -INCH_TO_PIXELS (node_height)/2 + abs(y1-y2));
- plugin->drawable_list = g_list_prepend (plugin->drawable_list, item);
-
- continue;
+ if (!args) /* Member variables */
+ {
+ ClsNodeItem *cls_item = g_new0 (ClsNodeItem, 1);
+ cls_item->cls_node = cls_node;
+ cls_item->sym_name = g_strdup (name);
+ cls_item->order = var_order++;
+ gdk_pixbuf_ref (icon);
+ cls_item->icon = icon;
+
+ g_hash_table_insert (cls_node->members,
+ g_strdup (cls_item->sym_name),
+ cls_item);
+ g_string_append_printf (label, "|%s", cls_item->sym_name);
+
+ /* Setup file and line */
+ cls_item->line = ianjuta_symbol_get_line (symbol, NULL);
+ cls_item->file = ianjuta_symbol_get_file (symbol, NULL);
+ g_object_ref (cls_item->file);
}
- else /* The "more" item is the last */
+ else /* Member methods */
{
- if (expansion_status == NODE_HALF_EXPANDED &&
- j == (NODE_NTH_FIELD (graph_node, i)->n_flds - 1))
- {
- g_signal_connect (GTK_OBJECT (node_data->canvas_item), "event",
- G_CALLBACK (on_nodedata_expanded_event),
- node_data);
- continue;
- }
- else /* Normal class item */
+ ClsNodeItem *cls_item;
+ gchar *method_key = g_strconcat (name, args, NULL);
+ cls_item = g_hash_table_lookup (cls_node->members, method_key);
+
+ if (cls_item) /* We found an entry for this method */
{
- g_signal_connect (GTK_OBJECT (node_data->canvas_item), "event",
- G_CALLBACK (on_nodedata_expanded_event),
- node_data);
+ IAnjutaSymbolType sym_type
+ = ianjuta_symbol_get_sym_type (symbol, NULL);
+ if (!(sym_type & IANJUTA_SYMBOL_TYPE_PROTOTYPE))
+ {
+ /* This one is method, so take this one instead */
+ g_free (cls_item->args);
+ cls_item->args = g_strdup (args);
+
+ if (cls_item->file) g_object_unref (cls_item->file);
+ cls_item->file = NULL;
+
+ /* Setup file and line */
+ cls_item->line = ianjuta_symbol_get_line (symbol, NULL);
+ cls_item->file = ianjuta_symbol_get_file (symbol, NULL);
+ g_object_ref (cls_item->file);
+ }
}
- }
-
- /* go on with the icons */
- if (symbol_iter && ianjuta_iterable_get_length (symbol_iter, NULL) > 0)
- {
- const GdkPixbuf *pixbuf;
- GFile* gfile;
- gchar *file;
- gint line;
- IAnjutaSymbol *symbol = IANJUTA_SYMBOL (symbol_iter);
-
- gfile = ianjuta_symbol_get_file (symbol, NULL);
- line = ianjuta_symbol_get_line (symbol, NULL);
- pixbuf = ianjuta_symbol_get_icon (symbol, NULL);
-
- item = gnome_canvas_item_new ( gnome_canvas_root
- (GNOME_CANVAS (plugin->canvas)),
- gnome_canvas_pixbuf_get_type(),
- "x",
- (gdouble) (node_pos->x -
- INCH_TO_PIXELS (node_width)/2 +2),
- "y",
- (gdouble) -node_pos->y -
- INCH_TO_PIXELS (node_height)/2+(j+0.5)*abs(y1-y2)-8,
- "pixbuf", pixbuf,
- NULL);
-
- /* set now the object properties on node_data. We still have a
- * reference to it so we can access its canvas_item */
- if (gfile)
+ else /* We did not find a member entry, create a new one */
{
- file = g_file_get_path (gfile);
+ ClsNodeItem *cls_item = g_new0 (ClsNodeItem, 1);
+ cls_item->cls_node = cls_node;
+ cls_item->sym_name = g_strconcat (name, "()", NULL);
+ cls_item->args = g_strdup (args);
+ cls_item->order = method_order++;
+ gdk_pixbuf_ref (icon);
+ cls_item->icon = icon;
- g_object_set_data_full (G_OBJECT (node_data->canvas_item),
- "__filepath",
- file, g_free);
- g_object_set_data (G_OBJECT (node_data->canvas_item),
- "__line",
- GINT_TO_POINTER (line));
+ g_string_append_printf (label, "|%s()", cls_item->sym_name);
+ g_hash_table_insert (cls_node->members, method_key,
+ cls_item);
- /* no need to free 'file'. It'll be freed when object'll be unreffed */
+ /* Setup file and line */
+ cls_item->line = ianjuta_symbol_get_line (symbol, NULL);
+ cls_item->file = ianjuta_symbol_get_file (symbol, NULL);
+ g_object_ref (cls_item->file);
}
}
-
- plugin->drawable_list = g_list_prepend (plugin->drawable_list, item);
- ianjuta_iterable_next (symbol_iter, NULL);
- } /*- for */
+ i++;
+ }
+ while (ianjuta_iterable_next (iter, NULL) && i < max_label_items);
+ }
+ if (iter)
+ g_object_unref (iter);
+
+ if (cls_node->expansion_status == CLS_NODE_SEMI_EXPANDED &&
+ real_items_length > NODE_HALF_DISPLAY_ELEM_NUM)
+ {
+ g_string_append_printf (label, "|%s", NODE_SHOW_ALL_MEMBERS_STR);
}
- if (symbol_iter)
- g_object_unref (symbol_iter);
+ g_string_append_printf (label, "}");
+ agxset(cls_node->agnode, sym->index, label->str);
+
+ /* set the margin for icons */
+ if (!(sym = agfindattr(cls_node->graph->proto->n, "margin")))
+ sym = agnodeattr(cls_node->graph, "margin", "0.11,0.055");
+ agxset(cls_node->agnode, sym->index, "0.3,0.03");
+
+ g_string_free (label, TRUE);
+
+ return TRUE;
+}
+
+static gint
+on_cls_node_item_compare (ClsNodeItem *a, ClsNodeItem *b)
+{
+ if (a->order > b->order) return 1;
+ if (a->order < b->order) return -1;
+ else return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Draw an expanded node. Function which simplifies cls_inherit_draw_graph().
+ */
+static void
+cls_node_draw_expanded (ClsNode *cls_node)
+{
+ GnomeCanvasItem *canvas_item;
+ gint item_height, j;
+ GList *members, *member;
+
+ g_return_if_fail (cls_node->sym_manager != NULL);
+ g_return_if_fail (cls_node->expansion_status == CLS_NODE_SEMI_EXPANDED ||
+ cls_node->expansion_status == CLS_NODE_FULL_EXPANDED);
+
+ if (cls_node->canvas_group)
+ gtk_object_destroy (GTK_OBJECT (cls_node->canvas_group));
+ cls_node->canvas_group =
+ gnome_canvas_item_new (gnome_canvas_root
+ (GNOME_CANVAS (cls_node->canvas)),
+ gnome_canvas_group_get_type (),
+ NULL);
+ cls_node->drawn_expansion_status = cls_node->expansion_status;
+ members = g_hash_table_get_values (cls_node->members);
+ members = g_list_sort (members, (GCompareFunc)on_cls_node_item_compare);
+
+ if (cls_node->expansion_status == CLS_NODE_SEMI_EXPANDED)
+ item_height = cls_node->height / (g_list_length (members) + 2);
+ else
+ item_height = cls_node->height / (g_list_length (members) + 1);
+
+ /* Class title */
+ canvas_item =
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_rect_get_type (),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", (gdouble) cls_node->width,
+ "y2", (gdouble) item_height,
+ "fill_color_gdk",
+ &cls_node->canvas->style->bg[GTK_STATE_ACTIVE],
+ NULL);
+
+ g_signal_connect (GTK_OBJECT (canvas_item), "event",
+ G_CALLBACK (on_expanded_class_title_event),
+ cls_node);
+
+ /* Arrow on the right of class title */
+ create_canvas_arrow_item (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ CLS_ARROW_DIR_DOWN,
+ &cls_node->canvas->style->fg[GTK_STATE_NORMAL],
+ cls_node->width - item_height,
+ 0, cls_node->width, item_height);
+ /* Class title text */
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_text_get_type (),
+ "text", cls_node->sym_name,
+ "justification", GTK_JUSTIFY_CENTER,
+ "anchor", GTK_ANCHOR_CENTER,
+ "x", (gdouble) 20.0,
+ "y", (gdouble) (j + 0.5) * item_height,
+ "fill_color_gdk",
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ "anchor", GTK_ANCHOR_W,
+ NULL);
+ /* Member items */
+ j = 1;
+ for (member = members; member; member = member->next)
+ {
+ ClsNodeItem *node_item = (ClsNodeItem*) member->data;
+
+ /* Member item background */
+ node_item->canvas_node_item =
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_rect_get_type (),
+ "x1", 0.0,
+ "y1", (gdouble) j * item_height,
+ "x2", (gdouble) cls_node->width,
+ "y2", (gdouble) (j + 1) * item_height,
+ "fill_color_gdk",
+ &cls_node->canvas->style->base[GTK_STATE_NORMAL],
+ NULL);
+ g_signal_connect (GTK_OBJECT (node_item->canvas_node_item),
+ "event",
+ G_CALLBACK (on_expanded_class_item_event),
+ node_item);
+
+ /* Member item text */
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_text_get_type (),
+ "text", node_item->sym_name,
+ "justification", GTK_JUSTIFY_CENTER,
+ "anchor", GTK_ANCHOR_CENTER,
+ "x", (gdouble) 20.0,
+ "y", (gdouble) (j + 0.5) * item_height,
+ "fill_color_gdk",
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ "anchor", GTK_ANCHOR_W,
+ NULL);
+ /* Member item icon */
+ if (node_item->icon)
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_pixbuf_get_type(),
+ "x", 2.0,
+ "y",
+ (gdouble) (j + 0.5) * item_height - 8,
+ "pixbuf", node_item->icon,
+ NULL);
+ if (node_item->order == 0 || j == 1) /* Variables and methods border */
+ create_canvas_line_item (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ 0, j * item_height,
+ cls_node->width, j * item_height);
+ j++;
+ }
+ g_list_free (members);
+
+ /* The last item for semi expanded item is "more" item */
+ if (cls_node->expansion_status == CLS_NODE_SEMI_EXPANDED)
+ {
+ /* More expand item background */
+ canvas_item =
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_rect_get_type (),
+ "x1", 0.0,
+ "y1", (gdouble) j * item_height,
+ "x2", (gdouble) cls_node->width,
+ "y2", (gdouble) (j + 1) * item_height,
+ "fill_color_gdk",
+ &cls_node->canvas->style->bg[GTK_STATE_ACTIVE],
+ NULL);
+
+ g_signal_connect (GTK_OBJECT (canvas_item), "event",
+ G_CALLBACK (on_expanded_class_more_event),
+ cls_node);
+
+ /* More expand item text */
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_text_get_type (),
+ "text", NODE_SHOW_ALL_MEMBERS_STR,
+ "justification", GTK_JUSTIFY_CENTER,
+ "anchor", GTK_ANCHOR_CENTER,
+ "x", (gdouble) 20.0,
+ "y", (gdouble) (j + 0.5) * item_height,
+ "fill_color_gdk",
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ "anchor", GTK_ANCHOR_W,
+ NULL);
+ create_canvas_line_item (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ 0, j * item_height,
+ cls_node->width, j * item_height);
+ }
/* make the outline bounds */
- item =
- gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (plugin->canvas)),
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
gnome_canvas_rect_get_type (),
- "x1",
- (gdouble) (node_pos->x -INCH_TO_PIXELS (node_width)/2-1 ),
- "y1",
- (gdouble) -node_pos->y -INCH_TO_PIXELS (node_height)/2 -1,
- "x2",
- (gdouble) node_pos->x +INCH_TO_PIXELS (node_width)/2,
- "y2",
- (gdouble) -node_pos->y +INCH_TO_PIXELS (node_height)/2 -1,
+ "x1", (gdouble) 0.0,
+ "y1", (gdouble) 0.0,
+ "x2", (gdouble) cls_node->width,
+ "y2", (gdouble) cls_node->height,
"outline_color_gdk",
- &plugin->canvas->style->text[GTK_STATE_ACTIVE],
+ &cls_node->canvas->style->text[GTK_STATE_ACTIVE],
"width_units", 1.0,
NULL);
-
- plugin->drawable_list = g_list_prepend (plugin->drawable_list, item);
}
static void
-cls_inherit_draw_single_node (AnjutaClassInheritance *plugin,
- Agnode_t *graph_node,
- point *node_pos, gdouble node_width,
- gdouble node_height)
+cls_node_draw_collapsed (ClsNode *cls_node)
{
- NodeData *node_data;
GnomeCanvasItem *item;
gdouble text_width_value;
- IAnjutaSymbol *node_sym;
- const gchar* node_sym_name;
- gint x1, y1, x2, y2;
- node_sym = class_inheritance_get_symbol_from_agnode_key_name (plugin,
- graph_node->name);
- node_sym_name = ianjuta_symbol_get_name (node_sym, NULL);
- node_data = g_new0 (NodeData, 1);
-
- /* set the plugin reference */
- node_data->plugin = plugin;
- node_data->anchored = FALSE;
- node_data->klass_id = ianjuta_symbol_get_id (IANJUTA_SYMBOL (node_sym), NULL);
- node_data->sub_item = NULL;
-
- g_object_unref (node_sym);
-
- x1 = node_pos->x - INCH_TO_PIXELS (node_width)/2;
- y1 = -(node_pos->y - INCH_TO_PIXELS (node_height)/2);
- x2 = node_pos->x + INCH_TO_PIXELS (node_width)/2;
- y2 = -(node_pos->y + INCH_TO_PIXELS (node_height)/2);
-
- node_data->canvas_item =
- gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (plugin->canvas)),
- gnome_canvas_rect_get_type (),
- "x1", (gdouble) x1,
- "y1", (gdouble) y1,
- "x2", (gdouble) x2,
- "y2", (gdouble) y2,
- "fill_color_gdk",
- &plugin->canvas->style->base[GTK_STATE_NORMAL],
- "outline_color_gdk",
- &plugin->canvas->style->text[GTK_STATE_NORMAL],
- "width_units", 1.0,
- NULL);
+ g_return_if_fail (cls_node->agnode != NULL);
+ g_return_if_fail (cls_node->canvas);
+ g_return_if_fail (cls_node->expansion_status == CLS_NODE_COLLAPSED);
+
+ /* Clean up members */
+ g_hash_table_remove_all (cls_node->members);
+
+ /* Switch to collapsed canvas item */
+ if (cls_node->canvas_group)
+ gtk_object_destroy (GTK_OBJECT (cls_node->canvas_group));
+ cls_node->canvas_group =
+ gnome_canvas_item_new (gnome_canvas_root
+ (GNOME_CANVAS (cls_node->canvas)),
+ gnome_canvas_group_get_type (),
+ NULL);
+ cls_node->drawn_expansion_status = CLS_NODE_COLLAPSED;
- plugin->node_list = g_list_prepend (plugin->node_list, node_data);
-
- g_signal_connect (GTK_OBJECT (node_data->canvas_item), "event",
- G_CALLBACK (on_collapsed_class_nodedata_event),
- node_data);
-
- /* --- texts --- */
- item = gnome_canvas_item_new (gnome_canvas_root
- (GNOME_CANVAS (plugin->canvas)),
+ item =
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+ gnome_canvas_rect_get_type (),
+ "x1", (gdouble) 0.0,
+ "y1", (gdouble) 0.0,
+ "x2", (gdouble) cls_node->width,
+ "y2", (gdouble) cls_node->height,
+ "fill_color_gdk",
+ &cls_node->canvas->style->base[GTK_STATE_NORMAL],
+ "outline_color_gdk",
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ "width_units", 1.0,
+ NULL);
+ g_signal_connect (GTK_OBJECT (item), "event",
+ G_CALLBACK (on_collapsed_class_event),
+ cls_node);
+
+ /* --- text --- */
+ item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
gnome_canvas_text_get_type (),
- "text", node_sym_name,
+ "text", cls_node->sym_name,
"justification", GTK_JUSTIFY_CENTER,
"anchor", GTK_ANCHOR_CENTER,
- "x",
- (gdouble) (node_pos->x - INCH_TO_PIXELS (node_width)/2),
- "y", (gdouble) -node_pos->y,
+ "x", (gdouble) 0.0,
+ "y", (gdouble) cls_node->height/2,
"fill_color_gdk",
- &plugin->canvas->style->text[GTK_STATE_NORMAL],
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
"anchor", GTK_ANCHOR_W,
NULL );
-
/* center the text in the node... */
g_object_get (item, "text_width", &text_width_value, NULL);
- gnome_canvas_item_set (item, "x",
- (gdouble)((node_pos->x - text_width_value/2)), NULL);
-
- plugin->drawable_list = g_list_prepend (plugin->drawable_list, item);
+ gnome_canvas_item_set (item,
+ "x", (gdouble)((cls_node->width/2 - text_width_value/2)),
+ NULL);
}
-
-/*----------------------------------------------------------------------------
- * draw the graph on the canvas. So nodes, edges, arrows, texts..
- * If something is found already drawn on the canvas it is cleaned before
- * draw new things.
- */
static void
-cls_inherit_draw_graph (AnjutaClassInheritance *plugin)
+cls_node_draw_edge (ClsNodeEdge *cls_edge, ClsNode *cls_node)
{
- gint num_nodes;
- gdouble canvas_x1, canvas_y1, canvas_x2, canvas_y2;
- GnomeCanvasItem *item;
- Agnode_t *graph_node;
Agedge_t *edge;
+ GnomeCanvasPathDef *path_def;
+ GnomeCanvasPoints *points;
+ gint i, num_points;
- if (plugin->graph == NULL)
- return;
+ path_def = gnome_canvas_path_def_new();
+ edge = cls_edge->agedge;
+ num_points = ED_spl(edge)->list->size;
- DEBUG_PRINT ("%s", "======== going to draw graph ========");
- num_nodes = agnnodes (plugin->graph);
- g_return_if_fail (num_nodes > 0);
+ for (i = 0; i < num_points - 1; i += 3)
+ {
+ /* go on with bezier curves. We can retrieve the info such
+ * as control points from the struct of the edge
+ */
+ gnome_canvas_path_def_moveto (path_def,
+ ((ED_spl(edge))->list->list[0+i]).x,
+ GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[0+i]).y));
+
+ gnome_canvas_path_def_curveto (path_def,
+ ((ED_spl(edge))->list->list[1+i]).x,
+ GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[1+i]).y),
+ ((ED_spl(edge))->list->list[2+i]).x,
+ GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[2+i]).y),
+ ((ED_spl(edge))->list->list[3+i]).x,
+ GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[3+i]).y));
+ }
- /* compiles nodes/edges informations, such as positions, coordinates etc */
- gvLayout (plugin->gvc, plugin->graph, "dot");
+ /* draw the path_def */
+ if (cls_edge->canvas_line)
+ {
+ gnome_canvas_item_set (cls_edge->canvas_line,
+ "bpath", path_def,
+ NULL);
+ }
+ else
+ {
+ cls_edge->canvas_line =
+ gnome_canvas_item_new (gnome_canvas_root
+ (GNOME_CANVAS (cls_node->canvas)),
+ gnome_canvas_bpath_get_type(),
+ "bpath", path_def,
+ "outline_color_gdk",
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ "width_pixels", 2,
+ NULL);
+ }
+ gnome_canvas_path_def_unref (path_def);
+
+ /* Draw arrow */
- /* set the size of the canvas. We need this to set the scrolling.. */
- canvas_x1 = canvas_y1 = 0;
- canvas_x2 = CANVAS_MIN_SIZE;
- canvas_y2 = -CANVAS_MIN_SIZE;
+ /* let's draw a canvas_line with an arrow-end */
+ points = gnome_canvas_points_new (2);
+
+ /* starting point */
+ points->coords[0] = ((ED_spl(edge))->list->list[num_points - 2]).x;
+ points->coords[1] =
+ GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points - 2]).y);
- /* check whether we had already drawn something on the canvas.
- * In case remove the items so we can clean up the canvas ready
- * for others paints
- */
- if (g_list_length (plugin->drawable_list) > 0 ||
- g_list_length (plugin->node_list) > 0)
+ /* pointer */
+ points->coords[2] = ((ED_spl(edge))->list->list[num_points - 1]).x;
+ points->coords[3] =
+ GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points - 1]).y);
+
+ if (cls_edge->canvas_arrow)
{
- class_inheritance_clean_canvas (plugin);
+ gnome_canvas_item_set (cls_edge->canvas_arrow,
+ "points", points,
+ NULL);
}
-
- /* first of all draw the nodes */
- for (graph_node = agfstnode (plugin->graph); graph_node;
- graph_node = agnxtnode (plugin->graph, graph_node))
+ else
{
- gdouble node_width;
- gdouble node_height;
- gdouble node_x1, node_y1, node_x2, node_y2;
- point node_pos;
+ cls_edge->canvas_arrow =
+ gnome_canvas_item_new (gnome_canvas_root
+ (GNOME_CANVAS (cls_node->canvas)),
+ gnome_canvas_line_get_type(),
+ "points", points,
+ "fill_color_gdk",
+ &cls_node->canvas->style->text[GTK_STATE_NORMAL],
+ "last_arrowhead", TRUE,
+ "arrow_shape_a", 10.0,
+ "arrow_shape_b", 10.0,
+ "arrow_shape_c", 4.0,
+ "width_units", 2.0,
+ NULL);
+ }
+ gnome_canvas_points_unref (points);
+
+}
+
+/* Ensures that a new canvas item is created for this node and moved to right
+ * position, or just moves an existing canvas item if already created.
+ */
+static void
+cls_node_ensure_draw (gpointer klass_id, ClsNode *cls_node, ClsBox *bounding_box)
+{
+ gdouble x, y;
+ point node_pos;
#ifndef ND_coord_i
- pointf node_posf;
+ pointf node_posf;
#endif
-
- /* get some infos from the node */
+
+ /* get some infos from the node */
#ifdef ND_coord_i
- node_pos = ND_coord_i(graph_node);
+ node_pos = ND_coord_i (cls_node->agnode);
#else
- node_posf = ND_coord(graph_node);
- PF2P(node_posf,node_pos);
+ node_posf = ND_coord (cls_node->agnode);
+ PF2P (node_posf, node_pos);
#endif
- /* Determine node coords and size w.r.t canvas */
- node_width = ND_width (graph_node);
- node_height = ND_height (graph_node);
- node_x1 = node_pos.x - INCH_TO_PIXELS (node_width)/2;
- node_y1 = -(node_pos.y - INCH_TO_PIXELS (node_height)/2);
- node_x2 = node_pos.x + INCH_TO_PIXELS (node_width)/2;
- node_y2 = -(node_pos.y + INCH_TO_PIXELS (node_height)/2);
-
- if (strcmp ("record", ND_shape (graph_node)->name) == 0 )
- {
- cls_inherit_draw_expanded_node (plugin, graph_node, &node_pos, node_width,
- node_height);
- }
- else /* it's a normal single node */
- cls_inherit_draw_single_node (plugin, graph_node, &node_pos, node_width,
- node_height);
-
- /* --- edges --- */
- for (edge = agfstedge (plugin->graph, graph_node); edge;
- edge = agnxtedge (plugin->graph, edge, graph_node))
- {
- GnomeCanvasPathDef *path_def;
- gint i;
-
- path_def = gnome_canvas_path_def_new();
-
- for ( i = 0; i < ED_spl(edge)->list->size-1; i+=3)
- {
-
- /* go on with bezier curves. We can retrieve the info such
- * as control points from the struct of the edge
- */
- gnome_canvas_path_def_moveto (path_def,
- ((ED_spl(edge))->list->list[0+i]).x,
- -((ED_spl(edge))->list->list[0+i]).y);
-
- gnome_canvas_path_def_curveto (path_def,
- ((ED_spl(edge))->list->list[1+i]).x,
- -((ED_spl(edge))->list->list[1+i]).y,
- ((ED_spl(edge))->list->list[2+i]).x,
- -((ED_spl(edge))->list->list[2+i]).y,
- ((ED_spl(edge))->list->list[3+i]).x,
- -((ED_spl(edge))->list->list[3+i]).y);
-
- /* check whether we have to draw an arrow. Is the right point? */
- if ( i+3 >= (ED_spl(edge)->list->size-1) )
- {
- GnomeCanvasPoints *points;
- gdouble upper_bound = (gdouble)(node_pos.y +
- INCH_TO_PIXELS (node_height)/2);
- gdouble x_offset;
- gint h;
-
- /*
- __|__ _
- \ / |
- \ / | h
- ° _|
- ^^^^^^^^^^^^^
- */
-
- h = abs (((ED_spl(edge))->list->list[3+i]).y - upper_bound);
-
- if ((((ED_spl(edge))->list->list[3+i]).x -
- ((ED_spl(edge))->list->list[2+i]).x) > 0)
- x_offset = sqrt( abs(10*10 - h*h));
- else
- x_offset = -sqrt( abs(10*10 - h*h));
-
- /* let's draw a canvas_line with an arrow-end */
- points = gnome_canvas_points_new (2);
+ /* Determine node coords and size *in* canvas world coordinate system */
+ cls_node->width = INCH_TO_PIXELS (ND_width (cls_node->agnode));
+ cls_node->height = INCH_TO_PIXELS (ND_height (cls_node->agnode));
+ cls_node->x1 = node_pos.x - cls_node->width/2;
+ cls_node->y1 = GRAPH_TO_CANVAS_Y ((node_pos.y + cls_node->height/2));
+ cls_node->x2 = node_pos.x + cls_node->width/2;
+ cls_node->y2 = GRAPH_TO_CANVAS_Y ((node_pos.y - cls_node->height/2));
+
+ if (cls_node->x1 < bounding_box->x1) bounding_box->x1 = cls_node->x1;
+ if (cls_node->y1 < bounding_box->y1) bounding_box->y1 = cls_node->y1;
+ if (cls_node->x2 > bounding_box->x2) bounding_box->x2 = cls_node->x2;
+ if (cls_node->y2 > bounding_box->y2) bounding_box->y2 = cls_node->y2;
+
+ if (cls_node->canvas_group == NULL ||
+ cls_node->drawn_expansion_status != cls_node->expansion_status)
+ {
+ if (cls_node->expansion_status == CLS_NODE_COLLAPSED)
+ cls_node_draw_collapsed (cls_node);
+ else
+ cls_node_draw_expanded (cls_node);
+ }
+ /* Move the canvas item to right place */
+ x = cls_node->x1;
+ y = cls_node->y1;
+ gnome_canvas_item_w2i (cls_node->canvas_group, &x, &y);
+ gnome_canvas_item_move (cls_node->canvas_group, x, y);
+ g_list_foreach (cls_node->edges, (GFunc) cls_node_draw_edge, cls_node);
+}
- /* starting point */
- points->coords[0] = ((ED_spl(edge))->list->list[3+i]).x;
- points->coords[1] = -((ED_spl(edge))->list->list[3+i]).y;
-
- /* pointer */
- points->coords[2] =
- ((ED_spl(edge))->list->list[3+i]).x + x_offset;
- points->coords[3] = -upper_bound;
-
- /* ok we take an arrow_max_length of 10 pixels for default. */
- if ( abs(x_offset) <= 10 )
- {
- item =
- gnome_canvas_item_new (gnome_canvas_root
- (GNOME_CANVAS (plugin->canvas)),
- gnome_canvas_line_get_type(),
- "points", points,
- "fill_color_gdk",
- &plugin->canvas->style->text[GTK_STATE_NORMAL],
- "last_arrowhead", TRUE,
- "arrow_shape_a", 10.0,
- "arrow_shape_b", 10.0,
- "arrow_shape_c", 4.0,
- "width_units", 1.0,
- NULL);
- plugin->drawable_list =
- g_list_prepend (plugin->drawable_list, item);
- }
- }
- }
-
- /* draw the path_def */
- item = gnome_canvas_item_new (gnome_canvas_root
- (GNOME_CANVAS (plugin->canvas)),
- gnome_canvas_bpath_get_type(),
- "bpath", path_def,
- "outline_color_gdk",
- &plugin->canvas->style->text[GTK_STATE_NORMAL],
- "width_pixels", 1,
- NULL);
- plugin->drawable_list =
- g_list_prepend (plugin->drawable_list, item);
- }
+/*----------------------------------------------------------------------------
+ * draw the graph on the canvas. So nodes, edges, arrows, texts..
+ */
+void
+cls_inherit_draw (AnjutaClassInheritance *plugin)
+{
+ ClsBox bounds;
- if (node_x1 < canvas_x1) canvas_x1 = node_x1;
- if (node_y1 > canvas_y1) canvas_y1 = node_y1;
- if (node_x2 > canvas_x2) canvas_x2 = node_x2;
- if (node_y2 < canvas_y2) canvas_y2 = node_y2;
- }
+ /* set the size of the canvas. We need this to set the scrolling.. */
+ bounds.x1 = 0;
+ bounds.y1 = 0;
+ bounds.x2 = CANVAS_MIN_SIZE;
+ bounds.y2 = CANVAS_MIN_SIZE;
+ g_hash_table_foreach (plugin->nodes, (GHFunc) cls_node_ensure_draw, &bounds);
+
/* Request extra 20px along x and y for 10px margin around the canvas */
gtk_widget_set_size_request (plugin->canvas,
- canvas_x2 - canvas_x1 + 20,
- canvas_y1 - canvas_y2 + 20);
+ bounds.x2 - bounds.x1 + 20,
+ bounds.y2 - bounds.y1 + 20);
gnome_canvas_set_scroll_region (GNOME_CANVAS (plugin->canvas),
- canvas_x1 - 10, canvas_y1 + 10,
- canvas_x2 + 10, canvas_y2 - 10);
-
- cls_inherit_graph_cleanup (plugin);
+ bounds.x1 - 10, bounds.y1 - 10,
+ bounds.x2 + 10, bounds.y2 + 10);
+}
+
+/*----------------------------------------------------------------------------
+ * draw the graph on the canvas. So nodes, edges, arrows, texts..
+ */
+void
+cls_inherit_layout (AnjutaClassInheritance *plugin)
+{
+ g_return_if_fail (plugin->graph != NULL);
+
+ if (plugin->layout_started)
+ gvFreeLayout(plugin->gvc, plugin->graph);
+
+ gvLayout (plugin->gvc, plugin->graph, "dot");
+ plugin->layout_started = TRUE;
+
+ /* DEBUG */
+ /* gvRenderFilename (plugin->gvc, plugin->graph, "png", "class-inheritance-test.png"); */
}
/*----------------------------------------------------------------------------
@@ -946,25 +870,29 @@ cls_inherit_draw_graph (AnjutaClassInheritance *plugin)
* canvas
*/
void
-class_inheritance_update_graph (AnjutaClassInheritance *plugin)
+cls_inherit_update (AnjutaClassInheritance *plugin)
{
IAnjutaSymbolManager *sm;
IAnjutaIterable *iter;
IAnjutaSymbol *symbol;
- GList *node;
- GTree *klass_parents;
- GList *klasses_list;
+ ClsNode *cls_node;
g_return_if_fail (plugin != NULL);
+ /* Recycle graphic engine */
+ cls_inherit_clear (plugin);
+
if (plugin->top_dir == NULL)
return;
sm = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
IAnjutaSymbolManager, NULL);
if (!sm)
+ {
+ /* fixme: clean grahp here */
return;
-
+ }
+
/* Get all classes */
iter = ianjuta_symbol_manager_search (sm, IANJUTA_SYMBOL_TYPE_CLASS,
TRUE,
@@ -974,37 +902,16 @@ class_inheritance_update_graph (AnjutaClassInheritance *plugin)
FALSE, -1, -1, NULL);
if (!iter)
{
- DEBUG_PRINT ("%s", "class_inheritance_update_graph (): search returned no items.");
+ DEBUG_PRINT ("%s", "cls_inherit_update_graph (): search returned no items.");
return;
}
- /*
- DEBUG_PRINT ("Number of classes found = %d",
- ianjuta_iterable_get_length (iter, NULL));
-
-
- do {
- const gchar *class_name;
- symbol = IANJUTA_SYMBOL (iter);
- class_name = ianjuta_symbol_get_name (symbol, NULL);
- DEBUG_PRINT ("=======> %s", class_name);
- }
- while (ianjuta_iterable_next (iter, NULL) == TRUE);
- */
-
ianjuta_iterable_first (iter, NULL);
if (ianjuta_iterable_get_length (iter, NULL) <= 0)
{
g_object_unref (iter);
return;
}
-
- /* initialize the glist and the gtree where to store the klass_ids */
- klasses_list = NULL;
- klass_parents = g_tree_new_full ((GCompareDataFunc)>ree_compare_func,
- NULL,
- NULL,
- g_object_unref);
do
{
gint klass_id;
@@ -1031,87 +938,101 @@ class_inheritance_update_graph (AnjutaClassInheritance *plugin)
/*DEBUG_PRINT ("%s", "ClassInheritance: klass_id cannot be <= 0");*/
continue;
}
-
- if (g_tree_lookup (klass_parents, GINT_TO_POINTER (klass_id)) != NULL)
- {
- /* we already have a class inserted with that name */
- continue;
- }
- /* insert into the gtree a class name id together with the associated parents */
- g_tree_insert (klass_parents, GINT_TO_POINTER (klass_id), parents);
-
- klasses_list = g_list_prepend (klasses_list, GINT_TO_POINTER (klass_id));
-
- } while (ianjuta_iterable_next (iter, NULL) == TRUE);
-
- klasses_list = g_list_reverse (klasses_list);
-
- /* we don't need the classes iter anymore */
- if (iter != NULL)
- g_object_unref (iter);
- else
- return;
+ cls_node = g_hash_table_lookup (plugin->nodes, GINT_TO_POINTER (klass_id));
+ if (!cls_node)
+ {
+ cls_node = cls_inherit_create_node (plugin, symbol);
+ g_hash_table_insert (plugin->nodes, GINT_TO_POINTER (klass_id), cls_node);
+ }
- /* For all classes get their parents */
- node = klasses_list;
- while (node)
- {
- gint klass_id;
- IAnjutaIterable *parents;
- IAnjutaSymbol *klass_symbol;
-
- klass_id = GPOINTER_TO_INT (node->data);
- parents = g_tree_lookup (klass_parents, GINT_TO_POINTER (klass_id));
- klass_symbol = ianjuta_symbol_manager_get_symbol_by_id (sm,
- klass_id,
- IANJUTA_SYMBOL_FIELD_SIMPLE,
- NULL);
-
+ /* Get parents */
do
{
+ gint parent_id;
+ ClsNode *parent_node;
IAnjutaSymbol *parent_symbol;
parent_symbol = IANJUTA_SYMBOL (parents);
+ parent_id = ianjuta_symbol_get_id (parent_symbol, NULL);
- cls_inherit_add_node (plugin, klass_symbol);
- cls_inherit_add_node (plugin, parent_symbol);
- cls_inherit_add_edge (plugin, parent_symbol, klass_symbol);
+ parent_node = g_hash_table_lookup (plugin->nodes, GINT_TO_POINTER (parent_id));
+ if (!parent_node)
+ {
+ parent_node = cls_inherit_create_node (plugin, parent_symbol);
+ g_hash_table_insert (plugin->nodes, GINT_TO_POINTER (parent_id), parent_node);
+ }
+ cls_node_add_edge (parent_node, cls_node);
} while (ianjuta_iterable_next (parents, NULL) == TRUE);
+ g_object_unref (parents);
- /* we don't need it anymore */
- g_object_unref (klass_symbol);
-
- /* parse next deriver class in the glist */
- node = g_list_next (node);
- }
+ } while (ianjuta_iterable_next (iter, NULL) == TRUE);
+
+ g_object_unref (iter);
- g_list_free (klasses_list);
- g_tree_destroy (klass_parents);
- cls_inherit_draw_graph (plugin);
+ cls_inherit_layout (plugin);
+ cls_inherit_draw (plugin);
}
-void
-class_inheritance_gtree_clear (AnjutaClassInheritance *plugin) {
-
- if (plugin->expansion_node_list == NULL)
- return;
-
- /* destroy the nodestatus hash table */
- g_tree_destroy (plugin->expansion_node_list);
+void
+cls_inherit_clear (AnjutaClassInheritance *plugin)
+{
+ g_hash_table_remove_all (plugin->nodes);
+}
+
+/*----------------------------------------------------------------------------
+ * Perform a dot_cleanup and a graph closing. Call this function at the end of
+ * call to draw_graph.
+ */
+void
+cls_inherit_free (AnjutaClassInheritance *plugin)
+{
+ if (plugin->nodes)
+ g_hash_table_destroy (plugin->nodes);
+ plugin->nodes = NULL;
+
+ /* Destroy graphics */
+ if (plugin->graph != NULL)
+ {
+ gvFreeLayout (plugin->gvc, plugin->graph);
+ agclose (plugin->graph);
+ }
+ if (plugin->gvc != NULL )
+ {
+ gvFreeContext (plugin->gvc);
+ }
+ plugin->graph = NULL;
+ plugin->gvc = NULL;
+ plugin->layout_started = FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * initialize the internal graphviz structure.
+ */
+static void
+cls_inherit_graph_init (AnjutaClassInheritance *plugin, gchar* graph_label)
+{
+ Agsym_t *sym;
+ gchar dpi_text[16];
+
+ snprintf (dpi_text, 16, "%d", INCH_TO_PIXELS_CONVERSION_FACTOR);
+ aginit ();
+ plugin->graph = agopen (graph_label, AGDIGRAPH);
+ plugin->gvc = gvContext();
+ plugin->layout_started = FALSE;
- /* reinitialize the table */
- plugin->expansion_node_list =
- g_tree_new_full ((GCompareDataFunc)>ree_compare_func,
- NULL,
- NULL,
- (GDestroyNotify)cls_inherit_nodestatus_destroy);
+ if (!(sym = agfindattr(plugin->graph->proto->n, "dpi")))
+ sym = agraphattr(plugin->graph, "dpi", dpi_text);
+ agxset(plugin->graph, sym->index, dpi_text);
}
void
-class_inheritance_base_gui_init (AnjutaClassInheritance *plugin)
+cls_inherit_init (AnjutaClassInheritance *plugin)
{
GtkWidget *s_window;
+ /* Initialize graph layout engine */
+ cls_inherit_graph_init (plugin, _(DEFAULT_GRAPH_NAME));
+
s_window = gtk_scrolled_window_new (NULL, NULL);
plugin->canvas = gnome_canvas_new ();
/*gtk_widget_modify_bg (plugin->canvas, GTK_STATE_NORMAL,
@@ -1126,9 +1047,9 @@ class_inheritance_base_gui_init (AnjutaClassInheritance *plugin)
CANVAS_MIN_SIZE);
gnome_canvas_set_scroll_region (GNOME_CANVAS (plugin->canvas),
-CANVAS_MIN_SIZE/2,
+ -CANVAS_MIN_SIZE/2,
CANVAS_MIN_SIZE/2,
- CANVAS_MIN_SIZE/2,
- -CANVAS_MIN_SIZE/2);
+ CANVAS_MIN_SIZE/2);
/* Use text background (normally white) for canvas background */
gtk_widget_modify_bg (plugin->canvas, GTK_STATE_NORMAL,
@@ -1137,11 +1058,12 @@ class_inheritance_base_gui_init (AnjutaClassInheritance *plugin)
g_signal_connect (G_OBJECT (plugin->canvas), "event",
G_CALLBACK (on_canvas_event),
plugin);
-
+ /*
g_signal_connect (G_OBJECT (plugin->canvas),
"style_set",
G_CALLBACK (on_style_set),
plugin);
+ */
plugin->widget = gtk_vbox_new (FALSE, 2);
/* --packing-- */
@@ -1151,14 +1073,8 @@ class_inheritance_base_gui_init (AnjutaClassInheritance *plugin)
gtk_widget_show_all (plugin->widget);
/* create new GList */
- plugin->drawable_list = NULL;
- plugin->node_list = NULL;
-
- plugin->expansion_node_list =
- g_tree_new_full ((GCompareDataFunc)>ree_compare_func,
- NULL, NULL,
- (GDestroyNotify)cls_inherit_nodestatus_destroy);
-
+ plugin->nodes = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
+ (GDestroyNotify)cls_node_free);
/* menu create */
plugin->menu = gtk_menu_new ();
diff --git a/plugins/class-inheritance/class-inherit.h b/plugins/class-inheritance/class-inherit.h
index 09c52a8..e7a07c4 100644
--- a/plugins/class-inheritance/class-inherit.h
+++ b/plugins/class-inheritance/class-inherit.h
@@ -1,7 +1,8 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
- * Copyright (C) Massimo Cora' 2005 <maxcvs email it>
- *
+ * Copyright (C) Massimo Cora' 2005 <maxcvs email it>,
+ * 2009 Naba Kumar <naba gnome org>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -30,42 +31,72 @@ G_BEGIN_DECLS
#define NODE_HALF_DISPLAY_ELEM_NUM 30
#define NODE_SHOW_ALL_MEMBERS_STR N_("Show all members...")
-typedef struct _NodeData {
- GnomeCanvasItem *canvas_item; /* item itself */
- gint klass_id; /* unique class identifier */
- gchar *sub_item; /* case of an expanded node */
- gboolean anchored; /* should it be anchored [e.g. paint all the
- * data to the graph?]
- */
- GtkWidget *menu;
- AnjutaClassInheritance *plugin;
-} NodeData;
-
-typedef struct _NodeExpansionStatus {
+typedef enum {
+ CLS_NODE_COLLAPSED,
+ CLS_NODE_SEMI_EXPANDED,
+ CLS_NODE_FULL_EXPANDED
+} ClsNodeExpansionType;
+
+typedef struct
+{
+ AnjutaClassInheritance *plugin; /* fixme: remove this */
+ Agraph_t *graph;
+ GtkWidget* canvas;
+
+ IAnjutaSymbolManager *sym_manager;
gint klass_id;
- gint expansion_status;
+ gchar *sym_name;
+
+ Agnode_t *agnode;
+
+ /* Node's expansion status */
+ ClsNodeExpansionType expansion_status;
+
+ /* Holds canvas group item for either collapsed or expanded node */
+ GnomeCanvasItem* canvas_group;
-} NodeExpansionStatus;
-
-enum {
- NODE_NOT_EXPANDED,
- NODE_HALF_EXPANDED,
- NODE_FULL_EXPANDED
-};
-
-gchar *
-class_inheritance_create_agnode_key_name (const IAnjutaSymbol* symbol);
-
-IAnjutaSymbol *
-class_inheritance_get_symbol_from_agnode_key_name (AnjutaClassInheritance *plugin,
- const gchar *key);
-
-void class_inheritance_base_gui_init (AnjutaClassInheritance *plugin);
-void class_inheritance_update_graph (AnjutaClassInheritance *plugin);
-void class_inheritance_clean_canvas (AnjutaClassInheritance *plugin);
-void class_inheritance_show_dynamic_class_popup_menu (GdkEvent *event,
- NodeData* nodedata);
-void class_inheritance_gtree_clear (AnjutaClassInheritance *plugin);
+ /* What expansion type is currently drawn */
+ ClsNodeExpansionType drawn_expansion_status;
+
+ /* Absolute coords in canvas. Only valid after node draw is ensured */
+ gint width, height, x1, y1, x2, y2;
+
+ /* Class members. Empty for collapsed nodes */
+ GHashTable *members;
+
+ /* All outgoing edges from this node */
+ GList *edges;
+} ClsNode;
+
+typedef struct {
+ Agedge_t *agedge;
+ GnomeCanvasItem *canvas_line;
+ GnomeCanvasItem *canvas_arrow;
+ ClsNode *cls_node_from;
+ ClsNode *cls_node_to;
+} ClsNodeEdge;
+
+typedef struct {
+ ClsNode *cls_node;
+ GnomeCanvasItem* canvas_node_item;
+ gint sym_id;
+ gchar *sym_name;
+ gchar *args;
+ GFile *file;
+ gint line;
+ GdkPixbuf *icon;
+ gint order;
+} ClsNodeItem;
+
+gboolean cls_node_collapse (ClsNode *cls_node);
+gboolean cls_node_expand (ClsNode *cls_node, ClsNodeExpansionType expand_type);
+
+void cls_inherit_init (AnjutaClassInheritance *plugin);
+void cls_inherit_layout (AnjutaClassInheritance *plugin);
+void cls_inherit_draw (AnjutaClassInheritance *plugin);
+void cls_inherit_update (AnjutaClassInheritance *plugin);
+void cls_inherit_clear (AnjutaClassInheritance *plugin);
+void cls_inherit_free (AnjutaClassInheritance *plugin);
G_END_DECLS
diff --git a/plugins/class-inheritance/plugin.c b/plugins/class-inheritance/plugin.c
index f18dac2..e5771ff 100644
--- a/plugins/class-inheritance/plugin.c
+++ b/plugins/class-inheritance/plugin.c
@@ -59,7 +59,7 @@ project_root_added (AnjutaPlugin *plugin, const gchar *name,
ci_plugin->top_dir = NULL;
/* let's update the graph */
- class_inheritance_update_graph (ci_plugin);
+ cls_inherit_update (ci_plugin);
}
static void
@@ -70,10 +70,7 @@ project_root_removed (AnjutaPlugin *plugin, const gchar *name,
ci_plugin = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
/* clean up the canvas */
- class_inheritance_clean_canvas (ci_plugin);
-
- /* destroy and re-initialize the hashtable */
- class_inheritance_gtree_clear (ci_plugin);
+ cls_inherit_clear (ci_plugin);
if (ci_plugin->top_dir)
g_free(ci_plugin->top_dir);
@@ -98,25 +95,25 @@ register_stock_icons (AnjutaPlugin *plugin)
static gboolean
activate_plugin (AnjutaPlugin *plugin)
{
- AnjutaClassInheritance *class_inheritance;
+ AnjutaClassInheritance *cls_inherit;
static gboolean initialized = FALSE;
DEBUG_PRINT ("%s", "AnjutaClassInheritance: Activating plugin ...");
register_stock_icons (plugin);
- class_inheritance = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
+ cls_inherit = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
- class_inheritance_base_gui_init (class_inheritance);
+ cls_inherit_init (cls_inherit);
- anjuta_shell_add_widget (plugin->shell, class_inheritance->widget,
+ anjuta_shell_add_widget (plugin->shell, cls_inherit->widget,
"AnjutaClassInheritance", _("Inheritance Graph"),
"class-inheritance-plugin-icon",
ANJUTA_SHELL_PLACEMENT_CENTER, NULL);
- class_inheritance->top_dir = NULL;
+ cls_inherit->top_dir = NULL;
/* set up project directory watch */
- class_inheritance->root_watch_id = anjuta_plugin_add_watch (plugin,
+ cls_inherit->root_watch_id = anjuta_plugin_add_watch (plugin,
IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
project_root_added,
project_root_removed, NULL);
@@ -133,13 +130,7 @@ deactivate_plugin (AnjutaPlugin *plugin)
class_inheritance = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
/* clean up the canvas [e.g. destroys it's elements */
- class_inheritance_clean_canvas (class_inheritance);
-
- /* destroy the nodestatus gtree */
- if (class_inheritance->expansion_node_list) {
- g_tree_destroy (class_inheritance->expansion_node_list);
- class_inheritance->expansion_node_list = NULL;
- }
+ cls_inherit_free (class_inheritance);
/* Container holds the last ref to this widget so it will be destroyed as
* soon as removed. No need to separately destroy it. */
@@ -187,7 +178,6 @@ class_inheritance_instance_init (GObject *obj)
plugin->widget = NULL;
plugin->graph = NULL;
plugin->gvc = NULL;
- plugin->expansion_node_list = NULL;
}
static void
diff --git a/plugins/class-inheritance/plugin.h b/plugins/class-inheritance/plugin.h
index 49a73b3..cfcb2dd 100644
--- a/plugins/class-inheritance/plugin.h
+++ b/plugins/class-inheritance/plugin.h
@@ -38,27 +38,24 @@ extern GType class_inheritance_get_type (GTypeModule *module);
#define ANJUTA_IS_PLUGIN_CLASS_INHERITANCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ANJUTA_TYPE_PLUGIN_CLASS_INHERITANCE))
#define ANJUTA_PLUGIN_CLASS_INHERITANCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANJUTA_TYPE_PLUGIN_CLASS_INHERITANCE, AnjutaClassInheritanceClass))
-
typedef struct _AnjutaClassInheritance AnjutaClassInheritance;
typedef struct _AnjutaClassInheritanceClass AnjutaClassInheritanceClass;
struct _AnjutaClassInheritance {
AnjutaPlugin parent;
- GtkWidget *widget; /* a vbox */
+ GtkWidget *widget; /* a vbox */
GtkWidget *update_button;
GtkWidget *menu;
GtkWidget *update;
GtkWidget *canvas;
- GList *drawable_list; /* GnomeCanvasItem* list. Edges, arrows and texts */
- GList *node_list; /* NodeData* list */
-
- GTree *expansion_node_list; /* expansion_status for the nodes */
+ GHashTable *nodes;
/* graphviz stuff */
GVC_t *gvc;
Agraph_t *graph;
+ gboolean layout_started;
gchar *top_dir;
guint root_watch_id;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]