changeset 16125:5f204f55af09

Add a utility function to create widgets from an XML description.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Sun, 15 Apr 2007 05:49:27 +0000
parents ab3f93232a2d
children d07f5128dd6b
files finch/libgnt/Makefile.am finch/libgnt/configure.ac finch/libgnt/gntutils.c finch/libgnt/gntutils.h finch/libgnt/test/Makefile finch/libgnt/test/parse.c
diffstat 6 files changed, 216 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/finch/libgnt/Makefile.am	Sun Apr 15 05:42:14 2007 +0000
+++ b/finch/libgnt/Makefile.am	Sun Apr 15 05:49:27 2007 +0000
@@ -77,9 +77,11 @@
 libgnt_la_LDFLAGS = -export-dynamic
 libgnt_la_LIBADD = \
 	$(GLIB_LIBS) \
-	$(GNT_LIBS)
+	$(GNT_LIBS) \
+	$(LIBXML_LIBS)
 
 AM_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GNT_CFLAGS) \
-	$(DEBUG_CFLAGS)
+	$(DEBUG_CFLAGS) \
+	$(LIBXML_CFLAGS)
--- a/finch/libgnt/configure.ac	Sun Apr 15 05:42:14 2007 +0000
+++ b/finch/libgnt/configure.ac	Sun Apr 15 05:49:27 2007 +0000
@@ -203,6 +203,9 @@
 
 GNT_CFLAGS=
 GNT_LIBS=
+AC_ARG_WITH(ncurses-headers, [AC_HELP_STRING([--with-ncurses-headers=DIR],
+		[compile finch against the ncurses includes in DIR])],
+		[ac_ncurses_includes="$withval"], [ac_ncurses_includes=""])
 AC_CHECK_LIB(ncursesw, initscr, [GNT_LIBS="-lncursesw"], [enable_gnt=no])
 AC_CHECK_LIB(panelw, update_panels, [GNT_LIBS="$GNT_LIBS -lpanelw"], [enable_gnt=no])
 
@@ -214,8 +217,9 @@
 else
 	dnl # Some distros put the headers in ncursesw/, some don't
 	found_ncurses_h=no
-	for f in /usr/include/ncursesw/ncurses.h /usr/include/ncurses.h
+	for location in $ac_ncurses_includes /usr/include/ncursesw /usr/include
 	do
+		f="$location/ncurses.h"
 		AC_CHECK_HEADER($f,[
 			AC_MSG_CHECKING([if $f supports wide characters])
 			AC_TRY_COMPILE([
@@ -226,7 +230,7 @@
 				# error get_wch not found!
 				#endif
 			], [
-				dir=`dirname $f`
+				dir=$location
 				if test x"$dir" != x"." ; then
 					GNT_CFLAGS="-I$dir/"
 				else
@@ -241,13 +245,29 @@
 			])
 		])
 	done
