[Gtk-sharp-list] DOM-like interface for Gtk#

Rafael Jannone jannone@inf.ufrgs.br
Thu, 29 Apr 2004 00:51:16 -0300


--=-+8gUGUMJescVAvwCKTjd
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi!

Are there any plans to bind a DOM-like interface for Gtk# widgets?

I hacked an ugly piece of code just to experiment with the idea (in attach).

It seems at first glance, that most of the work could be done by the
same translators currently generating the Gtk# bindings. Other way to
generate the required code could be done by using reflection over the
Gtk# classes.

Anyway, try this:

$ mcs -r:gtk-sharp.dll XUIDocTest.cs
$ mono XUIDocTest.exe form.xml

For those who didn't get it:

The loader will read the entire xml, but for each tag it will search for
any known corresponding widget (example: "window" -> Gtk.Window).
Instead of creating the widget directly, it will create a specialized
XmlElement which contains the widget, providing an interface for
attribute manipulation, child appending, and so on.  In other words, a
one-night hack briefly inspired by the DOM API spec.

So you can do things like this:

XmlElement label = (XmlElement)doc.SelectSingleNode("//label");
label.SetAttribute("text", "hardcoded text");

...and it will reflect directly on the widget: instant visual feedback,
much like you would do with Javascript + HTML.

Back to my question: are there any plans or interest to do something
like that? (specially with Javascript and Python running over Mono in the near future)

Cheers,
Rafael Jannone

--=-+8gUGUMJescVAvwCKTjd
Content-Disposition: attachment; filename=XUIDocTest.cs
Content-Type: text/x-csharp; name=XUIDocTest.cs; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit

using System;
using System.Xml;

using Gtk;

public class XUIDocTest {

	public class XUIElement : XmlElement {
		public XUIElement(string prefix,
			string localName,
			string namespaceURI,
			XmlDocument doc) : base(prefix, localName, namespaceURI, doc) 
			{
			}

		public virtual void OnSetAttribute (string name, string value) {
		}

                public override void SetAttribute (string name, string value)
                {
			OnSetAttribute (name, value);
			base.SetAttribute (name, value);
                }

		public override string SetAttribute (string localName, string namespaceURI, string value) {
			OnSetAttribute (localName, value);
			return base.SetAttribute (localName, namespaceURI, value);
		}

		public override XmlAttribute SetAttributeNode (XmlAttribute newAttr) {
			OnSetAttribute (newAttr.LocalName, newAttr.Value);
			return base.SetAttributeNode (newAttr);
		}
	}

	public class XUIWidget : XUIElement {
		public XUIWidget(string prefix,
			string localName,
			string namespaceURI,
			XmlDocument doc) : base(prefix, localName, namespaceURI, doc) 
			{
			}

		public virtual Gtk.Widget GetWidget() {
			return null;
		}
	}


	public class XUIContainer : XUIWidget {
		public XUIContainer(string prefix,
			string localName,
			string namespaceURI,
			XmlDocument doc) : base(prefix, localName, namespaceURI, doc) 
			{
			}

		public override XmlNode InsertBefore (XmlNode newChild, XmlNode refChild) {
			XUIWidget widget = (XUIWidget)newChild;
			Gtk.Container container = (Gtk.Container)GetWidget();
			container.Add(widget.GetWidget());
			return base.InsertBefore(newChild, refChild);
		}
	}

	public class XUIWindowElement : XUIContainer {

		private Gtk.Window window;

		public XUIWindowElement(string prefix,
			string localName,
			string namespaceURI,
			XmlDocument doc) : base(prefix, localName, namespaceURI, doc) 
			{
				window = new Gtk.Window("XUI Window");
				window.Show();
			}

		public override Gtk.Widget GetWidget() {
			return window;
		}

		public override void OnSetAttribute (string name, string value) {
			switch (name) {
				case "title":
					window.Title = value;
					break;
			}
		}
	}

	public class XUIVBoxElement : XUIContainer {

		private Gtk.VBox vbox;

		public XUIVBoxElement(string prefix,
			string localName,
			string namespaceURI,
			XmlDocument doc) : base(prefix, localName, namespaceURI, doc) 
			{
				vbox = new Gtk.VBox();
				vbox.Show();
			}

		public override Gtk.Widget GetWidget() {
			return vbox;
		}

		public override void OnSetAttribute (string name, string value) {
		}
	}

	public class XUIButtonElement : XUIContainer {

		private Gtk.Button button;

		public XUIButtonElement(string prefix,
			string localName,
			string namespaceURI,
			XmlDocument doc) : base(prefix, localName, namespaceURI, doc) 
			{
				button = new Gtk.Button("XUI Button");
				button.Show();
			}

		public override Gtk.Widget GetWidget() {
			return button;
		}

		public override void OnSetAttribute (string name, string value) {
			switch (name) {
				case "label":
					button.Label = value;
					break;
			}
		}
	}

	public class XUILabelElement : XUIWidget {

		private Gtk.Label label;

		public XUILabelElement(string prefix,
			string localName,
			string namespaceURI,
			XmlDocument doc) : base(prefix, localName, namespaceURI, doc) 
			{
				label = new Gtk.Label("XUI Label");
				label.Show();
			}

		public override Gtk.Widget GetWidget() {
			return label;
		}

		public override void OnSetAttribute (string name, string value) {
			switch (name) {
				case "text":
					label.Text = value;
					break;
			}
		}
	}

	public class XUIDocument : XmlDocument {
                public override XmlElement CreateElement (
                        string prefix,
                        string localName,
                        string namespaceURI)
                {
			XmlElement el;
			switch (localName) {
				case "window":
					el = new XUIWindowElement(prefix, localName, namespaceURI, this);
					break;
				case "vbox":
					el = new XUIVBoxElement(prefix, localName, namespaceURI, this);
					break;
				case "button":
					el = new XUIButtonElement(prefix, localName, namespaceURI, this);
					break;
				case "label":
					el = new XUILabelElement(prefix, localName, namespaceURI, this);
					break;
				default:
					el = base.CreateElement(prefix, localName, namespaceURI);
					break;
					
			}
			return el;
                }

	}

        public static void Main(string [] args) {
                try {
			Application.Init();

                        string url = (string)args[0];
                        XmlTextReader reader = new XmlTextReader(url);
                        XUIDocument doc = new XUIDocument();

                        Console.WriteLine("loading xml");
                        doc.Load(reader);
                        Console.WriteLine("ok!");

			XmlElement label = (XmlElement)doc.SelectSingleNode("//label");
			label.SetAttribute("text", "hardcoded text");

			Application.Run();
                } catch (XmlException e) {
                        Console.WriteLine(e.Message);
                }
        }
}

--=-+8gUGUMJescVAvwCKTjd
Content-Disposition: attachment; filename=form.xml
Content-Type: text/xml; name=form.xml; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit

<?xml version="1.0" encoding="UTF-8"?>
<window title="Test Program">
	<vbox>
		<label text="This is a test 1" />
		<label text="This is a test 2" />
		<button label="Ok!" />
	</vbox>
</window>

--=-+8gUGUMJescVAvwCKTjd--