diff --git a/ChangeLog b/ChangeLog
index c375dda66..71fd108b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2002-10-19 Rachel Hestilow
+
+ * gconf, sample/gconf: Added.
+
+ * glue/combo.c: This was never added, add it now.
+
+ * configure.in, makefile, sample/Makefile.in: Build new
+ gconf bindings if gnome is enabled.
+
2002-10-14 Mike Kestner
* glib/Object.cs (GetObject): remove (int) cast
diff --git a/configure.in b/configure.in
index 06d0c5e69..7e53ed4c3 100644
--- a/configure.in
+++ b/configure.in
@@ -112,6 +112,10 @@ glade/Makefile
gnome/Makefile
gda/Makefile
gnomedb/Makefile
+gconf/Makefile
+gconf/GConf/Makefile
+gconf/GConf.PropertyEditors/Makefile
+gconf/tools/Makefile
sample/Makefile
])
diff --git a/gconf/GConf.PropertyEditors/EditorShell.cs b/gconf/GConf.PropertyEditors/EditorShell.cs
new file mode 100644
index 000000000..97f1b8fa1
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/EditorShell.cs
@@ -0,0 +1,97 @@
+namespace GConf.PropertyEditors
+{
+ using System;
+ using System.Collections;
+
+ public class EditorNotSupportedException : Exception
+ {
+ }
+
+ public class InvalidGladeKeyException : Exception
+ {
+ public InvalidGladeKeyException (string control_name) : base ("No such glade entry \"" + control_name + "\"")
+ {
+ }
+ }
+
+ public class EditorShell
+ {
+ ArrayList editors = new ArrayList ();
+ Hashtable by_key = new Hashtable ();
+ Glade.XML gxml;
+ GConf.ChangeSet cs = null;
+
+ public EditorShell (Glade.XML gxml)
+ {
+ this.gxml = gxml;
+ }
+
+ public EditorShell (Glade.XML gxml, GConf.ChangeSet cs)
+ {
+ this.gxml = gxml;
+ this.cs = cs;
+ }
+
+ public void Add (PropertyEditor editor)
+ {
+ editors.Add (editor);
+ if (cs != null)
+ editor.ChangeSet = cs;
+ editor.Setup ();
+ }
+
+ public void Add (string key, string control_name)
+ {
+ Add (key, control_name, null, null);
+ }
+
+ public void Add (string key, string control_name, Type enum_type, int[] enum_values)
+ {
+ PropertyEditor editor;
+ Gtk.Widget control = gxml[control_name];
+
+ if (control == null)
+ throw new InvalidGladeKeyException (control_name);
+
+ if (control is Gnome.ColorPicker)
+ editor = new PropertyEditorColorPicker (key, (Gnome.ColorPicker) control);
+ else if (control is Gnome.FileEntry)
+ editor = new PropertyEditorFileEntry (key, (Gnome.FileEntry) control);
+ else if (control is Gtk.SpinButton)
+ editor = new PropertyEditorSpinButton (key, (Gtk.SpinButton) control);
+ else if (control is Gtk.RadioButton)
+ editor = new PropertyEditorRadioButton (key, (Gtk.RadioButton) control, enum_type, enum_values);
+ else if (control is Gtk.ToggleButton)
+ editor = new PropertyEditorToggleButton (key, (Gtk.ToggleButton) control);
+ else if (control is Gtk.Entry)
+ editor = new PropertyEditorEntry (key, (Gtk.Entry) control);
+ else if (control is Gtk.OptionMenu)
+ editor = new PropertyEditorOptionMenu (key, (Gtk.OptionMenu) control, enum_type, enum_values);
+ else
+ throw new EditorNotSupportedException ();
+
+ by_key.Add (key, editor);
+ Add (editor);
+ }
+
+ public void Add (string key, string control_name, Type enum_type)
+ {
+ Add (key, control_name, enum_type, null);
+ }
+
+ public void AddGuard (string key, string control_name)
+ {
+ if (!by_key.Contains (key))
+ return;
+ Gtk.Widget control = gxml[control_name];
+ if (control == null)
+ throw new InvalidGladeKeyException (control_name);
+
+ PropertyEditorBool editor = by_key[key] as PropertyEditorBool;
+ if (editor == null)
+ throw new EditorNotSupportedException ();
+
+ editor.AddGuard (control);
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/Makefile.in b/gconf/GConf.PropertyEditors/Makefile.in
new file mode 100644
index 000000000..8d80cae0f
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/Makefile.in
@@ -0,0 +1,28 @@
+MCS = mcs
+DESTDIR =
+
+SOURCES = \
+ PropertyEditor.cs \
+ PropertyEditorBool.cs \
+ PropertyEditorColorPicker.cs \
+ PropertyEditorEnum.cs \
+ PropertyEditorEntry.cs \
+ PropertyEditorFileEntry.cs \
+ PropertyEditorOptionMenu.cs \
+ PropertyEditorRadioButton.cs \
+ PropertyEditorSpinButton.cs \
+ PropertyEditorToggleButton.cs \
+ EditorShell.cs \
+ #
+
+all: gconf-sharp-peditors.dll
+
+gconf-sharp-peditors.dll: $(SOURCES)
+ $(MCS) $(SOURCES) /r:../GConf/gconf-sharp.dll /r:glib-sharp /r:gtk-sharp /r:gnome-sharp /r:glade-sharp /r:System.Drawing /target:library /out:gconf-sharp-peditors.dll
+
+install: all
+ cp gconf-sharp-peditors.dll $(DESTDIR)@prefix@/lib
+
+clean:
+ rm -f gconf-sharp-peditors.dll
+
diff --git a/gconf/GConf.PropertyEditors/PropertyEditor.cs b/gconf/GConf.PropertyEditors/PropertyEditor.cs
new file mode 100644
index 000000000..cf22a063c
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditor.cs
@@ -0,0 +1,78 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+
+ public abstract class PropertyEditor
+ {
+ protected abstract void ValueChanged (object sender, NotifyEventArgs args);
+ protected abstract void ConnectHandlers ();
+
+ string key;
+ Client client;
+ ChangeSet cs;
+ Widget control;
+
+ public string Key
+ {
+ get { return key; }
+ }
+
+ public Widget Control
+ {
+ get { return control; }
+ }
+
+ protected object Get ()
+ {
+ ClientBase c = (cs != null) ? (ClientBase) cs : (ClientBase) client;
+ try {
+ return c.Get (key);
+ } catch (NoSuchKeyException e) {
+ }
+
+ if (cs != null)
+ {
+ try {
+ return client.Get (key);
+ } catch (NoSuchKeyException e) {
+ }
+ }
+
+ return null;
+ }
+
+ protected virtual void Set (object val)
+ {
+ ClientBase c = (cs != null) ? (ClientBase) cs : (ClientBase) client;
+ c.Set (key, val);
+ }
+
+ public virtual void Setup ()
+ {
+ if (client == null)
+ client = new Client ();
+
+ ValueChanged (client, new NotifyEventArgs (key, Get ()));
+ ConnectHandlers ();
+ client.AddNotify (key, new NotifyEventHandler (ValueChanged));
+ }
+
+ public Client Client
+ {
+ get { return client; }
+ set { client = value; }
+ }
+
+ public ChangeSet ChangeSet
+ {
+ get { return cs; }
+ set { cs = value; }
+ }
+
+ public PropertyEditor (string key, Widget control)
+ {
+ this.key = key;
+ this.control = control;
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorBool.cs b/gconf/GConf.PropertyEditors/PropertyEditorBool.cs
new file mode 100644
index 000000000..d0ec72f90
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorBool.cs
@@ -0,0 +1,31 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using System;
+ using System.Collections;
+
+ public abstract class PropertyEditorBool : PropertyEditor
+ {
+ ArrayList guards = new ArrayList ();
+
+ public void AddGuard (Widget control)
+ {
+ guards.Add (control);
+ control.Sensitive = (bool) Get ();
+ }
+
+ protected override void Set (object val)
+ {
+ bool val_bool = (bool) val;
+
+ foreach (Widget control in guards)
+ control.Sensitive = val_bool;
+
+ base.Set (val);
+ }
+
+ public PropertyEditorBool (string key, Widget control) : base (key, control)
+ {
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorColorPicker.cs b/gconf/GConf.PropertyEditors/PropertyEditorColorPicker.cs
new file mode 100644
index 000000000..d179f54dd
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorColorPicker.cs
@@ -0,0 +1,44 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using GtkSharp;
+ using Gnome;
+ using System;
+ using System.Drawing;
+
+ public class PropertyEditorColorPicker : PropertyEditor
+ {
+ protected override void ValueChanged (object sender, NotifyEventArgs args)
+ {
+ object val = args.Value;
+ if (val == null)
+ return;
+
+ ColorPicker picker = (ColorPicker) Control;
+ Color color = ColorTranslator.FromHtml ((string) val);
+ picker.SetI8 (color.R, color.G, color.B, color.A);
+ }
+
+ byte ToByte (uint val)
+ {
+ return (byte) (val >> 8);
+ }
+
+ void Changed (object obj, ColorSetArgs args)
+ {
+ ColorPicker picker = (ColorPicker) Control;
+ Color color = Color.FromArgb (ToByte (picker.Red), ToByte (picker.Green), ToByte (picker.Blue));
+ Set (ColorTranslator.ToHtml (color));
+ }
+
+ protected override void ConnectHandlers ()
+ {
+ ColorPicker picker = (ColorPicker) Control;
+ picker.ColorSet += new ColorSetHandler (Changed);
+ }
+
+ public PropertyEditorColorPicker (string key, ColorPicker picker) : base (key, picker)
+ {
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorEntry.cs b/gconf/GConf.PropertyEditors/PropertyEditorEntry.cs
new file mode 100644
index 000000000..25edf97c1
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorEntry.cs
@@ -0,0 +1,33 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using System;
+
+ public class PropertyEditorEntry : PropertyEditor
+ {
+ protected override void ValueChanged (object sender, NotifyEventArgs args)
+ {
+ object val = args.Value;
+ if (val == null)
+ return;
+ Entry entry = (Entry) Control;
+ entry.Text = (string) val;
+ }
+
+ void Changed (object obj, EventArgs args)
+ {
+ Entry entry = (Entry) Control;
+ Set (entry.Text);
+ }
+
+ protected override void ConnectHandlers ()
+ {
+ Entry entry = (Entry) Control;
+ entry.Changed += new EventHandler (Changed);
+ }
+
+ public PropertyEditorEntry (string key, Entry entry) : base (key, entry)
+ {
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorEnum.cs b/gconf/GConf.PropertyEditors/PropertyEditorEnum.cs
new file mode 100644
index 000000000..e1d0d49c3
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorEnum.cs
@@ -0,0 +1,85 @@
+namespace GConf.PropertyEditors
+{
+ using System;
+
+ public abstract class PropertyEditorEnum : PropertyEditor
+ {
+ Type enum_type = null;
+ int[] enum_values;
+ bool is_int = false;
+
+ protected int ValueToInt (object val)
+ {
+ if (val is int)
+ {
+ is_int = true;
+ return (int) val;
+ }
+ else if (val is string && enum_type != null)
+ {
+ object enum_val;
+ try {
+ enum_val = Enum.Parse (enum_type, (string) val);
+ } catch (Exception e) {
+ enum_val = 0;
+ }
+
+ int history = -1;
+ for (int i = 0; i < enum_values.Length; i++)
+ {
+ if (enum_values[i] == (int) enum_val)
+ {
+ history = i;
+ break;
+ }
+ }
+ return history;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ protected override void Set (object val)
+ {
+ if (is_int)
+ base.Set ((int) val);
+ else if (enum_type != null)
+ {
+ int enum_val = enum_values[(int) val];
+ base.Set (Enum.GetName (enum_type, enum_val));
+ }
+ }
+
+ public PropertyEditorEnum (string key, Gtk.Widget control) : base (key, control)
+ {
+ }
+
+ void InitValues ()
+ {
+ Array values = Enum.GetValues (enum_type);
+ enum_values = new int[values.Length];
+
+ int i = 0;
+ foreach (object val in values)
+ {
+ enum_values[i] = (int) val;
+ i++;
+ }
+ }
+
+ public PropertyEditorEnum (string key, Gtk.Widget control, Type enum_type, int[] enum_values) : base (key, control)
+ {
+ this.enum_type = enum_type;
+ if (enum_values == null)
+ InitValues ();
+ }
+
+ public PropertyEditorEnum (string key, Gtk.Widget control, Type enum_type) : base (key, control)
+ {
+ this.enum_type = enum_type;
+ InitValues ();
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorFileEntry.cs b/gconf/GConf.PropertyEditors/PropertyEditorFileEntry.cs
new file mode 100644
index 000000000..fdbd59fc8
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorFileEntry.cs
@@ -0,0 +1,37 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using Gnome;
+ using System;
+
+ public class PropertyEditorFileEntry : PropertyEditor
+ {
+ protected override void ValueChanged (object sender, NotifyEventArgs args)
+ {
+ object val = args.Value;
+ if (val == null)
+ return;
+ FileEntry entry = (FileEntry) Control;
+ entry.Filename = (string) val;
+ }
+
+ void Changed (object obj, EventArgs args)
+ {
+ FileEntry entry = (FileEntry) Control;
+ string filename = entry.Filename;
+ if (filename == null)
+ filename = String.Empty;
+ Set (filename);
+ }
+
+ protected override void ConnectHandlers ()
+ {
+ FileEntry entry = (FileEntry) Control;
+ entry.Changed += new EventHandler (Changed);
+ }
+
+ public PropertyEditorFileEntry (string key, FileEntry entry) : base (key, entry)
+ {
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorOptionMenu.cs b/gconf/GConf.PropertyEditors/PropertyEditorOptionMenu.cs
new file mode 100644
index 000000000..cbd266a32
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorOptionMenu.cs
@@ -0,0 +1,41 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using GtkSharp;
+ using System;
+
+ public class PropertyEditorOptionMenu : PropertyEditorEnum
+ {
+ protected override void ValueChanged (object sender, NotifyEventArgs args)
+ {
+ object val = args.Value;
+ OptionMenu menu = (OptionMenu) Control;
+ menu.SetHistory ((uint) ValueToInt (val));
+ }
+
+ void Changed (object obj, EventArgs args)
+ {
+ OptionMenu menu = (OptionMenu) Control;
+ int history = menu.History;
+ Set (history);
+ }
+
+ protected override void ConnectHandlers ()
+ {
+ OptionMenu menu = (OptionMenu) Control;
+ menu.Changed += new EventHandler (Changed);
+ }
+
+ public PropertyEditorOptionMenu (string key, OptionMenu menu) : base (key, menu)
+ {
+ }
+
+ public PropertyEditorOptionMenu (string key, OptionMenu menu, Type enum_type, int[] enum_values) : base (key, menu, enum_type, enum_values)
+ {
+ }
+
+ public PropertyEditorOptionMenu (string key, OptionMenu menu, Type enum_type) : base (key, menu, enum_type)
+ {
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorRadioButton.cs b/gconf/GConf.PropertyEditors/PropertyEditorRadioButton.cs
new file mode 100644
index 000000000..8bd6f918b
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorRadioButton.cs
@@ -0,0 +1,62 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using GtkSharp;
+ using System;
+
+ public class PropertyEditorRadioButton : PropertyEditorEnum
+ {
+ GLib.SList group = null;
+
+ protected override void ValueChanged (object sender, NotifyEventArgs args)
+ {
+ object val = args.Value;
+ int selected = ValueToInt (val);
+ int i = group.Count - 1;
+ foreach (RadioButton button in group)
+ {
+ if (i == selected)
+ {
+ button.Active = true;
+ break;
+ }
+ i--;
+ }
+ }
+
+ void Changed (object obj, EventArgs args)
+ {
+ int i = group.Count - 1;
+ foreach (RadioButton button in group)
+ {
+ if (button.Active)
+ {
+ Set (i);
+ break;
+ }
+ i--;
+ }
+ }
+
+ protected override void ConnectHandlers ()
+ {
+ foreach (RadioButton button in group)
+ button.Toggled += new EventHandler (Changed);
+ }
+
+ public PropertyEditorRadioButton (string key, RadioButton button) : base (key, button)
+ {
+ group = button.Group;
+ }
+
+ public PropertyEditorRadioButton (string key, RadioButton button, Type enum_type, int[] enum_values) : base (key, button, enum_type, enum_values)
+ {
+ group = button.Group;
+ }
+
+ public PropertyEditorRadioButton (string key, RadioButton button, Type enum_type) : base (key, button, enum_type)
+ {
+ group = button.Group;
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorSpinButton.cs b/gconf/GConf.PropertyEditors/PropertyEditorSpinButton.cs
new file mode 100644
index 000000000..8326d50ae
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorSpinButton.cs
@@ -0,0 +1,42 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using GtkSharp;
+ using System;
+
+ public class PropertyEditorSpinButton : PropertyEditor
+ {
+ bool is_int;
+
+ protected override void ValueChanged (object sender, NotifyEventArgs args)
+ {
+ object val = args.Value;
+ SpinButton spin = (SpinButton) Control;
+ is_int = val is int;
+
+ if (is_int)
+ spin.Value = (double) (int) val;
+ else
+ spin.Value = (double) val;
+ }
+
+ void Changed (object obj, EventArgs args)
+ {
+ Adjustment adj = (Adjustment) obj;
+ if (is_int)
+ Set ((int) adj.Value);
+ else
+ Set (adj.Value);
+ }
+
+ protected override void ConnectHandlers ()
+ {
+ SpinButton spin = (SpinButton) Control;
+ spin.Adjustment.ValueChanged += new EventHandler (Changed);
+ }
+
+ public PropertyEditorSpinButton (string key, SpinButton spin) : base (key, spin)
+ {
+ }
+ }
+}
diff --git a/gconf/GConf.PropertyEditors/PropertyEditorToggleButton.cs b/gconf/GConf.PropertyEditors/PropertyEditorToggleButton.cs
new file mode 100644
index 000000000..63a123200
--- /dev/null
+++ b/gconf/GConf.PropertyEditors/PropertyEditorToggleButton.cs
@@ -0,0 +1,31 @@
+namespace GConf.PropertyEditors
+{
+ using Gtk;
+ using System;
+
+ public class PropertyEditorToggleButton : PropertyEditorBool
+ {
+ protected override void ValueChanged (object sender, NotifyEventArgs args)
+ {
+ object val = args.Value;
+ ToggleButton checkbox = (ToggleButton) Control;
+ checkbox.Active = (bool) val;
+ }
+
+ void Toggled (object obj, EventArgs args)
+ {
+ ToggleButton checkbox = (ToggleButton) Control;
+ Set (checkbox.Active);
+ }
+
+ protected override void ConnectHandlers ()
+ {
+ ToggleButton checkbox = (ToggleButton) Control;
+ checkbox.Toggled += new EventHandler (Toggled);
+ }
+
+ public PropertyEditorToggleButton (string key, ToggleButton checkbox) : base (key, checkbox)
+ {
+ }
+ }
+}
diff --git a/gconf/GConf/ChangeSet.cs b/gconf/GConf/ChangeSet.cs
new file mode 100644
index 000000000..a3ad60d37
--- /dev/null
+++ b/gconf/GConf/ChangeSet.cs
@@ -0,0 +1,60 @@
+namespace GConf
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ public class ChangeSet : ClientBase, IDisposable
+ {
+ IntPtr Raw = IntPtr.Zero;
+
+ [DllImport("gconf-2")]
+ static extern IntPtr gconf_change_set_new ();
+
+ public ChangeSet ()
+ {
+ Initialize ();
+ Raw = gconf_change_set_new ();
+ }
+
+ ~ChangeSet ()
+ {
+ Dispose ();
+ }
+
+ [DllImport("gconf-2")]
+ static extern void gconf_change_set_unref (IntPtr cs);
+
+ public void Dispose ()
+ {
+ if (Raw != IntPtr.Zero)
+ {
+ gconf_change_set_unref (Raw);
+ Raw = IntPtr.Zero;
+ }
+ }
+
+ [DllImport("gconf-2")]
+ static extern void gconf_change_set_set (IntPtr cs, string key, IntPtr val);
+
+ protected override void SetValue (string key, Value val)
+ {
+ gconf_change_set_set (Raw, key, val.Handle);
+ }
+
+ [DllImport("gconf-2")]
+ static extern bool gconf_change_set_check_value (IntPtr cs, string key, out IntPtr val);
+
+ public override object Get (string key)
+ {
+ IntPtr raw_val;
+ if (gconf_change_set_check_value (Raw, key, out raw_val) && raw_val != IntPtr.Zero) {
+ Value val = new Value (raw_val);
+ val.Managed = false;
+ return val.Get ();
+ } else {
+ throw new NoSuchKeyException ();
+ }
+ }
+ }
+}
+
diff --git a/gconf/GConf/Client.cs b/gconf/GConf/Client.cs
new file mode 100644
index 000000000..72226f883
--- /dev/null
+++ b/gconf/GConf/Client.cs
@@ -0,0 +1,99 @@
+namespace GConf
+{
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+
+ public class Client : ClientBase
+ {
+ IntPtr Raw = IntPtr.Zero;
+ Hashtable dirs = new Hashtable ();
+ Hashtable callbacks = new Hashtable ();
+
+ [DllImport("gconf-2")]
+ static extern IntPtr gconf_client_get_default ();
+
+ public Client ()
+ {
+ Initialize ();
+ Raw = gconf_client_get_default ();
+ }
+
+ internal Client (IntPtr raw)
+ {
+ Initialize ();
+ Raw = raw;
+ }
+
+ [DllImport("gconf-2")]
+ static extern void gconf_client_set (IntPtr client, string key, IntPtr val, out IntPtr err);
+
+ protected override void SetValue (string key, Value val)
+ {
+ IntPtr err;
+ gconf_client_set (Raw, key, val.Handle, out err);
+ if (err != IntPtr.Zero)
+ throw new GLib.GException (err);
+ }
+
+ [DllImport("gconf-2")]
+ static extern IntPtr gconf_client_get (IntPtr client, string key, out IntPtr err);
+
+ public override object Get (string key)
+ {
+ IntPtr err;
+ IntPtr raw = gconf_client_get (Raw, key, out err);
+ if (err != IntPtr.Zero)
+ throw new GLib.GException (err);
+ if (raw == IntPtr.Zero)
+ throw new NoSuchKeyException ();
+
+ Value val = new Value (raw);
+ return val.Get ();
+ }
+
+ [DllImport("gconf-2")]
+ static extern uint gconf_client_add_dir (IntPtr client, string dir, int preload, out IntPtr err);
+
+ void AddDir (string dir)
+ {
+ IntPtr err;
+
+ if (dirs.Contains (dir))
+ return;
+
+ dirs.Add (dir, 1);
+ gconf_client_add_dir (Raw, dir, 0, out err);
+ if (err != IntPtr.Zero)
+ throw new GLib.GException (err);
+ }
+
+ [DllImport("gconf-2")]
+ static extern uint gconf_client_notify_add (IntPtr client, string dir, NotifyFuncNative func, IntPtr user_data, IntPtr destroy_notify, out IntPtr err);
+
+ public void AddNotify (string dir, NotifyEventHandler notify)
+ {
+ IntPtr err;
+
+ AddDir (dir);
+ uint cnxn = gconf_client_notify_add (Raw, dir, NotifyWrapper.Wrap (notify), IntPtr.Zero, IntPtr.Zero, out err);
+ if (err != IntPtr.Zero)
+ throw new GLib.GException (err);
+ callbacks.Add (notify, cnxn);
+ }
+
+ [DllImport("gconf-2")]
+ static extern void gconf_client_notify_remove (IntPtr client, uint cnxn);
+
+ public void RemoveNotify (string dir, NotifyEventHandler notify)
+ {
+ if (!callbacks.Contains (notify))
+ return;
+
+ uint cnxn = (uint) callbacks[notify];
+ gconf_client_notify_remove (Raw, cnxn);
+ callbacks.Remove (notify);
+ }
+ }
+}
+
diff --git a/gconf/GConf/ClientBase.cs b/gconf/GConf/ClientBase.cs
new file mode 100644
index 000000000..1ab355e3b
--- /dev/null
+++ b/gconf/GConf/ClientBase.cs
@@ -0,0 +1,54 @@
+namespace GConf
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ public abstract class ClientBase
+ {
+ public abstract object Get (string key);
+ protected abstract void SetValue (string key, Value val);
+/*
+ public void Set (string key, string val)
+ {
+ Set (key, new Value (val));
+ }
+
+ public void Set (string key, int val)
+ {
+ Set (key, new Value (val));
+ }
+
+ public void Set (string key, double val)
+ {
+ Set (key, new Value (val));
+ }
+
+ public void Set (string key, bool val)
+ {
+ Set (key, new Value (val));
+ }
+*/
+ public void Set (string key, object val)
+ {
+ SetValue (key, new Value (val));
+ }
+
+ [DllImport("gconf-2")]
+ static extern bool gconf_is_initialized ();
+
+ [DllImport("gconf-2")]
+ static extern bool gconf_init (int argc, IntPtr argv, out IntPtr err);
+
+ protected void Initialize ()
+ {
+ if (!gconf_is_initialized ())
+ {
+ IntPtr err;
+ gconf_init (0, IntPtr.Zero, out err);
+ if (err != IntPtr.Zero)
+ throw new GLib.GException (err);
+ }
+ }
+ }
+}
+
diff --git a/gconf/GConf/Makefile.in b/gconf/GConf/Makefile.in
new file mode 100644
index 000000000..dbeb37865
--- /dev/null
+++ b/gconf/GConf/Makefile.in
@@ -0,0 +1,26 @@
+MCS = mcs
+DESTDIR =
+
+SOURCES = \
+ ClientBase.cs \
+ Client.cs \
+ ChangeSet.cs \
+ _Entry.cs \
+ NoSuchKeyException.cs \
+ NotifyEventArgs.cs \
+ NotifyEventHandler.cs \
+ NotifyWrapper.cs \
+ Value.cs \
+ #
+
+all: gconf-sharp.dll
+
+gconf-sharp.dll: $(SOURCES)
+ $(MCS) $(SOURCES) /r:glib-sharp.dll /target:library /out:gconf-sharp.dll
+
+install: all
+ cp gconf-sharp.dll $(DESTDIR)@prefix@/lib
+
+clean:
+ rm -f gconf-sharp.dll
+
diff --git a/gconf/GConf/NoSuchKeyException.cs b/gconf/GConf/NoSuchKeyException.cs
new file mode 100644
index 000000000..bf774ffe4
--- /dev/null
+++ b/gconf/GConf/NoSuchKeyException.cs
@@ -0,0 +1,8 @@
+namespace GConf
+{
+ using System;
+
+ public class NoSuchKeyException : Exception
+ {
+ }
+}
diff --git a/gconf/GConf/NotifyEventArgs.cs b/gconf/GConf/NotifyEventArgs.cs
new file mode 100644
index 000000000..9f6c46448
--- /dev/null
+++ b/gconf/GConf/NotifyEventArgs.cs
@@ -0,0 +1,25 @@
+namespace GConf
+{
+ public class NotifyEventArgs : System.EventArgs
+ {
+ string key;
+ object val;
+
+ public NotifyEventArgs (string key, object val)
+ {
+ this.key = key;
+ this.val = val;
+ }
+
+ public string Key
+ {
+ get { return key; }
+ }
+
+ public object Value
+ {
+ get { return val; }
+ }
+ }
+}
+
diff --git a/gconf/GConf/NotifyEventHandler.cs b/gconf/GConf/NotifyEventHandler.cs
new file mode 100644
index 000000000..ee33e989d
--- /dev/null
+++ b/gconf/GConf/NotifyEventHandler.cs
@@ -0,0 +1,4 @@
+namespace GConf
+{
+ public delegate void NotifyEventHandler (object sender, NotifyEventArgs args);
+}
diff --git a/gconf/GConf/NotifyWrapper.cs b/gconf/GConf/NotifyWrapper.cs
new file mode 100644
index 000000000..46531435e
--- /dev/null
+++ b/gconf/GConf/NotifyWrapper.cs
@@ -0,0 +1,37 @@
+namespace GConf
+{
+ using System;
+ using System.Collections;
+
+ internal delegate void NotifyFuncNative (IntPtr client_ptr, uint id, IntPtr entry_ptr, IntPtr user_data);
+
+ internal class NotifyWrapper
+ {
+ static ArrayList refs = new ArrayList ();
+ NotifyEventHandler notify;
+ NotifyFuncNative native;
+
+ void NotifyCB (IntPtr client_ptr, uint id, IntPtr entry_ptr, IntPtr user_data)
+ {
+ Client client = new Client (client_ptr);
+ _Entry entry = new _Entry (entry_ptr);
+ Value val = new Value (entry.ValuePtr);
+ val.Managed = false;
+ notify (client, new NotifyEventArgs (entry.Key, val.Get ()));
+ }
+
+ public NotifyWrapper (NotifyEventHandler notify)
+ {
+ this.notify = notify;
+ this.native = new NotifyFuncNative (this.NotifyCB);
+ }
+
+ public static NotifyFuncNative Wrap (NotifyEventHandler notify)
+ {
+ NotifyWrapper wrapper = new NotifyWrapper (notify);
+ refs.Add (wrapper);
+ return wrapper.native;
+ }
+ }
+}
+
diff --git a/gconf/GConf/Value.cs b/gconf/GConf/Value.cs
new file mode 100644
index 000000000..ad471a753
--- /dev/null
+++ b/gconf/GConf/Value.cs
@@ -0,0 +1,196 @@
+namespace GConf
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ internal enum ValueType
+ {
+ Invalid,
+ String,
+ Int,
+ Float,
+ Bool,
+ Schema,
+ List,
+ Pair
+ };
+
+ internal struct NativeValue
+ {
+ public ValueType type;
+ }
+
+ internal class InvalidValueTypeException : Exception
+ {
+ }
+
+ internal class Value : IDisposable
+ {
+ IntPtr Raw = IntPtr.Zero;
+ ValueType val_type = ValueType.Invalid;
+ bool managed = true;
+
+ [DllImport("gconf-2")]
+ static extern void gconf_value_set_string (IntPtr value, string data);
+ [DllImport("gconf-2")]
+ static extern void gconf_value_set_int (IntPtr value, int data);
+ [DllImport("gconf-2")]
+ static extern void gconf_value_set_float (IntPtr value, double data);
+ [DllImport("gconf-2")]
+ static extern void gconf_value_set_bool (IntPtr value, bool data);
+
+ ValueType LookupType (object data)
+ {
+ if (data is string) {
+ return ValueType.String;
+ } else if (data is int) {
+ return ValueType.Int;
+ } else if (data is double) {
+ return ValueType.Float;
+ } else if (data is bool) {
+ return ValueType.Bool;
+ } else {
+ return ValueType.Invalid;
+ }
+ }
+
+ public void Set (object data)
+ {
+ if (data == null)
+ throw new NullReferenceException ();
+
+ ValueType type = LookupType (data);
+ Set (data, type);
+ }
+
+ void Set (object data, ValueType type)
+ {
+ if (data == null)
+ throw new NullReferenceException ();
+
+ switch (type)
+ {
+ case ValueType.String:
+ gconf_value_set_string (Raw, (string) data);
+ break;
+ case ValueType.Int:
+ gconf_value_set_int (Raw, (int) data);
+ break;
+ case ValueType.Float:
+ gconf_value_set_float (Raw, (double) data);
+ break;
+ case ValueType.Bool:
+ gconf_value_set_bool (Raw, (bool) data);
+ break;
+ default:
+ throw new InvalidValueTypeException ();
+ }
+ }
+
+ [DllImport("gconf-2")]
+ static extern string gconf_value_get_string (IntPtr value);
+
+ [DllImport("gconf-2")]
+ static extern int gconf_value_get_int (IntPtr value);
+
+ [DllImport("gconf-2")]
+ static extern double gconf_value_get_float (IntPtr value);
+
+ [DllImport("gconf-2")]
+ static extern bool gconf_value_get_bool (IntPtr value);
+
+ public object Get ()
+ {
+ switch (val_type)
+ {
+ case ValueType.String:
+ return gconf_value_get_string (Raw);
+ case ValueType.Int:
+ return gconf_value_get_int (Raw);
+ case ValueType.Float:
+ return gconf_value_get_float (Raw);
+ case ValueType.Bool:
+ return gconf_value_get_bool (Raw);
+ default:
+ throw new InvalidValueTypeException ();
+ }
+ }
+
+ [DllImport("gconf-2")]
+ static extern IntPtr gconf_value_new (ValueType type);
+
+ public Value (ValueType type)
+ {
+ Raw = gconf_value_new (type);
+ }
+
+ void Initialize (object val, ValueType type)
+ {
+ Raw = gconf_value_new (type);
+ val_type = type;
+ Set (val, type);
+ }
+
+ public Value (IntPtr raw)
+ {
+ Raw = raw;
+ NativeValue val = (NativeValue) Marshal.PtrToStructure (raw, typeof (NativeValue));
+ val_type = val.type;
+ }
+/*
+ public Value (string val)
+ {
+ Initialize (val, ValueType.String);
+ }
+
+ public Value (int val)
+ {
+ Initialize (val, ValueType.Int);
+ }
+
+ public Value (double val)
+ {
+ Initialize (val, ValueType.Float);
+ }
+
+ public Value (bool val)
+ {
+ Initialize (val, ValueType.Bool);
+ }
+*/
+ public Value (object val)
+ {
+ Initialize (val, LookupType (val));
+ }
+ public bool Managed
+ {
+ get { return managed; }
+ set { managed = value; }
+ }
+
+ [DllImport("gconf-2")]
+ static extern void gconf_value_free (IntPtr value);
+
+ ~Value ()
+ {
+ Dispose ();
+ }
+
+ public void Dispose ()
+ {
+ if (managed && Raw != IntPtr.Zero)
+ {
+ gconf_value_free (Raw);
+ Raw = IntPtr.Zero;
+ }
+ }
+
+ public IntPtr Handle
+ {
+ get {
+ return Raw;
+ }
+ }
+ }
+}
+
diff --git a/gconf/GConf/_Entry.cs b/gconf/GConf/_Entry.cs
new file mode 100644
index 000000000..d2dee1be8
--- /dev/null
+++ b/gconf/GConf/_Entry.cs
@@ -0,0 +1,31 @@
+namespace GConf
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ internal struct _NativeEntry
+ {
+ public string key;
+ public IntPtr value;
+ }
+
+ internal class _Entry
+ {
+ _NativeEntry native;
+
+ public _Entry (IntPtr raw)
+ {
+ native = (_NativeEntry) Marshal.PtrToStructure (raw, typeof (_NativeEntry));
+ }
+
+ public string Key
+ {
+ get { return native.key; }
+ }
+
+ internal IntPtr ValuePtr
+ {
+ get { return native.value; }
+ }
+ }
+}
diff --git a/gconf/Makefile.in b/gconf/Makefile.in
new file mode 100644
index 000000000..0b012a407
--- /dev/null
+++ b/gconf/Makefile.in
@@ -0,0 +1,19 @@
+SUBDIRS = GConf GConf.PropertyEditors tools
+
+@ENABLE_GNOME_TRUE@ all: linux
+@ENABLE_GNOME_FALSE@ all:
+
+linux:
+ for i in $(SUBDIRS); do \
+ make -C $$i || exit 1; \
+ done
+
+install: all
+ for i in $(SUBDIRS); do \
+ make -C $$i install || exit 1; \
+ done
+
+clean:
+ for i in $(SUBDIRS); do \
+ make -C $$i clean || exit 1; \
+ done
diff --git a/gconf/doc/intro.html b/gconf/doc/intro.html
new file mode 100644
index 000000000..3372aaaa2
--- /dev/null
+++ b/gconf/doc/intro.html
@@ -0,0 +1,207 @@
+
+
+
+
+ Using GConf#
+
+
+
+ Using GConf#
+ Introduction
+ Using GConf directly from an application is often inconvenient.
+ Because the configuration key system effectively represents a
+ string-based API, accessing GConf values leaves your application
+ open to runtime errors from a single typo. Even if you store your
+ keys in constants (as is recommended), you still wind up maintaining
+ two lists of keys: one in the schema, and one in your app.
+ Another problem is that the GConf value types are very limited:
+ string, float, int, bool, and list. When storing common value types
+ such as colors or enumerations, one has to serialize these values
+ to and from strings.
+ Finally, providing graphical dialogs for your settings can be a very
+ tedious process. For each config element exposed in your UI, you have
+ to manually hook up the "changed" signal on the UI to a custom handler
+ setting the GConf value. Inversely, one must initially populate the
+ dialog based on previously-set GConf values. Complicating all of this
+ is the GNOME HIG, which specifies that all preference dialogs be
+ instant-apply if possible.
+ GConf# addresses these issues with two new utilities: SchemaGen, and
+ the GConf.PropertyEditors library.
+
+ SchemaGen
+ SchemaGen is a new tool which generates a custom API for the settings
+ in a gconf schema file. Given a schema, it generates two classes,
+ Settings and SettingKeys. Settings provides static
+ properties for each specified gconf setting. These properties map
+ directly to the values in the gconf database. Settings also
+ specifies static events for each setting indicating when the setting
+ has changed, and a generic Changed event which notifies when any
+ of your settings have changed. Finally, for every property in
+ Settings, SchemaGen creates a read-only property of the same
+ name in SettingKeys specifying the GConf key used to access
+ this property. SettingKeys is not needed if you are only using
+ the Settings class, but it is very useful when attaching
+ PropertyEditors, or when accessing GConf directly.
+ SchemaGen also provides for limited marshalling to and from the
+ GConf value types. It currently defines marshallers for
+ System.Drawing.Color and for enumerations. This is done by specifying
+ a cstype directive in the GConf schema.
+ Example
+ First, we need to write a GConf schema specifying our settings.
+
+<gconfschema>
+ <schemalist>
+ <schema>
+ <key>/schemas/apps/gconfsharp/sample_app/toolbar_alignment</key>
+ <applyto>/apps/gconfsharp/sample_app/toolbar_alignment</applyto>
+ <owner>sample_app</owner>
+ <type>string</type>
+ <cstype class="Sample.Alignment">enum</cstype>
+ <locale name="C">
+ <short>Toolbar alignment</short>
+ <long>Where the toolbar should be. Can be one of Top, Bottom, Left, Rigt.</long>
+ </locale>
+ <default>Top</default>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gconfsharp/sample_app/text_color</key>
+ <applyto>/apps/gconfsharp/sample_app/text_color</applyto>
+ <owner>sample_app</owner>
+ <type>string</type>
+ <cstype>color</cstype>
+ <locale name="C">
+ <short>Text color</short>
+ <long>Text color</long>
+ </locale>
+ <default>#000000</default>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gconfsharp/sample_app/enable_text_color</key>
+ <applyto>/apps/gconfsharp/sample_app/enable_text_color</applyto>
+ <owner>sample_app</owner>
+ <type>bool</type>
+ <locale name="C">
+ <short>Show colored text</short>
+ <long>Show colored text</long>
+ </locale>
+ <default>#000000</default>
+ </schema>
+ </schemalist>
+</gconfschemafile>
+
+ Note how we specify both the cstype and type for the enum and color.
+ This is because GConf doesn't know anything about cstype.
+ We save this to sample.schema, and install it with the command:
+ env GCONF_CONFIG_SOURCE="" gconftool-2 --makefile-install-rule sample.schema
+ GConf generates a warning because it doesn't recognize cstype, but
+ it is nothing to worry about.
+ We're now ready to run SchemaGen. Installing the schema before running
+ SchemaGen is not required, but you should make sure to install it before
+ running your application, because GConf# will throw an exception if
+ GConf can't find your settings.
+ SchemaGen's full executable name is gconfsharp-schemagen. It
+ takes a namespace and the schema filename as parameters, and outputs
+ to the console. Here is the command used to generate Settings.cs for
+ sample.schema:
+ gconfsharp-schemagen Sample sample.schema > Settings.cs
+ Now we're ready to write a small program using our new settings.
+
+namespace Sample
+{
+ using System;
+ using System.Drawing;
+
+ public enum Alignment
+ {
+ Top,
+ Bottom,
+ Left,
+ Right
+ }
+
+ class X
+ {
+ public static void Main (string args[])
+ {
+ Alignment align = Settings.ToolbarAlignment;
+ Console.WriteLine ("Alignment is: {0}", align);
+ Settings.ToolbarAlignment = Left;
+ Console.WriteLine ("Color is: {0}", Settings.TextColor);
+ Console.WriteLine ("Color is enabled: {0}", Settings.TextEnableColor);
+ }
+ }
+}
+
+ As you can see, our GConf settings are now nicely encapsulated, and
+ are as easy to access as any other .NET properties.
+ Property Editors
+ Property Editors are objects which act as intermediaries between
+ GConf and Gtk+ widgets. They are analoguous to the Controller of the MVC
+ design pattern. Property editors do two things:
+
+ - They listen to GConf notifications, and update the widget
+ to reflect any changes in a GConf setting.
+
- They connect to the various "changed" signals on a widget,
+ and update GConf to reflect the widget's current state.
+
+ This means that the widget and GConf are always in sync, no matter
+ if the value is set through Gtk+ or through GConf. GConf# defines a
+ number of Property Editors which correspond to common widget/setting
+ combinations -- for example, a CheckButton representing a boolean
+ setting.
+
+ GConf# also provides a utility class called EditorShell.
+ EditorShell exposes a simple API to automatically construct
+ PropertyEditors for a Glade UI.
+ As a historical note, and in the interests of giving credit where
+ credit is due, it should be noted that GConf Property Editors are
+ not unique to GConf#. They were originally conceived and implemented
+ by Bradford Hovinen for use in the GNOME Control Center. Although
+ the APIs are somewhat similar, the original version was written in
+ C and was limited to internal use in the Control Center.
+ Example
+ For this example we'll assume you have written a Glade UI for
+ the settings in the previous example. It employs three elements:
+ an option menu named "toolbar_menu", a checkbox named "enable_check",
+ and a color picker named "colorpicker". Given our Glade.XML object,
+ all we have to do is set up the EditorShell.
+
+Glade.XML gxml = ...
+GConf.PropertyEditors.EditorShell shell = new GConf.PropertyEditors.EditorShell (gxml);
+
+shell.Add (SettingKeys.ToolbarAlignment, "toolbar_menu", typeof (Sample.Alignment));
+shell.Add (SettingKeys.EnableTextColor, "enable_check");
+shell.Add (SettingKeys.TextColor, "colorpicker");
+
+ That's all that is needed to implement the preferences dialog. Note
+ how we didn't have to specify what type of property editor to use.
+ The EditorShell uses introspection to create the correct Property
+ Editor for all the types of widgets it knows about. Also note that
+ because ToolbarAlignment is an enum, we had to pass its type in so that
+ the Property Editor can store its value correctly. By default,
+ Property Editors assume that the order of elements in an OptionMenu
+ (or RadioButton) correspond to the order of values in an enum. If
+ this is not the case, you can pass in an additional parameter to
+ Add: an array of integers, each array element being the integer
+ representation of an enum value. This array represents the order of
+ values in your GUI element.
+
+ Now, a really good preference dialog would "ghost out" the
+ color picker if the "Enable text color" option is disabled. This
+ requires a small addition to our previous code:
+
+shell.AddGuard (SettingKeys.EnableTextColor, "color_box");
+
+ Again, for the purposes of the example, "color_box" is the name of the
+ HBox containing the label and color picker corresponding to TextColor.
+
+
+
+ Last updated: October 19th, 2002
+ Rachel Hestilow (hestilow@ximian.com)
+
+
+
+
diff --git a/gconf/tools/Makefile.in b/gconf/tools/Makefile.in
new file mode 100644
index 000000000..60b99e9e9
--- /dev/null
+++ b/gconf/tools/Makefile.in
@@ -0,0 +1,25 @@
+MCS = mcs
+DESTDIR =
+bindir = @prefix@/bin
+
+SOURCES = \
+ schemagen.cs \
+ #
+
+all: gconfsharp-schemagen.exe gconfsharp-schemagen
+
+gconfsharp-schemagen.exe: $(SOURCES)
+ $(MCS) /out:gconfsharp-schemagen.exe $(SOURCES)
+
+gconfsharp-schemagen: gconfsharp-schemagen.in
+ sed -e 's^\@bindir\@^$(bindir)^g' < gconfsharp-schemagen.in > gconfsharp-schemagen.tmp \
+ && mv gconfsharp-schemagen.tmp gconfsharp-schemagen \
+ && chmod +x gconfsharp-schemagen
+
+install: all
+ chmod +x gconfsharp-schemagen && cp gconfsharp-schemagen.exe gconfsharp-schemagen $(DESTDIR)@prefix@/bin
+
+clean:
+ rm -f gconfsharp-schemagen.exe
+ rm -f gconfsharp-schemagen
+
diff --git a/gconf/tools/gconfsharp-schemagen.in b/gconf/tools/gconfsharp-schemagen.in
new file mode 100644
index 000000000..abb690315
--- /dev/null
+++ b/gconf/tools/gconfsharp-schemagen.in
@@ -0,0 +1,2 @@
+#!/bin/sh
+@bindir@/mono @bindir@/gconfsharp-schemagen.exe "$@"
diff --git a/gconf/tools/schemagen.cs b/gconf/tools/schemagen.cs
new file mode 100644
index 000000000..9bcf1e73f
--- /dev/null
+++ b/gconf/tools/schemagen.cs
@@ -0,0 +1,272 @@
+namespace GConf.Tools
+{
+ using GConf;
+ using System;
+ using System.Xml;
+ using System.Collections;
+ using System.IO;
+ using System.Text;
+
+ class SchemaGen
+ {
+ private Hashtable keys = new Hashtable ();
+ private Hashtable classes = new Hashtable ();
+
+ static void Die (string error)
+ {
+ Console.WriteLine (error);
+ Environment.Exit (1);
+ }
+
+ void DieInvalid (string filename)
+ {
+ Die (filename + " is an invalid schema");
+ }
+
+ void Parse (string filename)
+ {
+ XmlDocument doc = new XmlDocument ();
+ try {
+ doc.Load (filename);
+ } catch (XmlException e) {
+ Die ("Could not parse " + filename);
+ }
+
+ XmlElement root = doc.DocumentElement;
+ if (!(root != null && root.HasChildNodes && root.Name == "gconfschemafile"))
+ DieInvalid (filename);
+
+ foreach (XmlNode slist in root.ChildNodes)
+ {
+ if (!(slist != null && slist.Name == "schemalist"))
+ continue;
+
+ foreach (XmlNode schema_node in slist.ChildNodes)
+ {
+ XmlElement schema = schema_node as XmlElement;
+ if (!(schema != null && schema.Name == "schema"))
+ continue;
+
+ XmlElement key = schema["applyto"];
+ XmlElement type = schema["cstype"];
+ if (type == null)
+ type = schema["type"];
+ if (key == null || type == null)
+ DieInvalid (filename);
+ keys.Add (key.InnerText, type.InnerText);
+
+ if (type.HasAttribute ("class"))
+ classes.Add (key.InnerText, type.GetAttribute ("class"));
+ }
+ }
+ }
+
+ string ExtractPrefix ()
+ {
+ string path = null;
+
+ foreach (string key in keys.Keys)
+ {
+ int slash = key.LastIndexOf ('/');
+ if (slash < 0)
+ continue;
+
+ string new_path = key.Substring (0, slash + 1);
+ if (path == null || new_path.Length < path.Length)
+ path = new_path;
+ }
+
+ return path;
+ }
+
+ string BaseName (string key)
+ {
+ int slash = key.LastIndexOf ('/');
+ if (slash < 0)
+ return key;
+ return key.Substring (slash + 1);
+ }
+
+ string PropertyName (string key)
+ {
+ string basename = BaseName (key);
+ StringBuilder sb = new StringBuilder ();
+
+ bool needs_caps = true;
+ foreach (char orig in basename)
+ {
+ char c = orig;
+ if (c == '_' || c == '-')
+ {
+ needs_caps = true;
+ continue;
+ }
+
+ if (needs_caps)
+ {
+ c = c.ToString ().ToUpper ()[0];
+ needs_caps = false;
+ }
+
+ sb.Append (c);
+ }
+
+ return sb.ToString ();
+ }
+
+ string CSType (string key, string type)
+ {
+ switch (type)
+ {
+ case "float":
+ return "double";
+ case "string":
+ return "string";
+ case "int":
+ return "int";
+ case "bool":
+ return "bool";
+ case "color":
+ return "System.Drawing.Color";
+ case "enum":
+ if (classes.Contains (key))
+ return (string) classes[key];
+ else
+ return "string";
+ default:
+ return null;
+ }
+ }
+
+ void GenerateSimpleProperty (TextWriter sw, string key, string key_str, string type, string cstype)
+ {
+ sw.WriteLine ("\t\t\tget {");
+ sw.WriteLine ("\t\t\t\treturn ({0}) client.Get ({1});", cstype, key_str);
+ sw.WriteLine ("\t\t\t}");
+
+ sw.WriteLine ("\t\t\tset {");
+ sw.WriteLine ("\t\t\t\tclient.Set ({0}, value);", key_str);
+ sw.WriteLine ("\t\t\t}");
+ }
+
+ void GenerateColorProperty (TextWriter sw, string key, string key_str, string type, string cstype)
+ {
+ sw.WriteLine ("\t\t\tget {");
+ sw.WriteLine ("\t\t\t\treturn System.Drawing.ColorTranslator.FromHtml ((string) client.Get ({0}));", key_str);
+ sw.WriteLine ("\t\t\t}");
+
+ sw.WriteLine ("\t\t\tset {");
+ sw.WriteLine ("\t\t\t\tclient.Set ({0}, System.Drawing.ColorTranslator.ToHtml (value));", key_str);
+ sw.WriteLine ("\t\t\t}");
+ }
+
+ void GenerateEnumProperty (TextWriter sw, string key, string key_str, string type, string cstype)
+ {
+ sw.WriteLine ("\t\t\tget {");
+ sw.WriteLine ("\t\t\t\ttry {");
+ sw.WriteLine ("\t\t\t\t\treturn ({0}) System.Enum.Parse (typeof ({0}), (string) client.Get ({1}));", cstype, key_str);
+ sw.WriteLine ("\t\t\t\t} catch (System.Exception e) {");
+ sw.WriteLine ("\t\t\t\t\treturn ({0}) 0;", cstype);
+ sw.WriteLine ("\t\t\t\t}");
+ sw.WriteLine ("\t\t\t}");
+
+ sw.WriteLine ("\t\t\tset {");
+ sw.WriteLine ("\t\t\t\tclient.Set ({0}, System.Enum.GetName (typeof ({1}), value));", key_str, cstype);
+ sw.WriteLine ("\t\t\t}");
+ }
+
+ void GenerateEvent (TextWriter sw, string name, string key_str)
+ {
+ sw.WriteLine ();
+ sw.WriteLine ("\t\tpublic static event GConf.NotifyEventHandler {0}Changed", name);
+ sw.WriteLine ("\t\t{");
+ sw.WriteLine ("\t\t\tadd {");
+ sw.WriteLine ("\t\t\t\tclient.AddNotify ({0}, value);", key_str);
+ sw.WriteLine ("\t\t\t}");
+ sw.WriteLine ("\t\t\tremove{");
+ sw.WriteLine ("\t\t\t\tclient.RemoveNotify ({0}, value);", key_str);
+ sw.WriteLine ("\t\t\t}");
+ sw.WriteLine ("\t\t}");
+ }
+
+ void Generate (string ns_str)
+ {
+ string path = ExtractPrefix ();
+ TextWriter sw = Console.Out;
+
+ sw.WriteLine ("namespace {0}", ns_str);
+ sw.WriteLine ("{");
+
+ sw.WriteLine ("\tpublic class Settings");
+ sw.WriteLine ("\t{");
+ sw.WriteLine ("\t\tstatic GConf.Client client = new GConf.Client ();");
+
+ GenerateEvent (sw, "", "\"" + path.Substring (0, path.Length - 1) + "\"");
+
+ foreach (string key in keys.Keys)
+ {
+ string type = (string) keys[key];
+ string cstype = CSType (key, type);
+ string key_str = "\"" + key + "\"";
+
+ if (cstype == null)
+ {
+ Console.Error.WriteLine ("Warning: unknown type \"{0}\" for key {1}", type, key);
+ continue;
+ }
+
+ sw.WriteLine ();
+ sw.WriteLine ("\t\tpublic static {0} {1}", cstype, PropertyName (key));
+ sw.WriteLine ("\t\t{");
+
+ switch (type)
+ {
+ case "color":
+ GenerateColorProperty (sw, key, key_str, type, cstype);
+ break;
+ case "enum":
+ GenerateEnumProperty (sw, key, key_str, type, cstype);
+ break;
+ default:
+ GenerateSimpleProperty (sw, key, key_str, type, cstype);
+ break;
+ }
+
+ sw.WriteLine ("\t\t}");
+
+ GenerateEvent (sw, PropertyName (key), key_str);
+ }
+
+ sw.WriteLine ("\t}");
+ sw.WriteLine ();
+ sw.WriteLine ("\tpublic class SettingKeys");
+ sw.WriteLine ("\t{");
+
+ foreach (string key in keys.Keys)
+ {
+ sw.WriteLine ("\t\tpublic static string {0}", PropertyName (key));
+ sw.WriteLine ("\t\t{");
+ sw.WriteLine ("\t\t\tget {");
+ sw.WriteLine ("\t\t\t\t return \"{0}\";", key);
+ sw.WriteLine ("\t\t\t}");
+ sw.WriteLine ("\t\t}");
+ }
+
+ sw.WriteLine ("\t}");
+ sw.WriteLine ("}");
+ }
+
+ public static void Main (string[] args)
+ {
+ if (args.Length < 2)
+ Die ("Usage: gconfsharp-schemagen namespace schemafile");
+ string ns = args[0];
+ string filename = args[1];
+
+ SchemaGen gen = new SchemaGen ();
+ gen.Parse (filename);
+ gen.Generate (ns);
+ }
+ }
+}
+
diff --git a/makefile b/makefile
index 8ab24e29d..52f7276f1 100644
--- a/makefile
+++ b/makefile
@@ -1,6 +1,6 @@
NATIVE_DIRS = glue parser
-DIRS=generator api glib pango atk gdk gtk glade art gnome gda gnomedb sample
+DIRS=generator api glib pango atk gdk gtk glade art gnome gda gnomedb gconf sample
ROOT=/cygdrive/$(subst \,/,$(subst :\,/,$(SYSTEMROOT)))
CSC=$(ROOT)/microsoft.net/framework/v1.0.3705/csc.exe
MCS=mcs
diff --git a/sample/Makefile.in b/sample/Makefile.in
index 28f5c8f10..c10a89df6 100755
--- a/sample/Makefile.in
+++ b/sample/Makefile.in
@@ -18,7 +18,8 @@ windows:
$(CSC) /unsafe /out:gtk-hello-world.exe /r:../glib/glib-sharp.dll /r:../gtk/gtk-sharp.dll /r:../gdk/gdk-sharp.dll HelloWorld.cs
$(CSC) /unsafe /out:button.exe /r:../glib/glib-sharp.dll /r:../gtk/gtk-sharp.dll ButtonApp.cs
-linux: gtk-hello-world.exe button.exe menu.exe size.exe scribble.exe treeviewdemo.exe $(GNOME_TARGETS) $(GLADE_TARGETS)
+linux: gtk-hello-world.exe button.exe menu.exe size.exe scribble.exe treeviewdemo.exe $(GNOME_TARGETS) $(GLADE_TARGETS)
+@ENABLE_GNOME_TRUE@ make -C gconf
gtk-hello-world.exe: HelloWorld.cs
$(MCS) --unsafe -o gtk-hello-world.exe $(local_paths) $(all_assemblies) HelloWorld.cs
@@ -55,11 +56,11 @@ glade-test.exe: GladeTest.cs test.glade
clean:
rm -f *.exe
+@ENABLE_GNOME_TRUE@ make -C gconf clean
unix:
@echo "'make unix' is broken for now."
install: linux
- @echo "Nothing to install."
-
-
+@ENABLE_GNOME_TRUE@ make -C gconf install
+
diff --git a/sample/gconf/Makefile b/sample/gconf/Makefile
new file mode 100644
index 000000000..30c491b2e
--- /dev/null
+++ b/sample/gconf/Makefile
@@ -0,0 +1,21 @@
+SOURCES = \
+ Settings.cs \
+ main.cs \
+ #
+
+MCS = mcs
+GCONFDIR=../../gconf
+
+all: sample.exe
+
+sample.exe: sample.schema sample.glade $(SOURCES)
+ $(MCS) /out:sample.exe $(SOURCES) /r:$(GCONFDIR)/GConf/gconf-sharp.dll /r:$(GCONFDIR)/GConf.PropertyEditors/gconf-sharp-peditors.dll /r:gtk-sharp /r:glade-sharp /r:gnome-sharp /r:System.Drawing /resource:sample.glade
+
+Settings.cs: sample.schema
+ MONO_PATH=$(top_builddir)/gconf/GConf/gconf-sharp.dll mono $(GCONFDIR)/tools/gconfsharp-schemagen.exe Sample sample.schema > Settings.cs
+
+install: all
+ GCONF_CONFIG_SOURCE="" gconftool-2 --makefile-install-rule sample.schema
+
+clean:
+ rm -f sample.exe Settings.cs
diff --git a/sample/gconf/main.cs b/sample/gconf/main.cs
new file mode 100644
index 000000000..4ea6f623e
--- /dev/null
+++ b/sample/gconf/main.cs
@@ -0,0 +1,75 @@
+using GConf;
+using GConf.PropertyEditors;
+using Gtk;
+using GtkSharp;
+using Gnome;
+using System;
+
+namespace Sample
+{
+ public enum Names
+ {
+ Roy,
+ George,
+ Bob,
+ Sally
+ }
+
+ public enum Direction
+ {
+ Up,
+ Down,
+ Left,
+ Right
+ }
+
+ class X
+ {
+ void DeleteEvent (object obj, DeleteEventArgs args)
+ {
+ Application.Quit ();
+ }
+
+ void Close (object obj, EventArgs args)
+ {
+ Application.Quit ();
+ }
+
+ static void Changed (object obj, NotifyEventArgs args)
+ {
+ Console.WriteLine ("Something changed:");
+ Console.WriteLine ("\tkey: {0}", args.Key);
+ Console.WriteLine ("\tvalue: {0}", args.Value);
+ }
+
+ static void ColorChanged (object obj, NotifyEventArgs args)
+ {
+ Console.WriteLine ("The color changed!");
+ }
+
+ public static void Main (string[] argv)
+ {
+ Program app = new Program ("sampleapp", "0.0.1", Modules.UI, argv);
+
+ Glade.XML gxml = new Glade.XML (null, "sample.glade", "preferences_dialog", null);
+ gxml.Autoconnect (new X ());
+
+ Settings.Changed += new NotifyEventHandler (Changed);
+ Settings.TheColorChanged += new NotifyEventHandler (ColorChanged);
+
+ EditorShell shell = new EditorShell (gxml);
+ shell.Add (SettingKeys.Enable, "enable");
+ shell.Add (SettingKeys.TheColor, "colorpicker");
+ shell.Add (SettingKeys.TheFilename, "fileentry");
+ shell.Add (SettingKeys.TheInteger, "spinbutton_int");
+ shell.Add (SettingKeys.TheFloat, "spinbutton_float");
+ shell.Add (SettingKeys.TheFirstEnum, "optionmenu", typeof (Names));
+ shell.Add (SettingKeys.TheSecondEnum, "radiobutton", typeof (Direction));
+ shell.Add (SettingKeys.TheText, "entry");
+
+ shell.AddGuard (SettingKeys.Enable, "table1");
+
+ app.Run ();
+ }
+ }
+}
diff --git a/sample/gconf/sample.glade b/sample/gconf/sample.glade
new file mode 100644
index 000000000..a905896fa
--- /dev/null
+++ b/sample/gconf/sample.glade
@@ -0,0 +1,572 @@
+
+
+
+
+
+
+
+ True
+ Preferences
+ GTK_WINDOW_TOPLEVEL
+ GTK_WIN_POS_NONE
+ False
+ True
+ False
+ True
+
+
+
+
+ 2
+ True
+ False
+ 0
+
+
+
+ 5
+ True
+ GTK_BUTTONBOX_END
+ 10
+
+
+
+ True
+ True
+ True
+ gtk-close
+ True
+ GTK_RELIEF_NORMAL
+ -7
+
+
+
+
+
+ 0
+ False
+ True
+ GTK_PACK_END
+
+
+
+
+
+ 4
+ True
+ False
+ 0
+
+
+
+ True
+ True
+ Enable all this junk
+ True
+ GTK_RELIEF_NORMAL
+ False
+ False
+ True
+
+
+ 0
+ False
+ False
+
+
+
+
+
+ True
+ False
+ 4
+
+
+
+
+
+
+
+
+
+
+ 0
+ False
+ False
+
+
+
+
+
+ True
+ False
+ 4
+
+
+
+
+
+
+
+
+
+
+ 0
+ True
+ True
+
+
+
+
+
+ True
+ 7
+ 2
+ False
+ 0
+ 0
+
+
+
+ True
+ Filename
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0.5
+ 0.5
+ 0
+ 0
+
+
+ 0
+ 1
+ 1
+ 2
+ fill
+
+
+
+
+
+
+ True
+ A color
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0.5
+ 0.5
+ 0
+ 0
+
+
+ 0
+ 1
+ 0
+ 1
+ fill
+
+
+
+
+
+
+ True
+ 10
+ False
+ False
+
+
+
+ True
+ True
+ True
+ True
+ 0
+
+ True
+ *
+ False
+
+
+
+
+ 1
+ 2
+ 1
+ 2
+
+
+
+
+
+
+ True
+ True
+ True
+ False
+ Pick a color
+
+
+ 1
+ 2
+ 0
+ 1
+ fill
+
+
+
+
+
+
+ True
+ An integer
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0
+ 0.5
+ 0
+ 0
+
+
+ 0
+ 1
+ 2
+ 3
+ fill
+
+
+
+
+
+
+ True
+ A float
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0
+ 0.5
+ 0
+ 0
+
+
+ 0
+ 1
+ 3
+ 4
+ fill
+
+
+
+
+
+
+ True
+ True
+ 1
+ 0
+ False
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 1 0 100 1 10 10
+
+
+ 1
+ 2
+ 2
+ 3
+
+
+
+
+
+
+ True
+ True
+ 1
+ 2
+ False
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 1 0 100 1 10 10
+
+
+ 1
+ 2
+ 3
+ 4
+
+
+
+
+
+
+ True
+ An enum
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0
+ 0.5
+ 0
+ 0
+
+
+ 0
+ 1
+ 4
+ 5
+ fill
+
+
+
+
+
+
+
+ 1
+ 2
+ 4
+ 5
+ fill
+
+
+
+
+
+
+ True
+ 0
+ 0.5
+ GTK_SHADOW_ETCHED_IN
+
+
+
+ True
+ False
+ 0
+
+
+
+ True
+ True
+ Up
+ True
+ GTK_RELIEF_NORMAL
+ False
+ False
+ True
+
+
+ 0
+ False
+ False
+
+
+
+
+
+ True
+ True
+ Down
+ True
+ GTK_RELIEF_NORMAL
+ False
+ False
+ True
+ radiobutton
+
+
+ 0
+ False
+ False
+
+
+
+
+
+ True
+ True
+ Left
+ True
+ GTK_RELIEF_NORMAL
+ False
+ False
+ True
+ radiobutton
+
+
+ 0
+ False
+ False
+
+
+
+
+
+ True
+ True
+ Right
+ True
+ GTK_RELIEF_NORMAL
+ False
+ False
+ True
+ radiobutton
+
+
+ 0
+ False
+ False
+
+
+
+
+
+
+
+ True
+ Another enum
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0.5
+ 0.5
+ 0
+ 0
+
+
+ label_item
+
+
+
+
+ 0
+ 2
+ 5
+ 6
+ fill
+
+
+
+
+
+ True
+ Some Text
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0
+ 0.5
+ 4
+ 0
+
+
+ 0
+ 1
+ 6
+ 7
+ fill
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+ 0
+
+ True
+ *
+ False
+
+
+ 1
+ 2
+ 6
+ 7
+
+
+
+
+
+ 0
+ True
+ True
+
+
+
+
+ 4
+ False
+ True
+
+
+
+
+
+
+
diff --git a/sample/gconf/sample.gladep b/sample/gconf/sample.gladep
new file mode 100644
index 000000000..ed4465497
--- /dev/null
+++ b/sample/gconf/sample.gladep
@@ -0,0 +1,7 @@
+
+
+
+
+ sample
+ sample
+
diff --git a/sample/gconf/sample.schema b/sample/gconf/sample.schema
new file mode 100644
index 000000000..54d02409e
--- /dev/null
+++ b/sample/gconf/sample.schema
@@ -0,0 +1,73 @@
+
+
+
+
+ /schemas/apps/gconfsharp/sample_app/enable
+ /apps/gconfsharp/sample_app/enable
+ sample_app
+ bool
+ true
+
+
+
+ /schemas/apps/gconfsharp/sample_app/the_color
+ /apps/gconfsharp/sample_app/the_color
+ sample_app
+ string
+ color
+
+ #0000ff
+
+
+ /schemas/apps/gconfsharp/sample_app/the_filename
+ /apps/gconfsharp/sample_app/the_filename
+ sample_app
+ string
+
+
+
+
+ /schemas/apps/gconfsharp/sample_app/the_integer
+ /apps/gconfsharp/sample_app/the_integer
+ sample_app
+ int
+
+ 37
+
+
+ /schemas/apps/gconfsharp/sample_app/the_float
+ /apps/gconfsharp/sample_app/the_float
+ sample_app
+ float
+
+ 3.14
+
+
+ /schemas/apps/gconfsharp/sample_app/the_first_enum
+ /apps/gconfsharp/sample_app/the_first_enum
+ sample_app
+ string
+ enum
+
+ Bob
+
+
+ /schemas/apps/gconfsharp/sample_app/the_second_enum
+ /apps/gconfsharp/sample_app/the_second_enum
+ sample_app
+ string
+ enum
+
+ Left
+
+
+ /schemas/apps/gconfsharp/sample_app/the_text
+ /apps/gconfsharp/sample_app/the_text
+ sample_app
+ string
+
+ Hello World
+
+
+
+