+	if test x"$found_ncurses_h" != "xyes"; then
+		enable_gnt="no"
+	fi
 fi
 AC_SUBST(GNT_CFLAGS)
 AC_SUBST(GNT_LIBS)
 
 if test "x$enable_gnt" = "xno"; then
 	AC_MSG_ERROR([
-*** You need ncursesw or ncurses.])
+*** You need ncursesw or ncurses and its header files.])
+fi
+
+dnl Check for libxml
+have_libxml=yes
+PKG_CHECK_MODULES(LIBXML, [libxml-2.0], , [
+		AC_MSG_RESULT(no)
+		have_libxml=no
+	])
+AC_SUBST(LIBXML_CFLAGS)
+AC_SUBST(LIBXML_LIBS)
+
+if test "x$have_libxml" = "xno"; then
+	AC_DEFINE(NO_LIBXML, 1, [Do not have libxml2.])
 fi
 
 AC_OUTPUT([Makefile
--- a/finch/libgnt/gntutils.c	Sun Apr 15 05:42:14 2007 +0000
+++ b/finch/libgnt/gntutils.c	Sun Apr 15 05:49:27 2007 +0000
@@ -1,9 +1,25 @@
-#include "gntutils.h"
+#include "gntbutton.h"
+#include "gntcheckbox.h"
+#include "gntcombobox.h"
+#include "gntentry.h"
+#include "gntlabel.h"
+#include "gntline.h"
+#include "gnttextview.h"
 #include "gnttree.h"
+#include "gntutils.h"
+#include "gntwindow.h"
 
+#include "config.h"
+
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 
+#ifndef NO_LIBXML
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#endif
+
 #include "config.h"
 
 void gnt_util_get_text_bound(const char *text, int *width, int *height)
@@ -184,9 +200,156 @@
 	gnt_tree_set_compare_func(bv.tree, (GCompareFunc)g_utf8_collate);
 	g_hash_table_foreach(klass->actions, add_action, &bv);
 	g_hash_table_foreach(klass->bindings, add_binding, &bv);
-	gnt_tree_adjust_columns(bv.tree);
+	if (GNT_TREE(tree)->list == NULL) {
+		gnt_widget_destroy(tree);
+		tree = NULL;
+	} else
+		gnt_tree_adjust_columns(bv.tree);
 	g_hash_table_destroy(hash);
 
 	return tree;
 }
 
+#ifndef NO_LIBXML
+static GntWidget *
+gnt_widget_from_xmlnode(xmlNode *node, GntWidget **data[])
+{
+	GntWidget *widget = NULL;
+	char *name;
+	char *id, *prop, *content;
+	int val;
+
+	if (node == NULL || node->name == NULL || node->type != XML_ELEMENT_NODE)
+		return NULL;
+
+	name = (char*)node->name;
+	content = (char*)xmlNodeGetContent(node);
+	if (strcmp(name + 1, "window") == 0 || strcmp(name + 1, "box") == 0) {
+		xmlNode *ch;
+		char *title;
+		gboolean vert = (*name == 'v');
+
+		if (name[1] == 'w')
+			widget = gnt_window_box_new(FALSE, vert);
+		else
+			widget = gnt_box_new(FALSE, vert);
+
+		title = (char*)xmlGetProp(node, (xmlChar*)"title");
+		if (title) {
+			gnt_box_set_title(GNT_BOX(widget), title);
+			xmlFree(title);
+		}
+
+		prop = (char*)xmlGetProp(node, (xmlChar*)"fill");
+		if (prop) {
+			if (sscanf(prop, "%d", &val) == 1)
+				gnt_box_set_fill(GNT_BOX(widget), !!val);
+			xmlFree(prop);
+		}
+
+		prop = (char*)xmlGetProp(node, (xmlChar*)"align");
+		if (prop) {
+			if (sscanf(prop, "%d", &val) == 1)
+				gnt_box_set_alignment(GNT_BOX(widget), val);
+			xmlFree(prop);
+		}
+
+		prop = (char*)xmlGetProp(node, (xmlChar*)"pad");
+		if (prop) {
+			if (sscanf(prop, "%d", &val) == 1)
+				gnt_box_set_pad(GNT_BOX(widget), val);
+			xmlFree(prop);
+		}
+
+		for (ch = node->children; ch; ch=ch->next)
+			gnt_box_add_widget(GNT_BOX(widget), gnt_widget_from_xmlnode(ch, data));
+	} else if (strcmp(name, "button") == 0) {
+		widget = gnt_button_new(content);
+	} else if (strcmp(name, "label") == 0) {
+		widget = gnt_label_new(content);
+	} else if (strcmp(name, "entry") == 0) {
+		widget = gnt_entry_new(content);
+	} else if (strcmp(name, "combobox") == 0) {
+		widget = gnt_combo_box_new();
+	} else if (strcmp(name, "checkbox") == 0) {
+		widget = gnt_check_box_new(content);
+	} else if (strcmp(name, "tree") == 0) {
+		widget = gnt_tree_new();
+	} else if (strcmp(name, "textview") == 0) {
+		widget = gnt_text_view_new();
+	} else if (strcmp(name + 1, "line") == 0) {
+		widget = gnt_line_new(*name == 'v');
+	}
+
+	xmlFree(content);
+
+	if (widget == NULL) {
+		g_printerr("Invalid widget name %s\n", name);
+		return NULL;
+	}
+
+	id = (char*)xmlGetProp(node, (xmlChar*)"id");
+	if (id) {
+		int i;
+		sscanf(id, "%d", &i);
+		*data[i] = widget;
+		xmlFree(id);
+	}
+
+	prop = (char*)xmlGetProp(node, (xmlChar*)"border");
+	if (prop) {
+		int val;
+		if (sscanf(prop, "%d", &val) == 1) {
+			if (val)
+				GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
+			else
+				GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
+		}
+		xmlFree(prop);
+	}
+
+	prop = (char*)xmlGetProp(node, (xmlChar*)"shadow");
+	if (prop) {
+		int val;
+		if (sscanf(prop, "%d", &val) == 1) {
+			if (val)
+				GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
+			else
+				GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
+		}
+		xmlFree(prop);
+	}
+
+	return widget;
+}
+#endif
+
+void gnt_util_parse_widgets(const char *string, int num, ...)
+{
+#ifndef NO_LIBXML
+	xmlParserCtxtPtr ctxt;
+	xmlDocPtr doc;
+	xmlNodePtr node;
+	va_list list;
+	GntWidget ***data;
+	int id;
+
+	ctxt = xmlNewParserCtxt();
+	doc = xmlCtxtReadDoc(ctxt, (xmlChar*)string, NULL, NULL, XML_PARSE_NOBLANKS);
+
+	data = g_new0(GntWidget **, num);
+
+	va_start(list, num);
+	for (id = 0; id < num; id++)
+		data[id] = va_arg(list, gpointer);
+
+	node = xmlDocGetRootElement(doc);
+	gnt_widget_from_xmlnode(node, data);
+
+	xmlFreeDoc(doc);
+	xmlCleanupParser();
+	va_end(list);
+	g_free(data);
+#endif
+}
+
--- a/finch/libgnt/gntutils.h	Sun Apr 15 05:42:14 2007 +0000
+++ b/finch/libgnt/gntutils.h	Sun Apr 15 05:49:27 2007 +0000
@@ -39,3 +39,8 @@
  */
 GntWidget *gnt_widget_bindings_view(GntWidget *widget);
 
+/**
+ * Parse widgets from 'string'.
+ */
+void gnt_util_parse_widgets(const char *string, int num, ...);
+
--- a/finch/libgnt/test/Makefile	Sun Apr 15 05:42:14 2007 +0000
+++ b/finch/libgnt/test/Makefile	Sun Apr 15 05:49:27 2007 +0000
@@ -2,7 +2,7 @@
 CFLAGS=`pkg-config --cflags gobject-2.0 gmodule-2.0` -g -I../ -DSTANDALONE
 LDFLAGS=`pkg-config --libs gobject-2.0 gmodule-2.0 gnt` -pg
 
-EXAMPLES=combo focus tv multiwin keys menu
+EXAMPLES=combo focus tv multiwin keys menu parse
 
 all:
 	make examples
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/libgnt/test/parse.c	Sun Apr 15 05:49:27 2007 +0000
@@ -0,0 +1,18 @@
+#include "gntutils.h"
+
+int main()
+{
+	GntWidget *win, *button;
+
+	gnt_init();
+
+	gnt_util_parse_widgets("<vwindow id='0' fill='0' align='2'><label>This is a test.</label><button id='1'>OK</button></vwindow>", 2, &win, &button);
+	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), win);
+	gnt_widget_show(win);
+
+	gnt_main();
+
+	gnt_quit();
+	return 0;
+}
+