[anjuta/cls-inherit-foocanvas] class-inheritance: Copied class-inheritance plugin from anjuta-extras



commit 7f4095a28fe9b4c7f7fc886cf5ebd40bd4d58f7c
Author: Naba Kumar <naba gnome org>
Date:   Fri May 7 19:53:30 2010 +0300

    class-inheritance: Copied class-inheritance plugin from anjuta-extras

 configure.in                                       |   54 +
 plugins/Makefile.am                                |    1 +
 plugins/class-inheritance/Makefile.am              |   63 +
 .../anjuta-class-inheritance-plugin-48.png         |  Bin 0 -> 980 bytes
 .../anjuta-class-inheritance-plugin.svg            |  311 +++++
 .../anjuta-class-inheritance.plugin.in             |    5 +
 plugins/class-inheritance/class-callbacks.c        |  448 ++++++++
 plugins/class-inheritance/class-callbacks.h        |   47 +
 plugins/class-inheritance/class-inherit.c          | 1214 ++++++++++++++++++++
 plugins/class-inheritance/class-inherit.h          |  119 ++
 plugins/class-inheritance/plugin.c                 |  197 ++++
 plugins/class-inheritance/plugin.h                 |   87 ++
 12 files changed, 2546 insertions(+), 0 deletions(-)
---
diff --git a/configure.in b/configure.in
index 64d486e..f057cc1 100644
--- a/configure.in
+++ b/configure.in
@@ -46,6 +46,7 @@ LIBWNCK_REQUIRED=2.12
 GDA_REQUIRED=4.0.0
 UNIQUE_REQUIRED=1.0.0
 VALA_REQUIRED=0.7.8
+LIBGRAPHVIZ_REQUIRED=1.0
 
 AC_SUBST(GLIB_REQUIRED)
 AC_SUBST(GDK_PIXBUF_REQUIRED)
@@ -65,6 +66,7 @@ AC_SUBST(GTKSOURCEVIEW_REQUIRED)
 AC_SUBST(LIBWNCK_REQUIRED)
 AC_SUBST(GDA_REQUIRED)
 AC_SUBST(UNIQUE_REQUIRED)
+AC_SUBST(LIBGRAPHVIZ_REQUIRED)
 
 AM_INIT_AUTOMAKE([1.9 dist-bzip2 no-dist-gzip])
 AC_CONFIG_HEADERS(config.h)
@@ -769,6 +771,57 @@ fi
 
 AC_SUBST(SYMBOL_DB_SHM)
 
+
+dnl Check for graphviz (class inheritance and profiler plugins)
+dnl --------------------------------------------------------------------------
+dnl FIXME: For some strange reason graphviz-devel rpm install the *.pc files
+dnl in /usr/lib/graphviz/pkgconfig, instead of usual /usr/lib/pkgconfig. This
+dnl makes pkgconfig check fail if we don't add the above path in
+dnl PKG_CONFIG_PATH. We have added both /usr/lib/graphviz/pkgconfig and
+dnl /usr/local/lib/pkgconfig paths. If graphviz is installed in other prefix
+dnl (other than /usr or /usr/local or the current installation prefix),
+dnl following pkgconfig check will fail.
+dnl --------------------------------------------------------------------------
+AC_ARG_ENABLE(graphviz,
+	AC_HELP_STRING([--disable-graphviz],[Disable GraphViz support in Anjuta]), 
+	[ if test "$enableval" = "no"; then
+		user_disabled_graphviz=1
+	  fi ],
+	[ user_disabled_graphviz=0 ])
+
+AC_MSG_CHECKING(if GraphViz support is disabled)
+if test "$user_disabled_graphviz" = 1; then
+	AC_MSG_RESULT(yes)
+	libgraphviz_found="no"
+else
+	AC_MSG_RESULT(no)
+	
+	dnl Set pkgconfig path
+	ANJUTA_PKG_CONFIG_PATH_SAVE="${PKG_CONFIG_PATH}"
+	PKG_CONFIG_PATH="/usr/lib/graphviz/pkgconfig:$PKG_CONFIG_PATH"
+	PKG_CONFIG_PATH="/usr/local/lib/graphviz/pkgconfig:$PKG_CONFIG_PATH"
+	PKG_CONFIG_PATH="/usr/lib64/graphviz/pkgconfig:$PKG_CONFIG_PATH"
+	PKG_CONFIG_PATH="/usr/local/lib64/graphviz/pkgconfig:$PKG_CONFIG_PATH"
+	
+	anjuta_save_prefix="$prefix"
+	test "x$prefix" = xNONE && prefix=$ac_default_prefix
+	graphviz_pkgconfig=`eval echo ${libdir}/graphviz/pkgconfig`
+	PKG_CONFIG_PATH="$graphviz_pkgconfig:$PKG_CONFIG_PATH"
+	prefix="$anjuta_save_prefix"
+
+	export PKG_CONFIG_PATH
+	PKG_CHECK_MODULES(GRAPHVIZ,
+		[libgvc >= $LIBGRAPHVIZ_REQUIRED libgraph >= $LIBGRAPHVIZ_REQUIRED], 
+		[libgraphviz_found="yes"],
+		[libgraphviz_found="no"])
+	
+	dnl Restore pkgconfig path
+	PKG_CONFIG_PATH="${ANJUTA_PKG_CONFIG_PATH_SAVE}"
+	export PKG_CONFIG_PATH
+fi
+
+AM_CONDITIONAL(HAVE_GRAPHVIZ, [test x$libgraphviz_found = xyes])
+
 dnl --------- help outputs -----------
 dnl manuals/C/Makefile
 dnl manuals/C/anjuta-tutorial/Makefile
@@ -808,6 +861,7 @@ plugins/Makefile
 plugins/gtodo/Makefile
 plugins/class-gen/Makefile
 plugins/class-gen/templates/Makefile
+plugins/class-inheritance/Makefile
 plugins/patch/Makefile
 plugins/document-manager/Makefile
 plugins/document-manager/images/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 329fd2b..13ba3da 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -15,6 +15,7 @@ SUBDIRS = . \
 	cvs-plugin \
 	macro \
 	class-gen \
+	class-inheritance \
 	patch \
 	subversion \
 	project-import \
