[anjuta] class-inheritance: Copied class-inheritance plugin from anjuta-extras
- From: Naba Kumar <naba src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta] class-inheritance: Copied class-inheritance plugin from anjuta-extras
- Date: Sat, 8 May 2010 11:37:53 +0000 (UTC)
commit 6a969be6ee75161b822049fa70b70018c5bf457b
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]