diff --git a/plugins/class-inheritance/Makefile.am b/plugins/class-inheritance/Makefile.am
new file mode 100644
index 0000000..09b8eb1
--- /dev/null
+++ b/plugins/class-inheritance/Makefile.am
@@ -0,0 +1,63 @@
+
+if HAVE_GRAPHVIZ
+
+# Plugin Icon file
+cls_inheritance_pixmapsdir = $(anjuta_image_dir)
+cls_inheritance_pixmaps_DATA = \
+	anjuta-class-inheritance-plugin.svg \
+	anjuta-class-inheritance-plugin-48.png
+
+# Plugin description file
+plugin_in_files = anjuta-class-inheritance.plugin.in
+%.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+
+cls_inheritance_plugindir = $(anjuta_plugin_dir)
+cls_inheritance_plugin_DATA = $(plugin_in_files:.plugin.in=.plugin)
+
+# NOTE :
+# The naming convention is very intentional
+# We are forced to use the prefix 'lib' by automake and libtool
+#    There is probably a way to avoid it but it is not worth to effort
+#    to find out.
+# The 'anjuta_' prfix is a safety measure to avoid conflicts where the
+#    plugin 'libpython.so' needs to link with the real 'libpython.so'
+
+# Include paths
+AM_CPPFLAGS = \
+	$(LIBFOOCANVAS_CFLAGS) \
+	$(LIBANJUTA_CFLAGS) \
+	$(EXTRA_CFLAGS) \
+	$(GRAPHVIZ_CFLAGS) \
+	-DG_LOG_DOMAIN=\"libanjuta-class-inheritance\"
+
+# Where to install the plugin
+plugindir = $(anjuta_plugin_dir)
+
+# The plugin
+plugin_LTLIBRARIES = libanjuta-class-inheritance.la
+
+libanjuta_class_inheritance_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
+
+# Plugin dependencies
+libanjuta_class_inheritance_la_LIBADD = \
+	$(LIBFOOCANVAS_LIBS) \
+	$(LIBANJUTA_LIBS) \
+	$(GRAPHVIZ_LIBS)
+
+# Plugin sources
+libanjuta_class_inheritance_la_SOURCES = \
+	plugin.c \
+	plugin.h \
+	class-inherit.c \
+	class-inherit.h \
+	class-callbacks.c \
+	class-callbacks.h 
+
+endif
+
+EXTRA_DIST = \
+	$(plugin_in_files) \
+	$(cls_inheritance_plugin_DATA) \
+	$(cls_inheritance_ui_DATA) \
+	$(cls_inheritance_glade_DATA) \
+	$(cls_inheritance_pixmaps_DATA)
diff --git a/plugins/class-inheritance/anjuta-class-inheritance-plugin-48.png b/plugins/class-inheritance/anjuta-class-inheritance-plugin-48.png
new file mode 100644
index 0000000..04e3608
Binary files /dev/null and b/plugins/class-inheritance/anjuta-class-inheritance-plugin-48.png differ
diff --git a/plugins/class-inheritance/anjuta-class-inheritance-plugin.svg b/plugins/class-inheritance/anjuta-class-inheritance-plugin.svg
new file mode 100644
index 0000000..1f50cc7
--- /dev/null
+++ b/plugins/class-inheritance/anjuta-class-inheritance-plugin.svg
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://web.resource.org/cc/";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:xlink="http://www.w3.org/1999/xlink";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.45.1"
+   width="48"
+   height="48"
+   version="1.0"
+   sodipodi:docbase="/home/maker/icons/anjuta-new2/plugins"
+   sodipodi:docname="anjuta-class-inheritance.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="/home/maker/icons/anjuta-new2/plugins/anjuta-class-inheritance-plugin-48.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <sodipodi:namedview
+     inkscape:cy="12.527183"
+     inkscape:cx="23.616362"
+     inkscape:zoom="1"
+     inkscape:window-height="923"
+     inkscape:window-width="1044"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     width="48px"
+     height="48px"
+     showgrid="true"
+     inkscape:window-x="0"
+     inkscape:window-y="32"
+     inkscape:current-layer="svg2" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs5">
+    <marker
+       style="overflow:visible"
+       id="TriangleOutS"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="TriangleOutS"
+       refX="0.0">
+      <path
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         id="path3274"
+         transform="scale(0.2)"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="TriangleOutM"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="TriangleOutM"
+       refX="0.0">
+      <path
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         id="path3271"
+         transform="scale(0.4)"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " />
+    </marker>
+    <marker
+       style="overflow:visible;"
+       id="Arrow2Send"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="Arrow2Send"
+       refX="0.0">
+      <path
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         id="path3203"
+         transform="scale(0.3) rotate(180) translate(-2.3,0)"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow2Sstart"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="Arrow2Sstart"
+       refX="0.0">
+      <path
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
+         id="path3200"
+         transform="scale(0.3) translate(-2.3,0)"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " />
+    </marker>
+    <marker
+       style="overflow:visible;"
+       id="Arrow1Send"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="Arrow1Send"
+       refX="0.0">
+      <path
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         id="path3185"
+         transform="scale(0.2) rotate(180) translate(6,0)"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="Arrow1Sstart"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="Arrow1Sstart"
+       refX="0.0">
+      <path
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         id="path3182"
+         transform="scale(0.2) translate(6,0)"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="TriangleInS"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="TriangleInS"
+       refX="0.0">
+      <path
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         id="path3265"
+         transform="scale(-0.2)"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="TriangleInM"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="TriangleInM"
+       refX="0.0">
+      <path
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         id="path3262"
+         transform="scale(-0.4)"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " />
+    </marker>
+    <marker
+       style="overflow:visible;"
+       id="Arrow2Mend"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="Arrow2Mend"
+       refX="0.0">
+      <path
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         id="path3197"
+         transform="scale(0.6) rotate(180) translate(0,0)"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " />
+    </marker>
+    <linearGradient
+       id="linearGradient3146"
+       inkscape:collect="always">
+      <stop
+         offset="0"
+         style="stop-color:#204a87;stop-opacity:1;"
+         id="stop3148" />
+      <stop
+         offset="1"
+         style="stop-color:#204a87;stop-opacity:0;"
+         id="stop3150" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3136">
+      <stop
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;"
+         id="stop3138" />
+      <stop
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         id="stop3140" />
+    </linearGradient>
+    <radialGradient
+       r="22.499998"
+       id="radialGradient3144"
+       fx="58.651649"
+       fy="14.520809"
+       gradientUnits="userSpaceOnUse"
+       inkscape:collect="always"
+       cy="14.520809"
+       cx="58.651649"
+       xlink:href="#linearGradient3136"
+       gradientTransform="matrix(1,0,0,1.2111365,-109,0.9341241)" />
+    <linearGradient
+       id="linearGradient3152"
+       gradientUnits="userSpaceOnUse"
+       inkscape:collect="always"
+       x1="58.446415"
+       y1="5.2448635"
+       xlink:href="#linearGradient3146"
+       gradientTransform="translate(-109,3.9999963)"
+       x2="58.651649"
+       y2="-12.72976" />
+    <linearGradient
+       id="linearGradient6308"
+       gradientUnits="userSpaceOnUse"
+       inkscape:collect="always"
+       x1="15"
+       y1="8.7244282"
+       xlink:href="#linearGradient3136"
+       x2="15"
+       y2="21.010408" />
+    <linearGradient
+       id="linearGradient6316"
+       gradientUnits="userSpaceOnUse"
+       inkscape:collect="always"
+       x1="34.452351"
+       y1="30.287689"
+       xlink:href="#linearGradient3136"
+       gradientTransform="translate(0,2)"
+       x2="34.398602"
+       y2="37.977474" />
+    <linearGradient
+       id="linearGradient6324"
+       gradientUnits="userSpaceOnUse"
+       inkscape:collect="always"
+       x1="33.83363"
+       y1="11.906407"
+       xlink:href="#linearGradient3136"
+       x2="33.868267"
+       y2="18.005203" />
+    <marker
+       style="overflow:visible"
+       id="TriangleOutSu"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="TriangleOutSu"
+       refX="0.0">
+      <path
+         style="marker-start:none;stroke:#ad7fa8;stroke-width:1.0pt;fill:#ad7fa8;fill-rule:evenodd"
+         id="path2223"
+         transform="scale(0.2)"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " />
+    </marker>
+    <marker
+       style="overflow:visible"
+       id="TriangleOutSb"
+       orient="auto"
+       refY="0.0"
+       inkscape:stockid="TriangleOutSb"
+       refX="0.0">
+      <path
+         style="marker-start:none;stroke:#ef2929;stroke-width:1.0pt;fill:#ef2929;fill-rule:evenodd"
+         id="path2305"
+         transform="scale(0.2)"
+         d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z " />
+    </marker>
+  </defs>
+  <path
+     style="stroke-linejoin:miter;marker-end:url(#TriangleOutSu);stroke-opacity:1;fill-rule:evenodd;marker-start:none;fill-opacity:0.75;stroke-dashoffset:0;stroke:#ad7fa8;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-width:3;fill:none"
+     d="M 14.977505,23.248699 L 14.933311,36.109121 L 23.818783,36.042858"
+     sodipodi:nodetypes="ccc"
+     id="path3379" />
+  <rect
+     style="opacity:1;fill:url(#linearGradient6308);fill-opacity:1.0;fill-rule:nonzero;stroke:#75507b;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+     id="rect3154"
+     width="16"
+     rx="0.057870258"
+     ry="0.057870261"
+     y="7"
+     x="7"
+     height="16" />
+  <path
+     style="stroke-linejoin:miter;marker-end:url(#TriangleOutSb);stroke-opacity:1;fill-rule:evenodd;marker-start:none;fill-opacity:0.75;stroke-dashoffset:0;stroke:#ef2929;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-width:3;fill:none"
+     id="path3165"
+     sodipodi:nodetypes="cc"
+     d="M 34.949104,19.05688 L 34.949104,25.846793" />
+  <rect
+     style="opacity:1;fill:url(#linearGradient6324);fill-opacity:1.0;fill-rule:nonzero;stroke:#cc0000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+     id="rect3156"
+     width="12"
+     rx="0.057870254"
+     ry="0.057870261"
+     y="11"
+     x="28.999998"
+     height="8" />
+  <rect
+     style="opacity:1;fill:url(#linearGradient6316);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.99999988;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+     id="rect3163"
+     width="12"
+     rx="0.057870258"
+     ry="0.057870265"
+     y="31"
+     x="29"
+     height="10" />
+</svg>
diff --git a/plugins/class-inheritance/anjuta-class-inheritance.plugin.in b/plugins/class-inheritance/anjuta-class-inheritance.plugin.in
new file mode 100644
index 0000000..6c0bb6f
--- /dev/null
+++ b/plugins/class-inheritance/anjuta-class-inheritance.plugin.in
@@ -0,0 +1,5 @@
+[Anjuta Plugin]
+Location=anjuta-class-inheritance:AnjutaClassInheritance
+Icon=anjuta-class-inheritance-plugin-48.png
+_Name=Class Inheritance
+_Description=A graph painter for the inheritance of the classes.
diff --git a/plugins/class-inheritance/class-callbacks.c b/plugins/class-inheritance/class-callbacks.c
new file mode 100644
index 0000000..4628420
--- /dev/null
+++ b/plugins/class-inheritance/class-callbacks.c
@@ -0,0 +1,448 @@
+/*
+ *  Copyright (C) Massimo Cora' 2005 <maxcvs email it>
+ *
+ *  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
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-symbol-manager.h>
+
+#include "plugin.h"
+#include "class-callbacks.h"
+#include "class-inherit.h"
+
+gint
+on_canvas_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data) 
+{
+	AnjutaClassInheritance *plugin;
+	plugin = ANJUTA_PLUGIN_CLASS_INHERITANCE (data);
+	
+	switch (event->type)
+	{
+	case GDK_BUTTON_PRESS:
+		if (event->button.button == 3)
+		{
+			g_return_val_if_fail (plugin->menu != NULL, FALSE);
+			
+			gtk_menu_popup (GTK_MENU (plugin->menu), NULL, NULL, NULL, NULL, 
+							event->button.button, event->button.time);
+		}
+		break;
+
+	default:
+		break;
+	}
+	
+	return FALSE;
+}
+
+gint
+on_canvas_event_proxy (GnomeCanvasItem *item, GdkEvent *event,
+                       GnomeCanvasItem *proxy_item)
+{
+	gint ret;
+
+	g_signal_emit_by_name (G_OBJECT (proxy_item), "event", event, &ret);
+	return ret;
+}
+
+gint
+on_expanded_class_title_event (GnomeCanvasItem *item, GdkEvent *event,
+                               ClsNode *cls_node)
+{
+	GnomeCanvasItem *text_item;
+	text_item = g_object_get_data (G_OBJECT (item), "__text__");
+	switch (event->type)
+	{
+	case GDK_BUTTON_PRESS:		/* single click */
+		if (event->button.button == 1 &&
+		    cls_node->expansion_status != CLS_NODE_COLLAPSED &&
+		    cls_node_collapse (cls_node))
+		{
+			cls_inherit_draw(cls_node->plugin);
+			return TRUE;
+		}
+		break;
+		
+	case GDK_ENTER_NOTIFY:		/* mouse entered in title's area */
+		gnome_canvas_item_set (item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_TITLE_PRELIGHT_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_TITLE_PRELIGHT_FG],
+							   NULL);
+		return TRUE;
+
+	case GDK_LEAVE_NOTIFY:		/* mouse exited title's area */
+		gnome_canvas_item_set (item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_TITLE_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_TITLE_FG],
+							   NULL);
+		return TRUE;
+	default:
+		break;
+	}
+	return FALSE;
+}
+
+static GnomeCanvasItem*
+create_class_item_tooltip (ClsNode *cls_node, const gchar *tooltip_text)
+{
+	GnomeCanvasItem *group, *canvas_item, *text_item;
+	gdouble text_width_value, text_height_value;
+
+	group =
+		gnome_canvas_item_new (gnome_canvas_root
+			                   (GNOME_CANVAS (cls_node->canvas)),
+			                   gnome_canvas_group_get_type (),
+			                   NULL);
+	
+	text_item =
+		gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
+					           gnome_canvas_text_get_type (),
+					           "text", tooltip_text,
+					           "justification", GTK_JUSTIFY_LEFT,
+					           "anchor", GTK_ANCHOR_CENTER,
+					           "fill_color_gdk",
+					           &cls_node->plugin->style[STYLE_ITEM_FG],
+					           NULL);
+
+	g_object_get (text_item, "text_width", &text_width_value,
+	              "text_height", &text_height_value, NULL);
+
+	gnome_canvas_item_set (text_item,
+	                       "x", (gdouble) 10 + text_width_value/2,
+				           "y", (gdouble) 10 + text_height_value/2,
+	                       	NULL);
+	/* Decoration */
+	GnomeCanvasPoints *points = gnome_canvas_points_new (8);
+	gint i = 0;
+	points->coords[i++] = 0;
+	points->coords[i++] = 0;
+	
+	points->coords[i++] = 30;
+	points->coords[i++] = 0;
+
+	points->coords[i++] = 40;
+	points->coords[i++] = -10;
+
+	points->coords[i++] = 50;
+	points->coords[i++] = 0;
+
+	points->coords[i++] = text_width_value + 20;
+	points->coords[i++] = 0;
+
+	points->coords[i++] = text_width_value + 20;
+	points->coords[i++] = text_height_value + 20;
+
+	points->coords[i++] = 0;
+	points->coords[i++] = text_height_value + 20;
+	
+	points->coords[i++] = 0;
+	points->coords[i++] = 0;
+
+	/* background */
+	canvas_item =
+		gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
+			                   gnome_canvas_polygon_get_type (),
+			                   "points", points,
+			                   "fill_color_gdk",
+			                   &cls_node->plugin->style[STYLE_ITEM_BG],
+			                   NULL);
+	/* border */
+	canvas_item =
+		gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
+	                       gnome_canvas_line_get_type (),
+	                       "points", points,
+	                       "fill_color_gdk",
+	                       &cls_node->plugin->style[STYLE_ITEM_FG],
+	                       NULL);
+	/* shadow */
+	canvas_item =
+		gnome_canvas_item_new (GNOME_CANVAS_GROUP (group),
+	                       gnome_canvas_polygon_get_type (),
+	                       "points", points,
+	                       "fill_color_gdk",
+	                       &cls_node->plugin->style[STYLE_TITLE_BG],
+	                       NULL);
+	gnome_canvas_points_unref (points);
+
+	/* Lower shadow */
+	gnome_canvas_item_lower (canvas_item, 10);
+
+	/* Offset shadow */
+	gnome_canvas_item_move (canvas_item, 5, 5);
+
+	/* Raise text */
+	gnome_canvas_item_raise (text_item, 10);
+	return group;
+}
+
+static gboolean
+on_canvas_item_show_tooltip_timeout (ClsNodeItem *node_item)
+{
+	gchar *tooltip;
+	gdouble x, y, x1, x2, y2;
+	
+	if (node_item->tooltip)
+		gtk_object_destroy (GTK_OBJECT (node_item->tooltip));
+	node_item->tooltip = NULL;
+	
+	if (node_item->args && strlen (node_item->args) > 2)
+	{
+		tooltip = g_strdup_printf (_("Args: %s"), node_item->args);
+
+		node_item->tooltip =
+			create_class_item_tooltip (node_item->cls_node, tooltip);
+		g_free (tooltip);
+	
+		g_object_get (node_item->cls_node->canvas_group, "x", &x, "y", &y, NULL);
+		g_object_get (node_item->canvas_node_item, "x1", &x1, "x2", &x2,
+				      "y2", &y2, NULL);
+		x = x + x1 + 25;
+		y = y + y2 + 10;
+
+		gnome_canvas_item_w2i (node_item->tooltip, &x, &y);
+		gnome_canvas_item_move (node_item->tooltip, x, y);
+		node_item->tooltip_timeout = 0;
+	}
+	return FALSE;
+}
+
+gint
+on_expanded_class_item_event (GnomeCanvasItem *item, GdkEvent *event,
+                              gpointer data)
+{
+	AnjutaClassInheritance *plugin;
+	ClsNodeItem *node_item;
+	GnomeCanvasItem *text_item;
+	
+	text_item = g_object_get_data (G_OBJECT (item), "__text__");
+	
+	node_item = (ClsNodeItem*)data;
+	plugin = node_item->cls_node->plugin;
+
+	switch (event->type)
+	{
+	case GDK_BUTTON_PRESS:		/* single click */
+		if (event->button.button == 1)
+		{
+			/* 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->plugin->style[STYLE_ITEM_PRELIGHT_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &node_item->cls_node->plugin->style[STYLE_ITEM_PRELIGHT_FG],
+							   NULL);
+		/* Show tooltip */
+		if (!node_item->tooltip)
+		{
+			if (node_item->tooltip_timeout)
+				g_source_remove (node_item->tooltip_timeout);
+			node_item->tooltip_timeout =
+				g_timeout_add (500,
+				               (GSourceFunc)on_canvas_item_show_tooltip_timeout,
+				               node_item);
+		}
+		return TRUE;
+
+	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->plugin->style[STYLE_ITEM_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &node_item->cls_node->plugin->style[STYLE_ITEM_FG],
+							   NULL);
+		/* Hide tooltip */
+		if (node_item->tooltip_timeout)
+			g_source_remove (node_item->tooltip_timeout);
+		node_item->tooltip_timeout = 0;
+		if (node_item->tooltip)
+			gtk_object_destroy (GTK_OBJECT (node_item->tooltip));
+		node_item->tooltip = NULL;
+		
+		return TRUE;
+	default:
+		break;
+	}
+	return FALSE;
+}
+
+gint
+on_expanded_class_more_event (GnomeCanvasItem *item, GdkEvent *event,
+                              ClsNode *cls_node)
+{
+	GnomeCanvasItem *text_item;
+	text_item = g_object_get_data (G_OBJECT (item), "__text__");
+	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_draw(cls_node->plugin);
+		}
+		break;
+		
+	case GDK_ENTER_NOTIFY:		/* mouse entered in more's area */
+		gnome_canvas_item_set (item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_TITLE_PRELIGHT_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_TITLE_PRELIGHT_FG],
+							   NULL);
+		return TRUE;
+
+	case GDK_LEAVE_NOTIFY:		/* mouse exited item's area */
+		gnome_canvas_item_set (item,
+							   "fill_color_gdk",
+		                       &cls_node->plugin->style[STYLE_TITLE_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_TITLE_FG],
+							   NULL);
+		return TRUE;
+	default:
+		break;
+	}
+	
+	return FALSE;
+}
+
+gint
+on_collapsed_class_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
+{
+	AnjutaClassInheritance *plugin;
+	ClsNode *cls_node;
+	GnomeCanvasItem *text_item;
+	text_item = g_object_get_data (G_OBJECT (item), "__text__");
+	
+	cls_node = (ClsNode*)data;
+	plugin = cls_node->plugin;
+
+	switch (event->type)
+	{
+	case GDK_BUTTON_PRESS:		/* single click */
+		if (event->button.button == 1)
+		{
+			if (cls_node_expand (cls_node, CLS_NODE_SEMI_EXPANDED))
+			{
+			    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 (item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_ITEM_PRELIGHT_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_ITEM_PRELIGHT_FG],
+							   NULL);
+		return TRUE;
+
+	case GDK_LEAVE_NOTIFY:		/* mouse exited item's area */
+		/* Make the outline thin */
+		gnome_canvas_item_set (item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_BG],
+							   NULL);
+		gnome_canvas_item_set (text_item,
+							   "fill_color_gdk",
+							   &cls_node->plugin->style[STYLE_FG],
+							   NULL);
+		return TRUE;
+	default:
+		break;
+	}
+	
+	return FALSE;
+}
+
+/*----------------------------------------------------------------------------
+ * callback for the canvas' right-click menu - update button.
+ */
+void
+on_update_menu_item_selected (GtkMenuItem *item,
+							  AnjutaClassInheritance *plugin)
+{
+	cls_inherit_update (plugin);
+}
+
+/*----------------------------------------------------------------------------
+ * callback for theme/colors changes
+ */
+void
+on_style_set (GtkWidget *widget, GtkStyle  *previous_style,
+			  AnjutaClassInheritance *plugin)
+{
+	GtkStyle *style = plugin->canvas->style;
+
+	plugin->style[STYLE_BG] = style->base[GTK_STATE_NORMAL];
+	plugin->style[STYLE_FG] = style->text[GTK_STATE_NORMAL];
+	plugin->style[STYLE_TITLE_FG] = style->fg[GTK_STATE_ACTIVE];
+	plugin->style[STYLE_TITLE_BG] = style->bg[GTK_STATE_ACTIVE];
+	plugin->style[STYLE_TITLE_PRELIGHT_FG] = style->fg[GTK_STATE_PRELIGHT];
+	plugin->style[STYLE_TITLE_PRELIGHT_BG] = style->bg[GTK_STATE_PRELIGHT];
+	plugin->style[STYLE_ITEM_FG] = style->text[GTK_STATE_NORMAL];
+	plugin->style[STYLE_ITEM_BG] = style->base[GTK_STATE_NORMAL];
+	plugin->style[STYLE_ITEM_PRELIGHT_FG] = style->text[GTK_STATE_SELECTED];
+	plugin->style[STYLE_ITEM_PRELIGHT_BG] = style->base[GTK_STATE_SELECTED];
+	
+	/* Use text background (normally white) for canvas background */
+	style->bg[GTK_STATE_NORMAL] = plugin->style[STYLE_BG];
+
+	/* FIXME: */
+	/* cls_inherit_update (plugin); */
+}
diff --git a/plugins/class-inheritance/class-callbacks.h b/plugins/class-inheritance/class-callbacks.h
new file mode 100644
index 0000000..e982ff2
--- /dev/null
+++ b/plugins/class-inheritance/class-callbacks.h
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (C) Massimo Cora' 2005 <maxcvs email it>
+ *
+ *  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
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+ 
+#ifndef _CLASS_CALLBACKS_H
+#define _CLASS_CALLBACKS_H
+
+#include "plugin.h"
+#include "class-inherit.h"
+
+gint on_canvas_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data);
+gint on_canvas_event_proxy (GnomeCanvasItem *item, GdkEvent *event,
+                            GnomeCanvasItem *proxy_item);
+
+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
new file mode 100644
index 0000000..bba6fca
--- /dev/null
+++ b/plugins/class-inheritance/class-inherit.c
@@ -0,0 +1,1214 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ *  Copyright (C) Massimo Cora' 2005 <maxcvs email it>
+ *                2010 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
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+ 
+#include <glib.h>
+#include <graphviz/gvc.h>		/* graphviz */
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-symbol-manager.h>
+
+#include "plugin.h"
+#include "class-inherit.h"
+#include "class-callbacks.h"
+
+#define DEFAULT_GRAPH_NAME		"Anjuta Graph"
+#define CANVAS_MIN_SIZE			250
+
+/* some macros to access deep graphviz's node structures */
+#define NODE_LOWER_LEFT(node,main_index,rec_index) \
+	(((field_t*)ND_shape_info (node))->fld[main_index]->fld[rec_index]->b.LL)
+
+#define NODE_UPPER_RIGHT(node,main_index,rec_index) \
+	(((field_t*)ND_shape_info (node))->fld[main_index]->fld[rec_index]->b.UR)
+
+#define NODE_NUM_FIELDS(node) \
+	((field_t*)ND_shape_info (node))->n_flds
+
+#define NODE_NTH_FIELD(node,nth) \
+	((field_t*)ND_shape_info (node))->fld[nth]
+
+#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) \
+				INCH_TO_PIXELS_CONVERSION_FACTOR * inch_size
+
+#define NODE_EDGE_ARROW_LENGTH 10
+
+/* 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 {
+	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 (GnomeCanvasGroup *canvas_group,
+                          CanvasArrowDir direction,
+                          const GdkColor *fill_color,
+                          /* Bounding box */
+                          gint x1, gint y1, gint x2, gint y2)
+{
+	GnomeCanvasItem *item;
+	const gint offset = 4;
+
+	/* FIXME: Use direction to draw different arrows, now it only is down */
+	/* Arrows */
+	GnomeCanvasPoints *triangle = gnome_canvas_points_new (4);
+	triangle->coords[0] = x1 + offset;
+	triangle->coords[1] = y1 + offset;
+	triangle->coords[2] = x2 - offset;
+	triangle->coords[3] = y1 + offset;
+	triangle->coords[4] = x1 + (x2 - x1)/2;
+	triangle->coords[5] = y2 - offset;
+	triangle->coords[6] = x1 + offset;
+	triangle->coords[7] = y1 + offset;
+
+	item = gnome_canvas_item_new (canvas_group,
+	                              gnome_canvas_polygon_get_type (),
+	                              "points", triangle,
+	                              "fill_color_gdk",
+	                              fill_color,
+	                              NULL);
+	gnome_canvas_points_unref (triangle);
+	return item;
+}
+
+static GnomeCanvasItem*
+create_canvas_line_item (GnomeCanvasGroup *canvas_group, GdkColor *fill_color,
+                          gint x1, gint y1, gint x2, gint y2)
+{
+	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;
+}
+
+static void
+cls_node_item_free (ClsNodeItem *cls_item)
+{
+	g_free (cls_item->label);
+	g_free (cls_item->args);
+	g_free (cls_item->type_name);
+
+	if (cls_item->file)
+		g_object_unref (cls_item->file);
+	if (cls_item->icon)
+		gdk_pixbuf_unref (cls_item->icon);
+	
+	if (cls_item->tooltip_timeout)
+		g_source_remove (cls_item->tooltip_timeout);
+
+	if (cls_item->tooltip)
+		gtk_object_destroy (GTK_OBJECT (cls_item->tooltip));
+
+	g_free (cls_item);
+}
+
+static void
+cls_node_edge_free (ClsNodeEdge *cls_edge)
+{
+	/* 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);
+}
+
+static void
+cls_node_free (ClsNode *cls_node)
+{
+	g_free (cls_node->sym_name);
+	g_hash_table_destroy (cls_node->edges_to);
+	g_hash_table_destroy (cls_node->edges_from);
+	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);
+}
+
+static gboolean
+cls_node_add_edge (ClsNode *cls_node_from, ClsNode *cls_node_to)
+{
+	ClsNodeEdge *cls_edge;
+
+	g_return_val_if_fail (cls_node_from->graph != NULL, FALSE);
+
+	/* Check if the edge already exists */
+	cls_edge = g_hash_table_lookup (cls_node_from->edges_to, cls_node_to);
+	if (cls_edge)
+		return TRUE;
+	
+	cls_edge = g_new0 (ClsNodeEdge, 1);
+	cls_edge->cls_node_from = cls_node_from;
+	cls_edge->cls_node_to = cls_node_to;
+	
+	if ((cls_edge->agedge = agedge (cls_node_from->graph,
+	                                cls_node_from->agnode,
+	                                cls_node_to->agnode)) == NULL)
+	{
+		g_free (cls_edge);
+		return FALSE;
+	}
+
+	g_hash_table_insert (cls_node_from->edges_to, cls_node_to, cls_edge);
+	g_hash_table_insert (cls_node_to->edges_from, cls_node_from, cls_edge);
+	return TRUE;
+}
+
+static void
+on_cls_node_unlink_from_foreach (ClsNode *cls_node_from, ClsNodeEdge *cls_edge,
+                            ClsNode *cls_node_to)
+{
+	g_hash_table_remove (cls_node_from->edges_to, cls_node_to);
+}
+
+static void
+on_cls_node_unlink_to_foreach (ClsNode *cls_node_to, ClsNodeEdge *cls_edge,
+                            ClsNode *cls_node_from)
+{
+	/* This is will also free cls_edge */
+	g_hash_table_remove (cls_node_to->edges_from, cls_node_from);
+}
+
+static void
+cls_node_unlink (ClsNode *cls_node)
+{
+	g_hash_table_foreach (cls_node->edges_from,
+	                      (GHFunc) on_cls_node_unlink_from_foreach,
+	                      cls_node);
+	g_hash_table_foreach (cls_node->edges_to,
+	                      (GHFunc) on_cls_node_unlink_to_foreach,
+	                      cls_node);
+}
+
+/*----------------------------------------------------------------------------
+ * 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 ClsNode*
+cls_inherit_create_node (AnjutaClassInheritance *plugin,
+                         const IAnjutaSymbol *node_sym)
+{
+	ClsNode *cls_node;
+	Agsym_t *sym;
+	gint font_size;
+	const gchar *font_name;
+	
+#define FONT_SIZE_STR_LEN 16
+	gchar font_size_str[FONT_SIZE_STR_LEN];
+
+	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;
+	cls_node->edges_to =
+		g_hash_table_new_full (g_direct_hash, g_direct_equal,
+		                       NULL, (GDestroyNotify)cls_node_edge_free);
+	cls_node->edges_from = g_hash_table_new (g_direct_hash, g_direct_equal);
+	
+	/* let's add the node to the graph */
+	if ((cls_node->agnode = agnode (cls_node->graph,
+	                                cls_node->sym_name)) == NULL)
+	{
+		cls_node_free (cls_node);
+		return NULL;
+	}
+	
+	/* set the font */
+	if (!(sym = agfindattr(plugin->graph->proto->n, "fontname")))
+		sym = agnodeattr(plugin->graph, "fontname", "");
+	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;
+
+	/* 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 ())
+					/ INCH_TO_PIXELS_CONVERSION_FACTOR;
+	
+	snprintf (font_size_str, FONT_SIZE_STR_LEN, "%d", font_size);
+	agxset(cls_node->agnode, sym->index, font_size_str);
+
+	if (!(sym = agfindattr(plugin->graph->proto->n, "ratio")))
+		sym = agnodeattr(plugin->graph, "ratio", "");
+	agxset(cls_node->agnode, sym->index, "expand");	
+
+	/* 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;
+}
+
+gboolean
+cls_node_collapse (ClsNode *cls_node)
+{
+	Agsym_t *sym;
+	
+	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;
+}
+
+gboolean
+cls_node_expand (ClsNode *cls_node, ClsNodeExpansionType expansion_type)
+{
+	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;
+	IAnjutaIterable *iter;
+	
+	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;
+	
+	if (!(sym = agfindattr(cls_node->graph->proto->n, "shape")))
+		sym = agnodeattr(cls_node->graph, "shape", "");
+	agxset (cls_node->agnode, sym->index, "record");
+	
+	if (!(sym = agfindattr(cls_node->graph->proto->n, "label")))
+		sym = agnodeattr(cls_node->graph, "label", "");
+	
+	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_KIND |
+	                                           IANJUTA_SYMBOL_FIELD_TYPE |
+	                                           IANJUTA_SYMBOL_FIELD_TYPE_NAME |
+	                                           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) 
+	{
+		max_label_items = real_items_length;
+		cls_node->expansion_status = CLS_NODE_FULL_EXPANDED;
+	}
+	else
+	{
+		max_label_items = NODE_HALF_DISPLAY_ELEM_NUM;
+		cls_node->expansion_status = CLS_NODE_SEMI_EXPANDED;
+	}
+
+	g_hash_table_remove_all (cls_node->members);
+	if (iter && real_items_length > 0)
+	{
+		gint i = 0;
+
+		/* First member variables */
+		do
+		{
+			const gchar *name, *args, *type_name;
+			IAnjutaSymbol *symbol;
+			GdkPixbuf *icon;
+			
+			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 (!args) /* Member variables */
+			{
+				ClsNodeItem *cls_item = g_new0 (ClsNodeItem, 1);
+
+				type_name = ianjuta_symbol_get_extra_info_string (symbol, IANJUTA_SYMBOL_FIELD_TYPE_NAME, NULL);
+				cls_item->cls_node = cls_node;
+				cls_item->label = g_strconcat (name, " : ", type_name, NULL);
+				cls_item->order = var_order++;
+				if (icon)
+					gdk_pixbuf_ref (icon);
+				cls_item->icon = icon;
+				
+				g_hash_table_insert (cls_node->members,
+				                     g_strdup (cls_item->label),
+				                     cls_item);
+				g_string_append_printf (label, "|%s", cls_item->label);
+
+				/* Setup file and line */
+				cls_item->type_name = g_strdup (type_name);
+				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 /* Member methods */
+			{
+				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 */
+				{
+					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);
+					}
+				}
+				else /* We did not find a member entry, create a new one */
+				{
+					ClsNodeItem *cls_item = g_new0 (ClsNodeItem, 1);
+					type_name = ianjuta_symbol_get_returntype (symbol, NULL);
+
+					cls_item->cls_node = cls_node;
+					if (type_name)
+					{
+						if (strlen (args) > 2)
+							cls_item->label = g_strconcat (name, "(...)",
+							                               " : ", type_name,
+							                               NULL);
+						else
+							cls_item->label = g_strconcat (name, "()", " : ",
+							                               type_name, NULL);
+					}
+					else
+					{
+						if (strlen (args) > 2)
+							cls_item->label = g_strconcat (name, "(...)", NULL);
+						else
+							cls_item->label = g_strconcat (name, "()", NULL);
+					}
+					cls_item->args = g_strdup (args);
+					cls_item->type_name = g_strdup (type_name);
+					cls_item->order = method_order++;
+					if (icon)
+						gdk_pixbuf_ref (icon);
+					cls_item->icon = icon;
+					
+					g_string_append_printf (label, "|%s", cls_item->label);
+					g_hash_table_insert (cls_node->members, method_key,
+					                     cls_item);
+					
+					/* 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);
+				}
+			}
+			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);
+	}
+	
+	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, *text_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->plugin->style[STYLE_TITLE_BG],
+		                       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->plugin->style[STYLE_TITLE_FG],
+	                          cls_node->width - item_height,
+	                          0, cls_node->width, item_height);
+	/* Class title text */
+	text_item = 
+		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->plugin->style[STYLE_TITLE_FG],
+			                   "anchor", GTK_ANCHOR_W,
+			                   NULL);
+	g_object_set_data (G_OBJECT (canvas_item), "__text__", text_item);
+	g_signal_connect (GTK_OBJECT (text_item), "event",
+	                  G_CALLBACK (on_canvas_event_proxy),
+					  canvas_item);
+	
+	/* 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->plugin->style[STYLE_ITEM_BG],
+				                   NULL);
+		g_signal_connect (GTK_OBJECT (node_item->canvas_node_item),
+			              "event",
+						  G_CALLBACK (on_expanded_class_item_event),
+						  node_item);
+	
+		/* Member item text */
+		text_item =
+			gnome_canvas_item_new (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+			                       gnome_canvas_text_get_type (),
+			                       "text", node_item->label,
+			                       "justification", GTK_JUSTIFY_CENTER,
+			                       "anchor", GTK_ANCHOR_CENTER,
+			                       "x", (gdouble) 20.0,
+			                       "y", (gdouble) (j + 0.5) * item_height,
+			                       "fill_color_gdk",
+			                       &cls_node->plugin->style[STYLE_ITEM_FG],
+			                       "anchor", GTK_ANCHOR_W,
+			                       NULL);
+		g_object_set_data (G_OBJECT (node_item->canvas_node_item),
+		                   "__text__", text_item);
+		g_signal_connect (GTK_OBJECT (text_item), "event",
+		                  G_CALLBACK (on_canvas_event_proxy),
+		                  node_item->canvas_node_item);
+
+		/* 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->plugin->style[STYLE_FG],
+				                         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->plugin->style[STYLE_TITLE_BG],
+				                   NULL);
+
+		g_signal_connect (GTK_OBJECT (canvas_item), "event",
+			              G_CALLBACK (on_expanded_class_more_event),
+						  cls_node);
+	
+		/* More expand item text */
+		text_item = 
+			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->plugin->style[STYLE_TITLE_FG],
+					               "anchor", GTK_ANCHOR_W,
+					               NULL);
+		g_object_set_data (G_OBJECT (canvas_item), "__text__", text_item);
+		g_signal_connect (GTK_OBJECT (text_item), "event",
+			              G_CALLBACK (on_canvas_event_proxy),
+			              canvas_item);
+
+		create_canvas_line_item (GNOME_CANVAS_GROUP (cls_node->canvas_group),
+		                         &cls_node->plugin->style[STYLE_FG],
+		                         0, j * item_height,
+		                         cls_node->width, j * item_height);
+	}
+	
+	/* make the outline bounds */
+	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,
+  						   "outline_color_gdk",
+							&cls_node->plugin->style[STYLE_FG],
+							"width_units", 1.0,
+							NULL);
+}
+
+static void
+cls_node_draw_collapsed (ClsNode *cls_node) 
+{
+	GnomeCanvasItem *item, *text_item;
+	gdouble text_width_value;
+
+	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;
+	
+	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->plugin->style[STYLE_BG],
+		                       "outline_color_gdk",
+		                       &cls_node->plugin->style[STYLE_FG],
+		                       "width_units", 1.0,
+		                       NULL);
+	g_signal_connect (GTK_OBJECT (item), "event",
+					  G_CALLBACK (on_collapsed_class_event),
+					  cls_node);
+
+	/* --- text --- */
+	text_item =
+		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) 0.0,
+		                       "y", (gdouble) cls_node->height/2,
+		                       "fill_color_gdk",
+		                       &cls_node->plugin->style[STYLE_FG],
+		                       "anchor", GTK_ANCHOR_W,        
+		                       NULL );
+	g_object_set_data (G_OBJECT (item), "__text__", text_item);
+	g_signal_connect (GTK_OBJECT (text_item), "event",
+	                  G_CALLBACK (on_canvas_event_proxy), item);
+	
+	/* center the text in the node... */
+	g_object_get (text_item, "text_width", &text_width_value, NULL);
+						
+	gnome_canvas_item_set (text_item,
+	                       "x", (gdouble)((cls_node->width/2 - text_width_value/2)),
+	                       NULL);
+}
+
+/* This function determins NODE_EDGE_ARROW_LENGTH long arrow destination
+ * as a projection of (x1, y1) - (x2, y2) line.
+ */
+static gboolean
+create_canvas_edge_arrow_ending (double x1, double y1, double x2, double y2,
+                                 double *end_x, double *end_y)
+{
+	double x = x2 - x1;
+	double y = y2 - y1;
+	double h1 = sqrt(y * y + x * x);
+
+	if (h1 == 0) /* Overlapping points, no direction! */
+		return FALSE;
+	
+	*end_x = x2 + NODE_EDGE_ARROW_LENGTH * x / h1;
+	*end_y = y2 + NODE_EDGE_ARROW_LENGTH * y / h1;
+	return TRUE;
+}
+
+static void
+cls_node_draw_edge (ClsNode *cls_node_to, ClsNodeEdge *cls_edge, ClsNode *cls_node_from)
+{
+	Agedge_t *edge;
+	GnomeCanvasPathDef *path_def;
+	GnomeCanvasPoints *points;
+	gint i, num_points;
+	
+	path_def = gnome_canvas_path_def_new();
+	edge = cls_edge->agedge;
+	num_points = ED_spl(edge)->list->size;
+	
+	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));
+	}
+	
+	/* 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_from->canvas)), 
+				                   gnome_canvas_bpath_get_type(),
+				                   "bpath", path_def,
+				                   "outline_color_gdk",
+				                   &cls_node_from->plugin->style[STYLE_FG],
+				                   "width_pixels", 2,
+				                   NULL);
+	}
+	gnome_canvas_path_def_unref (path_def);
+
+    /* Draw arrow */
+	
+	/* let's draw a canvas_line with an arrow-end */
+	points = gnome_canvas_points_new (2);
+
+	/* Arrow end position */
+	/* Sometimes, last 2 points overlap, resulting in failure to determine
+	 * next point, track back until there is a usable pair of points.
+	 */
+	do
+	{
+		num_points--;
+		
+		/* starting point */
+		points->coords[0] = ((ED_spl(edge))->list->list[num_points]).x;
+		points->coords[1] =
+			GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points]).y);
+	
+	}
+	while (num_points > 0 &&
+	       !create_canvas_edge_arrow_ending (((ED_spl(edge))->list->list[num_points - 1]).x,
+			                                 GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points - 1]).y),
+			                                 ((ED_spl(edge))->list->list[num_points]).x,
+			                                 GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points]).y),
+			                                 &points->coords[2], &points->coords[3]));
+
+	if (cls_edge->canvas_arrow)
+	{
+		gnome_canvas_item_set (cls_edge->canvas_arrow,
+		                       "points", points,
+					           NULL);
+	}
+	else
+	{
+		cls_edge->canvas_arrow =
+			gnome_canvas_item_new (gnome_canvas_root
+				                   (GNOME_CANVAS (cls_node_from->canvas)),
+				                   gnome_canvas_line_get_type(),
+				                   "points", points,
+				                   "fill_color_gdk",
+				                   &cls_node_from->plugin->style[STYLE_FG],
+				                   "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;
+#endif
+	
+	/* get some infos from the node */
+#ifdef ND_coord_i
+	node_pos = ND_coord_i (cls_node->agnode);
+#else
+	node_posf = ND_coord (cls_node->agnode);
+	PF2P (node_posf, node_pos);
+#endif
+
+	/* 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_hash_table_foreach (cls_node->edges_to, (GHFunc) cls_node_draw_edge, cls_node);
+}
+
+/*----------------------------------------------------------------------------
+ * draw the graph on the canvas. So nodes, edges, arrows, texts..
+ */
+void
+cls_inherit_draw (AnjutaClassInheritance *plugin)
+{
+	ClsBox bounds;
+
+	gvLayout (plugin->gvc, plugin->graph, "dot");
+
+	/* 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 */
+	gnome_canvas_set_scroll_region (GNOME_CANVAS (plugin->canvas),
+	                                bounds.x1 - 10, bounds.y1 - 10,
+	                                bounds.x2 + 10, bounds.y2 + 10);
+	gvFreeLayout(plugin->gvc, plugin->graph);
+}
+
+static void
+on_cls_node_mark_for_deletion (gpointer key, ClsNode *cls_node, gpointer data)
+{
+	cls_node->marked_for_deletion = TRUE;
+}
+
+static gboolean
+on_cls_node_delete_marked (gpointer key, ClsNode *cls_node, gpointer data)
+{
+	if (!cls_node->marked_for_deletion) return FALSE;
+	cls_node_unlink (cls_node);
+	return TRUE;
+}
+
+/*----------------------------------------------------------------------------
+ * update the internal graphviz graph-structure, then redraw the graph on the 
+ * canvas
+ */
+void
+cls_inherit_update (AnjutaClassInheritance *plugin)
+{
+	IAnjutaSymbolManager *sm;
+	IAnjutaIterable *iter;
+	IAnjutaSymbol *symbol;
+	ClsNode *cls_node;
+
+	g_return_if_fail (plugin != NULL);
+
+	/* Mark all nodes for deletion. Selectively, they will be unmarked below */
+	g_hash_table_foreach (plugin->nodes,
+	                      (GHFunc) on_cls_node_mark_for_deletion,
+	                      NULL);
+
+	if (plugin->top_dir == NULL)
+		goto cleanup;
+	
+	sm = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
+									 IAnjutaSymbolManager, NULL);
+	if (!sm)
+		goto cleanup;
+	
+	/* Get all classes */	
+	iter = ianjuta_symbol_manager_search (sm, IANJUTA_SYMBOL_TYPE_CLASS, 
+										  TRUE,
+										  IANJUTA_SYMBOL_FIELD_SIMPLE,
+										  NULL, TRUE,
+	                                      IANJUTA_SYMBOL_MANAGER_SEARCH_FS_PUBLIC, 
+	    								  FALSE, -1, -1, NULL);
+	if (!iter)
+	{
+		DEBUG_PRINT ("%s", "cls_inherit_update_graph (): search returned no items.");
+		goto cleanup;
+	}
+	
+	ianjuta_iterable_first (iter, NULL);
+	if (ianjuta_iterable_get_length (iter, NULL) <= 0)
+	{
+		g_object_unref (iter);
+		goto cleanup;
+	}
+	do 
+	{
+		gint klass_id;
+		IAnjutaIterable *parents;
+     
+		/* a symbol representing a class */
+		symbol = IANJUTA_SYMBOL (iter);
+
+		/* get parents of the current class */
+		parents = ianjuta_symbol_manager_get_class_parents (sm, symbol, 
+															IANJUTA_SYMBOL_FIELD_SIMPLE, 
+															NULL);
+
+		/* if no parents are found then continue */
+		if (parents == NULL || ianjuta_iterable_get_length (parents, NULL) <= 0)
+		{
+			/*DEBUG_PRINT ("ClassInheritance: no parents found for class %s",
+						 ianjuta_symbol_get_name (symbol, NULL));*/
+			continue;
+		}
+
+		if ((klass_id = ianjuta_symbol_get_id (symbol, NULL)) <= 0)
+		{
+			/*DEBUG_PRINT ("%s", "ClassInheritance: klass_id cannot be <= 0");*/
+			continue;
+		}
+		
+		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);
+		}
+		cls_node->marked_for_deletion = FALSE;
+
+		/* 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);
+			
+			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);
+			}
+			parent_node->marked_for_deletion = FALSE;
+			cls_node_add_edge (parent_node, cls_node);
+		} while (ianjuta_iterable_next (parents, NULL) == TRUE);
+		g_object_unref (parents);
+
+	} while (ianjuta_iterable_next (iter, NULL) == TRUE);
+
+	g_object_unref (iter);
+
+cleanup:
+	
+	/* Delete all marked nodes that did not get unmarked above. */
+	g_hash_table_foreach_remove (plugin->nodes,
+	                             (GHRFunc) on_cls_node_delete_marked,
+	                             NULL);
+
+	cls_inherit_draw (plugin);
+}
+
+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;
+}
+
+/*----------------------------------------------------------------------------
+ * 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();
+	
+	if (!(sym = agfindattr(plugin->graph->proto->n, "dpi")))
+		sym = agraphattr(plugin->graph, "dpi", dpi_text);
+	agxset(plugin->graph, sym->index, dpi_text);
+}
+
+void
+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);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (s_window),
+	                                GTK_POLICY_AUTOMATIC, 
+	                                GTK_POLICY_AUTOMATIC);
+	plugin->canvas = gnome_canvas_new ();
+	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);
+	gtk_container_add (GTK_CONTAINER (s_window), plugin->canvas);
+
+	/* Initialize styles */
+	gtk_widget_ensure_style (plugin->canvas);
+	on_style_set (plugin->canvas, NULL, 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-- */
+	/* vbox */
+	gtk_box_pack_start (GTK_BOX (plugin->widget), s_window, TRUE, TRUE, TRUE);
+
+	gtk_widget_show_all (plugin->widget);
+
+	/* create new GList */
+	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 ();
+
+	GtkWidget *menu_item = gtk_menu_item_new_with_label (_("Update"));
+	g_signal_connect (menu_item, "activate",
+	                  (GCallback)on_update_menu_item_selected, plugin);
+
+	/* set the user data on update selection */
+	gtk_menu_shell_append (GTK_MENU_SHELL (plugin->menu), menu_item);
+	gtk_widget_show_all (plugin->menu);
+
+	plugin->update = menu_item;
+
+	g_object_ref (plugin->menu);
+	g_object_ref (plugin->update);
+}
diff --git a/plugins/class-inheritance/class-inherit.h b/plugins/class-inheritance/class-inherit.h
new file mode 100644
index 0000000..0d50e64
--- /dev/null
+++ b/plugins/class-inheritance/class-inherit.h
@@ -0,0 +1,119 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ *  Copyright (C) Massimo Cora' 2005 <maxcvs email it>,
+ *                2010 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
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+ 
+#ifndef _CLASS_INHERIT_H
+#define _CLASS_INHERIT_H
+
+#include <libanjuta/interfaces/ianjuta-symbol-manager.h>
+#include <libgnomecanvas/libgnomecanvas.h>
+
+#include "plugin.h"
+
+G_BEGIN_DECLS
+
+#define NODE_HALF_DISPLAY_ELEM_NUM			30
+#define NODE_SHOW_ALL_MEMBERS_STR			N_("Show all members...")
+
+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;
+	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;
+	
+	/* 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 */
+	GHashTable *edges_to;
+
+	/* All inbound edges to this node */
+	GHashTable *edges_from;
+
+	/* Used during update scan */
+	gboolean marked_for_deletion;
+} 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 *label;
+	gchar *args;
+	gchar *type_name;
+	GFile *file;
+	gint line;
+	GdkPixbuf *icon;
+
+	/* The order in which this item is shown in the list */
+	gint order;
+
+	/* Tooltip shown on item hover */
+	GnomeCanvasItem *tooltip;
+
+	/* Tooltip timout id */
+	guint tooltip_timeout;
+	
+} 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_draw (AnjutaClassInheritance *plugin);
+void cls_inherit_update (AnjutaClassInheritance *plugin);
+void cls_inherit_clear (AnjutaClassInheritance *plugin);
+void cls_inherit_free (AnjutaClassInheritance *plugin);
+
+G_END_DECLS
+ 
+#endif /* _CLASS_INHERIT_H */
diff --git a/plugins/class-inheritance/plugin.c b/plugins/class-inheritance/plugin.c
new file mode 100644
index 0000000..e5771ff
--- /dev/null
+++ b/plugins/class-inheritance/plugin.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * plugin.c
+ * Copyright (C) Massimo Cora' 2005 <maxcvs email it>
+ * 
+ * plugin.c is free software.
+ * 
+ * You may 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, or (at your option) any later version.
+ * 
+ * plugin.c is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with plugin.c.  See the file "COPYING".  If not,
+ * write to:  The Free Software Foundation, Inc.,
+ *            51 Franklin Street, Fifth Floor,
+ *            Boston,  MA  02110-1301, USA.
+ */
+
+#include <config.h>
+#include <libanjuta/anjuta-shell.h>
+#include <glib/gi18n.h>
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-project-manager.h>
+#include <libanjuta/anjuta-debug.h>
+#include "plugin.h"
+#include "class-inherit.h"
+
+#define ICON_FILE "anjuta-class-inheritance-plugin-48.png"
+
+static gpointer parent_class;
+
+static void
+project_root_added (AnjutaPlugin *plugin, const gchar *name,
+					const GValue *value, gpointer user_data)
+{
+	AnjutaClassInheritance *ci_plugin;
+	const gchar *root_uri;
+
+	ci_plugin = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
+	root_uri = g_value_get_string (value);
+	
+	if (root_uri)
+	{
+		gchar *root_dir = anjuta_util_get_local_path_from_uri (root_uri);
+		if (root_dir)
+		{	
+			ci_plugin->top_dir = g_strdup(root_dir);
+		}
+		else
+			ci_plugin->top_dir = NULL;
+		g_free (root_dir);
+	}
+	else
+		ci_plugin->top_dir = NULL;
+	
+	/* let's update the graph */
+	cls_inherit_update (ci_plugin);
+}
+
+static void
+project_root_removed (AnjutaPlugin *plugin, const gchar *name,
+					  gpointer user_data)
+{
+	AnjutaClassInheritance *ci_plugin;
+	ci_plugin = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
+	
+	/* clean up the canvas */
+	cls_inherit_clear (ci_plugin);
+	
+	if (ci_plugin->top_dir)
+		g_free(ci_plugin->top_dir);
+	ci_plugin->top_dir = NULL;
+}
+
+static void
+register_stock_icons (AnjutaPlugin *plugin)
+{
+	static gboolean registered = FALSE;
+
+	if (registered)
+		return;
+	registered = TRUE;
+
+	BEGIN_REGISTER_ICON (plugin);
+	REGISTER_ICON (PACKAGE_PIXMAPS_DIR"/"ICON_FILE,
+				   "class-inheritance-plugin-icon");
+	END_REGISTER_ICON;
+}
+
+static gboolean
+activate_plugin (AnjutaPlugin *plugin)
+{
+	AnjutaClassInheritance *cls_inherit;
+	static gboolean initialized = FALSE;
+	
+	DEBUG_PRINT ("%s", "AnjutaClassInheritance: Activating plugin ...");
+	
+	register_stock_icons (plugin);
+	
+	cls_inherit = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
+	
+	cls_inherit_init (cls_inherit);
+	
+	anjuta_shell_add_widget (plugin->shell, cls_inherit->widget,
+							 "AnjutaClassInheritance", _("Inheritance Graph"),
+							 "class-inheritance-plugin-icon",
+							 ANJUTA_SHELL_PLACEMENT_CENTER, NULL);
+	cls_inherit->top_dir = NULL;
+	
+	/* set up project directory watch */
+	cls_inherit->root_watch_id = anjuta_plugin_add_watch (plugin,
+									IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
+									project_root_added,
+									project_root_removed, NULL);
+
+	initialized	= TRUE;	
+	return TRUE;
+}
+
+static gboolean
+deactivate_plugin (AnjutaPlugin *plugin)
+{
+	DEBUG_PRINT ("%s", "AnjutaClassInheritance: Dectivating plugin ...");
+	AnjutaClassInheritance* class_inheritance;
+	class_inheritance = ANJUTA_PLUGIN_CLASS_INHERITANCE (plugin);
+
+	/* clean up the canvas [e.g. destroys it's elements */
+	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. */
+	/* In most cases, only toplevel widgets (windows) require explicit 
+	 * destruction, because when you destroy a toplevel its children will 
+	 * be destroyed as well. */
+	anjuta_shell_remove_widget (plugin->shell,
+								class_inheritance->widget,
+								NULL);
+
+	/* Remove watches */
+	anjuta_plugin_remove_watch (plugin,
+								class_inheritance->root_watch_id,
+								TRUE);
+	return TRUE;
+}
+
+static void
+class_inheritance_finalize (GObject *obj)
+{
+	AnjutaClassInheritance *ci_plugin;
+	ci_plugin = ANJUTA_PLUGIN_CLASS_INHERITANCE (obj);
+	
+	if (ci_plugin->top_dir)
+		g_free (ci_plugin->top_dir);
+	
+	/* Finalization codes here */
+	G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+class_inheritance_dispose (GObject *obj)
+{
+	/* Disposition codes */
+	G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+class_inheritance_instance_init (GObject *obj)
+{
+	AnjutaClassInheritance *plugin = ANJUTA_PLUGIN_CLASS_INHERITANCE (obj);
+
+	plugin->uiid = 0;
+
+	plugin->widget = NULL;
+	plugin->graph = NULL;
+	plugin->gvc = NULL;
+}
+
+static void
+class_inheritance_class_init (GObjectClass *klass) 
+{
+	AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	plugin_class->activate = activate_plugin;
+	plugin_class->deactivate = deactivate_plugin;
+	klass->finalize = class_inheritance_finalize;
+	klass->dispose = class_inheritance_dispose;
+}
+
+ANJUTA_PLUGIN_BOILERPLATE (AnjutaClassInheritance, class_inheritance);
+ANJUTA_SIMPLE_PLUGIN (AnjutaClassInheritance, class_inheritance);
diff --git a/plugins/class-inheritance/plugin.h b/plugins/class-inheritance/plugin.h
new file mode 100644
index 0000000..f1b72a4
--- /dev/null
+++ b/plugins/class-inheritance/plugin.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * plugin.h
+ * Copyright (C) Massimo Cora' 2005 <maxcvs email it>
+ * 
+ * plugin.h is free software.
+ * 
+ * You may 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, or (at your option) any later version.
+ * 
+ * plugin.h is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with plugin.h.  See the file "COPYING".  If not,
+ * write to:  The Free Software Foundation, Inc.,
+ *            51 Franklin Street, Fifth Floor,
+ *            Boston,  MA  02110-1301, USA.
+ */
+
+#ifndef _CLASS_INHERITANCE_H_
+#define _CLASS_INHERITANCE_H_
+
+#include <libanjuta/anjuta-plugin.h>
+
+#include <gvc.h>		/* graphviz */
+
+G_BEGIN_DECLS
+
+extern GType class_inheritance_get_type (GTypeModule *module);
+#define ANJUTA_TYPE_PLUGIN_CLASS_INHERITANCE         (class_inheritance_get_type (NULL))
+#define ANJUTA_PLUGIN_CLASS_INHERITANCE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), ANJUTA_TYPE_PLUGIN_CLASS_INHERITANCE, AnjutaClassInheritance))
+#define ANJUTA_PLUGIN_CLASS_INHERITANCE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), ANJUTA_TYPE_PLUGIN_CLASS_INHERITANCE, AnjutaClassInheritanceClass))
+#define ANJUTA_IS_PLUGIN_CLASS_INHERITANCE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANJUTA_TYPE_PLUGIN_CLASS_INHERITANCE))
+#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;
+
+enum {
+	STYLE_BG,
+	STYLE_FG,
+	STYLE_TITLE_BG,
+	STYLE_TITLE_FG,
+	STYLE_TITLE_PRELIGHT_FG,
+	STYLE_TITLE_PRELIGHT_BG,
+	STYLE_ITEM_BG,
+	STYLE_ITEM_FG,
+	STYLE_ITEM_PRELIGHT_FG,
+	STYLE_ITEM_PRELIGHT_BG,
+	N_STYLES
+};
+
+struct _AnjutaClassInheritance {
+	AnjutaPlugin parent;
+	
+	GtkWidget *widget; /* a vbox */
+	GtkWidget *update_button;	
+	GtkWidget *menu;
+	GtkWidget *update;
+	
+	GtkWidget *canvas;
+	GHashTable *nodes;
+
+	/* graphviz stuff */	
+	GVC_t *gvc;
+	Agraph_t *graph;
+	
+	gchar *top_dir;
+	guint root_watch_id;
+	gint uiid;
+	
+	/* Style colors */
+	GdkColor style[N_STYLES];
+};
+
+struct _AnjutaClassInheritanceClass {
+	AnjutaPluginClass parent_class;
+};
+
+G_END_DECLS
+
+#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]