diff options
author | Lluis Sanchez <lluis@novell.com> | 2010-03-17 15:35:28 +0300 |
---|---|---|
committer | Lluis Sanchez <lluis@novell.com> | 2010-03-17 15:35:28 +0300 |
commit | 8fa37870e9cc22ffccdd494fa951b2c3807d7978 (patch) | |
tree | bda14806802947c51676c183b08f166878964c40 /main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors | |
parent | f1a8582658af8aeb0f6fa459965a2e4d0684c347 (diff) | |
parent | 585086f0ea0a49166046bb8f48d2def87907d0e0 (diff) |
Merged MD.Projects into MD.Core, and MD.Projects.Gui, MD.Core.Gui and MD.Components into MD.Ide.
svn path=/trunk/monodevelop/; revision=153730
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors')
16 files changed, 1988 insertions, 0 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/BooleanEditorCell.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/BooleanEditorCell.cs new file mode 100644 index 0000000000..747735037d --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/BooleanEditorCell.cs @@ -0,0 +1,92 @@ +// +// BooleanEditorCell.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType (typeof (bool))]
+ public class BooleanEditorCell : PropertyEditorCell + { + static int indicatorSize; + static int indicatorSpacing; + + static BooleanEditorCell () + { + Gtk.CheckButton cb = new Gtk.CheckButton (); + indicatorSize = (int) cb.StyleGetProperty ("indicator-size"); + indicatorSpacing = (int) cb.StyleGetProperty ("indicator-spacing"); + } + + public override void GetSize (int availableWidth, out int width, out int height) + { + width = 20; + height = 20; + } + + public override void Render (Gdk.Drawable window, Gdk.Rectangle bounds, Gtk.StateType state) + { + Gtk.ShadowType sh = (bool) Value ? Gtk.ShadowType.In : Gtk.ShadowType.Out; + int s = indicatorSize - 1; + if (s > bounds.Height) + s = bounds.Height; + if (s > bounds.Width) + s = bounds.Width; + Gtk.Style.PaintCheck (Container.Style, window, state, sh, bounds, Container, "checkbutton", bounds.X + indicatorSpacing - 1, bounds.Y + (bounds.Height - s)/2, s, s); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new BooleanEditor (); + } + } + + public class BooleanEditor : Gtk.CheckButton, IPropertyEditor + { + public void Initialize (EditSession session) + { + if (session.Property.PropertyType != typeof(bool)) + throw new ApplicationException ("Boolean editor does not support editing values of type " + session.Property.PropertyType); + } + + public object Value { + get { return Active; } + set { Active = (bool) value; } + } + + protected override void OnToggled () + { + base.OnToggled (); + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/CharPropertyEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/CharPropertyEditor.cs new file mode 100644 index 0000000000..69019a5214 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/CharPropertyEditor.cs @@ -0,0 +1,73 @@ +// +// CharPropertyEditor.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + + [PropertyEditorType (typeof (char))]
+ public class CharPropertyEditor : Gtk.Entry, IPropertyEditor + { + public CharPropertyEditor () + { + MaxLength = 1; + HasFrame = false; + } + + public void Initialize (EditSession session) + { + if (session.Property.PropertyType != typeof(char)) + throw new ApplicationException ("Char editor does not support editing values of type " + session.Property.PropertyType); + } + + char last; + + public object Value { + get { + if (Text.Length == 0) + return last; + else + return Text[0]; + } + set { + Text = value.ToString (); + last = (char) value; + } + } + + protected override void OnChanged () + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/CollectionEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/CollectionEditor.cs new file mode 100644 index 0000000000..067e6676e7 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/CollectionEditor.cs @@ -0,0 +1,359 @@ +/*
+ * CollectionEditor.cs - The base class for the visual type editors
+ *
+ * Part of PropertyGrid - A Gtk# widget that displays and allows
+ * editing of all of an object's public properties
+ *
+ * Authors:
+ * Michael Hutchinson <m.j.hutchinson@gmail.com>
+ *
+ * Copyright (C) 2005 Michael Hutchinson
+ *
+ * This sourcecode is licenced under The MIT License:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */ + +using System;
+using Gtk;
+using System.ComponentModel; +using System.ComponentModel.Design;
+using System.Collections;
+
+namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
+{
+ class CollectionEditor : PropertyEditorCell
+ {
+ //TODO: Support for multiple object types
+ private Type[] types;
+
+ protected override void Initialize () + { + base.Initialize (); + this.types = new Type[] { EditorManager.GetCollectionItemType (Property.PropertyType) };
+ } +
+ protected virtual Type[] NewItemTypes ()
+ {
+ return types;
+ }
+
+ public override bool DialogueEdit
+ {
+ get { return true; }
+ }
+
+ public override bool EditsReadOnlyObject {
+ get { return true; }
+ } + + protected override string GetValueText () + { + return MonoDevelop.Core.GettextCatalog.GetString ("(Collection)"); + }
+
+ public override void LaunchDialogue ()
+ {
+ //the Type in the collection
+ IList collection = (IList) Value; + string displayName = Property.DisplayName; +
+ //populate list with existing items
+ ListStore itemStore = new ListStore (typeof (object), typeof (int), typeof (string));
+ for (int i=0; i<collection.Count; i++)
+ itemStore.AppendValues(collection [i], i, collection [i].ToString ());
+
+ #region Building Dialogue
+
+ TreeView itemTree;
+ PropertyGrid grid;
+ TreeIter previousIter = TreeIter.Zero;
+
+ //dialogue and buttons
+ Dialog dialog = new Dialog () {
+ Title = displayName + " Editor",
+ Modal = true,
+ AllowGrow = true,
+ AllowShrink = true,
+ };
+ var toplevel = this.Container.Toplevel as Window;
+ if (toplevel != null)
+ dialog.TransientFor = toplevel;
+
+ dialog.AddActionWidget (new Button (Stock.Cancel), ResponseType.Cancel);
+ dialog.AddActionWidget (new Button (Stock.Ok), ResponseType.Ok);
+
+ //three columns for items, sorting, PropGrid
+ HBox hBox = new HBox ();
+ dialog.VBox.PackStart (hBox, true, true, 5);
+
+ //propGrid at end
+ grid = new PropertyGrid (base.EditorManager) {
+ CurrentObject = null,
+ WidthRequest = 200,
+ ShowHelp = false
+ };
+ hBox.PackEnd (grid, true, true, 5);
+
+ //followed by a ButtonBox
+ VBox buttonBox = new VBox ();
+ buttonBox.Spacing = 6;
+ hBox.PackEnd (buttonBox, false, false, 5);
+
+ //add/remove buttons
+ Button addButton = new Button (new Image (Stock.Add, IconSize.Button));
+ buttonBox.PackStart (addButton, false, false, 0);
+ if (types [0].IsAbstract)
+ addButton.Sensitive = false;
+ Button removeButton = new Button (new Gtk.Image (Stock.Remove, IconSize.Button));
+ buttonBox.PackStart (removeButton, false, false, 0);
+
+ //sorting buttons
+ Button upButton = new Button (new Image (Stock.GoUp, IconSize.Button));
+ buttonBox.PackStart (upButton, false, false, 0);
+ Button downButton = new Button (new Image (Stock.GoDown, IconSize.Button));
+ buttonBox.PackStart (downButton, false, false, 0);
+
+ //Third column has list (TreeView) in a ScrolledWindow
+ ScrolledWindow listScroll = new ScrolledWindow ();
+ listScroll.WidthRequest = 200;
+ listScroll.HeightRequest = 320;
+ hBox.PackStart (listScroll, false, false, 5);
+
+ itemTree = new TreeView (itemStore);
+ itemTree.Selection.Mode = SelectionMode.Single;
+ itemTree.HeadersVisible = false;
+ listScroll.AddWithViewport (itemTree);
+
+ //renderers and attribs for TreeView
+ CellRenderer rdr = new CellRendererText ();
+ itemTree.AppendColumn (new TreeViewColumn ("Index", rdr, "text", 1));
+ rdr = new CellRendererText ();
+ itemTree.AppendColumn (new TreeViewColumn ("Object", rdr, "text", 2));
+
+ #endregion
+
+ #region Events
+
+ addButton.Clicked += delegate {
+ //create the object
+ object instance = System.Activator.CreateInstance (types[0]);
+
+ //get existing selection and insert after it
+ TreeIter oldIter, newIter;
+ if (itemTree.Selection.GetSelected (out oldIter))
+ newIter = itemStore.InsertAfter (oldIter);
+ //or append if no previous selection
+ else
+ newIter = itemStore.Append ();
+ itemStore.SetValue (newIter, 0, instance);
+
+ //select, set name and update all the indices
+ itemTree.Selection.SelectIter (newIter);
+ UpdateName (itemStore, newIter);
+ UpdateIndices (itemStore);
+ };
+
+ removeButton.Clicked += delegate {
+ //get selected iter and the replacement selection
+ TreeIter iter, newSelection;
+ if (!itemTree.Selection.GetSelected (out iter))
+ return;
+
+ newSelection = iter;
+ if (!IterPrev (itemStore, ref newSelection)) {
+ newSelection = iter;
+ if (!itemStore.IterNext (ref newSelection))
+ newSelection = TreeIter.Zero;
+ }
+
+ //new selection. Zeroing previousIter prevents trying to update name of deleted iter.
+ previousIter = TreeIter.Zero;
+ if (itemStore.IterIsValid (newSelection))
+ itemTree.Selection.SelectIter (newSelection);
+
+ //and the removal and index update
+ itemStore.Remove (ref iter);
+ UpdateIndices (itemStore);
+ };
+
+ upButton.Clicked += delegate {
+ TreeIter iter, prev;
+ if (!itemTree.Selection.GetSelected (out iter))
+ return;
+
+ //get previous iter
+ prev = iter;
+ if (!IterPrev (itemStore, ref prev))
+ return;
+
+ //swap the two
+ itemStore.Swap (iter, prev);
+
+ //swap indices too
+ object prevVal = itemStore.GetValue (prev, 1);
+ object iterVal = itemStore.GetValue (iter, 1);
+ itemStore.SetValue (prev, 1, iterVal);
+ itemStore.SetValue (iter, 1, prevVal);
+ };
+
+ downButton.Clicked += delegate {
+ TreeIter iter, next;
+ if (!itemTree.Selection.GetSelected (out iter))
+ return;
+
+ //get next iter
+ next = iter;
+ if (!itemStore.IterNext (ref next))
+ return;
+
+ //swap the two
+ itemStore.Swap (iter, next);
+
+ //swap indices too
+ object nextVal = itemStore.GetValue (next, 1);
+ object iterVal = itemStore.GetValue (iter, 1);
+ itemStore.SetValue (next, 1, iterVal);
+ itemStore.SetValue (iter, 1, nextVal);
+ };
+
+ itemTree.Selection.Changed += delegate {
+ TreeIter iter;
+ if (!itemTree.Selection.GetSelected (out iter)) {
+ removeButton.Sensitive = false;
+ return;
+ }
+ removeButton.Sensitive = true;
+
+ //update grid
+ object obj = itemStore.GetValue (iter, 0);
+ grid.CurrentObject = obj;
+
+ //update previously selected iter's name
+ UpdateName (itemStore, previousIter);
+
+ //update current selection so we can update
+ //name next selection change
+ previousIter = iter;
+ };
+
+ grid.Changed += delegate {
+ TreeIter iter;
+ if (itemTree.Selection.GetSelected (out iter))
+ UpdateName (itemStore, iter);
+ };
+
+ TreeIter selectionIter;
+ removeButton.Sensitive = itemTree.Selection.GetSelected (out selectionIter);
+
+ dialog.ShowAll ();
+ grid.ShowToolbar = false;
+
+ #endregion
+
+ //show and get response
+ ResponseType response = (ResponseType) dialog.Run(); + dialog.Destroy ();
+
+ //if 'OK' put items back in collection
+ if (response == ResponseType.Ok)
+ { + DesignerTransaction tran = CreateTransaction (Instance); + object old = collection; + + try { + collection.Clear();
+ foreach (object[] o in itemStore)
+ collection.Add (o[0]); + EndTransaction (Instance, tran, old, collection, true); + } + catch { + EndTransaction (Instance, tran, old, collection, false); + throw; + }
+ }
+ } + + //This and EndTransaction are from Mono internal class System.ComponentModel.ReflectionPropertyDescriptor + // Lluis Sanchez Gual (lluis@ximian.com), (C) Novell, Inc, MIT X11 license + DesignerTransaction CreateTransaction (object obj) + { + IComponent com = obj as IComponent; + if (com == null || com.Site == null) return null; + + IDesignerHost dh = (IDesignerHost) com.Site.GetService (typeof(IDesignerHost)); + if (dh == null) return null; + + DesignerTransaction tran = dh.CreateTransaction (); + IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService)); + if (ccs != null) + ccs.OnComponentChanging (com, Property); + return tran; + } + + void EndTransaction (object obj, DesignerTransaction tran, object oldValue, object newValue, bool commit) + { + if (tran == null) return; + + if (commit) { + IComponent com = obj as IComponent; + IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService)); + if (ccs != null) + ccs.OnComponentChanged (com, Property, oldValue, newValue); + tran.Commit (); + } + else + tran.Cancel (); + }
+
+ static void UpdateIndices (ListStore itemStore)
+ {
+ TreeIter iter;
+ int i = 0;
+ if (!itemStore.GetIterFirst (out iter)) + return;
+
+ do {
+ itemStore.SetValue (iter, 1, i);
+ i++;
+ } while (itemStore.IterNext (ref iter));
+ }
+
+ static void UpdateName (ListStore itemStore, TreeIter iter)
+ {
+ if (iter.Equals (TreeIter.Zero))
+ return;
+
+ object item = itemStore.GetValue (iter, 0);
+ string name = item.ToString ();
+ if (string.IsNullOrEmpty (name))
+ name = MonoDevelop.Core.GettextCatalog.GetString ("(Empty)");;
+
+ itemStore.SetValue(iter, 2, name);
+ }
+
+ //generally useful function... why not in model already?
+ static bool IterPrev (TreeModel model, ref TreeIter iter)
+ {
+ TreePath tp = model.GetPath (iter);
+ return tp.Prev() && model.GetIter (out iter, tp);
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ColorEditorCell.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ColorEditorCell.cs new file mode 100644 index 0000000000..af94facd33 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ColorEditorCell.cs @@ -0,0 +1,115 @@ +// +// BooleanEditorCell.cs +// +// Author: +// Lluis Sanchez Gual +// Michael Hutchinson <m.j.hutchinson@gmail.com> +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType (typeof (System.Drawing.Color))]
+ public class ColorEditorCell: PropertyEditorCell + { + const int ColorBoxSize = 16; + const int ColorBoxSpacing = 3; + + public override void GetSize (int availableWidth, out int width, out int height) + { + base.GetSize (availableWidth - ColorBoxSize - ColorBoxSpacing, out width, out height); + width += ColorBoxSize + ColorBoxSpacing; + if (height < ColorBoxSize) height = ColorBoxSize; + } + + protected override string GetValueText () + { + System.Drawing.Color color = (System.Drawing.Color) Value;
+ //TODO: dropdown known color selector so this does something
+ if (color.IsKnownColor)
+ return color.Name;
+ else if (color.IsEmpty)
+ return "";
+ else
+ return String.Format("#{0:x2}{1:x2}{2:x2}", color.R, color.G, color.B);
+ } + + public override void Render (Gdk.Drawable window, Gdk.Rectangle bounds, Gtk.StateType state) + { + Gdk.GC gc = new Gdk.GC (window); + gc.RgbFgColor = GetColor (); + int yd = (bounds.Height - ColorBoxSize) / 2; + window.DrawRectangle (gc, true, bounds.X, bounds.Y + yd, ColorBoxSize - 1, ColorBoxSize - 1); + window.DrawRectangle (Container.Style.BlackGC, false, bounds.X, bounds.Y + yd, ColorBoxSize - 1, ColorBoxSize - 1); + bounds.X += ColorBoxSize + ColorBoxSpacing; + bounds.Width -= ColorBoxSize + ColorBoxSpacing; + base.Render (window, bounds, state); + } + + private Gdk.Color GetColor ()
+ {
+ System.Drawing.Color color = (System.Drawing.Color) Value;
+ //TODO: Property.Converter.ConvertTo() fails: why?
+ return new Gdk.Color (color.R, color.G, color.B);
+ }
+
+ protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new ColorEditor (); + } + } + + public class ColorEditor : Gtk.ColorButton, IPropertyEditor + { + public void Initialize (EditSession session) + { + if (session.Property.PropertyType != typeof(System.Drawing.Color)) + throw new ApplicationException ("Color editor does not support editing values of type " + session.Property.PropertyType); + } + + public object Value { + get { + int red = (int) (255 * (float) Color.Red / ushort.MaxValue);
+ int green = (int) (255 * (float) Color.Green / ushort.MaxValue);
+ int blue = (int) (255 * (float) Color.Blue / ushort.MaxValue);
+ return System.Drawing.Color.FromArgb (red, green, blue); + } + set { + System.Drawing.Color color = (System.Drawing.Color) value;
+ Color = new Gdk.Color (color.R, color.G, color.B); + } + } + + protected override void OnColorSet () + { + base.OnColorSet (); + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/DateTimeEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/DateTimeEditor.cs new file mode 100644 index 0000000000..0e2f6e1be7 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/DateTimeEditor.cs @@ -0,0 +1,98 @@ +// +// DateTimeEditorCell.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using Gtk; +using Gdk; +using System.Text; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType (typeof (DateTime))]
+ public class DateTimeEditorCell: PropertyEditorCell + { + protected override string GetValueText () + { + return ((DateTime)Value).ToLongDateString (); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new DateTimeEditor (); + } + } + + public class DateTimeEditor: Gtk.HBox, IPropertyEditor + { + Gtk.Entry entry; + DateTime time; + + public DateTimeEditor() + { + entry = new Gtk.Entry (); + entry.Changed += OnChanged; + entry.HasFrame = false; + PackStart (entry, true, true, 0); + ShowAll (); + } + + public void Initialize (EditSession session) + { + } + + public object Value { + get { return time; } + set { + time = (DateTime) value; + entry.Changed -= OnChanged; + entry.Text = time.ToString ("G"); + entry.Changed += OnChanged; + } + } + + void OnChanged (object o, EventArgs a) + { + string s = entry.Text; + + foreach (string form in formats) { + try { + time = DateTime.ParseExact (s, form, null); + if (ValueChanged != null) + ValueChanged (this, a); + break; + } catch { + } + } + } + + public event EventHandler ValueChanged; + + static string[] formats = {"u", "G", "g", "d", "T", "t"}; + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/DefaultEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/DefaultEditor.cs new file mode 100644 index 0000000000..f05387164f --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/DefaultEditor.cs @@ -0,0 +1,49 @@ +/*
+ * DefaultEditor.cs - The default visual 'editor' for types we don't have
+ * an editor for.
+ *
+ * Part of PropertyGrid - A Gtk# widget that displays and allows
+ * editing of all of an object's public properties
+ *
+ * Authors:
+ * Michael Hutchinson <m.j.hutchinson@gmail.com> + * Lluis Sanchez Gual
+ *
+ * Copyright (C) 2005 Michael Hutchinson
+ *
+ * This sourcecode is licenced under The MIT License:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+using System;
+using Gtk;
+using System.ComponentModel;
+
+namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
+{
+ public class DefaultEditor : PropertyEditorCell
+ { + protected override string GetValueMarkup () + { + return "<span foreground=\"grey\"><" + Property.PropertyType.ToString() + "></span>"; + }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EnumerationEditorCell.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EnumerationEditorCell.cs new file mode 100644 index 0000000000..f924f87716 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EnumerationEditorCell.cs @@ -0,0 +1,144 @@ +// +// EnumerationEditorCell.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System.ComponentModel; +using System.Reflection; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType(typeof(System.Enum))]
+ public class EnumerationEditorCell: PropertyEditorCell + { + protected override string GetValueText () + { + if (Value == null) + return ""; + + string val = Value.ToString (); + + // If the enum value has a Description attribute, return the description + foreach (FieldInfo f in Property.PropertyType.GetFields ()) { + if (f.Name == val) { + DescriptionAttribute att = (DescriptionAttribute) Attribute.GetCustomAttribute (f, typeof(DescriptionAttribute)); + if (att != null) + return att.Description; + else + return val; + } + } + return val; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new EnumerationEditor (); + } + } + + public class EnumerationEditor : Gtk.HBox, IPropertyEditor { + + Gtk.EventBox ebox; + Gtk.ComboBoxEntry combo; + Array values; + + public EnumerationEditor () : base (false, 0) + { + } + + public void Initialize (EditSession session) + { + PropertyDescriptor prop = session.Property; + + if (!prop.PropertyType.IsEnum) + throw new ApplicationException ("Enumeration editor does not support editing values of type " + prop.PropertyType); + + values = System.Enum.GetValues (prop.PropertyType); + Hashtable names = new Hashtable (); + foreach (FieldInfo f in prop.PropertyType.GetFields ()) { + DescriptionAttribute att = (DescriptionAttribute) Attribute.GetCustomAttribute (f, typeof(DescriptionAttribute)); + if (att != null) + names [f.Name] = att.Description; + else + names [f.Name] = f.Name; + } + + + ebox = new Gtk.EventBox (); + ebox.Show (); + PackStart (ebox, true, true, 0); + + combo = Gtk.ComboBoxEntry.NewText (); + combo.Changed += combo_Changed; + combo.Entry.IsEditable = false; + combo.Entry.CanFocus = false; + combo.Entry.HasFrame = false; + combo.Entry.HeightRequest = combo.SizeRequest ().Height; + combo.Show (); + ebox.Add (combo); + + foreach (object value in values) { + string str = prop.Converter.ConvertToString (value); + if (names.Contains (str)) + str = (string) names [str];
+ combo.AppendText (str); + } + } + + protected override void OnDestroyed () + { + base.OnDestroyed (); + ((IDisposable)this).Dispose (); + } + + void IDisposable.Dispose () + { + } + + public object Value { + get { + return values.GetValue (combo.Active); + } + set { + int i = Array.IndexOf (values, value); + if (i != -1) + combo.Active = i; + } + } + + public event EventHandler ValueChanged; + + void combo_Changed (object o, EventArgs args) + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + ebox.TooltipText = Value != null ? Value.ToString () : null; + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs new file mode 100644 index 0000000000..a07c47b6ca --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs @@ -0,0 +1,135 @@ +/*
+ * EventEditor.cs - Visual editor for Events
+ *
+ * Part of PropertyGrid - A Gtk# widget that displays and allows
+ * editing of all of an object's public properties
+ *
+ * Authors:
+ * Michael Hutchinson <m.j.hutchinson@gmail.com> + * Lluis Sanchez Gual
+ *
+ * Copyright (C) 2005 Michael Hutchinson
+ *
+ * This sourcecode is licenced under The MIT License:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+using System;
+using System.ComponentModel; +using System.ComponentModel.Design; +using System.Collections;
+using Gtk;
+
+namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
+{
+ [PropertyEditorType (typeof (Delegate), true)]
+ public class EventEditorCell : PropertyEditorCell
+ { + IEventBindingService evtBind;
+
+ protected override void Initialize () + { + IComponent comp = Instance as IComponent; + evtBind = (IEventBindingService) comp.Site.GetService (typeof (IEventBindingService)); + base.Initialize ();
+ } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + //get existing method names + ICollection IColl = evtBind.GetCompatibleMethods (evtBind.GetEvent (Property)) ; + string[] methods = new string [IColl.Count + 1]; + IColl.CopyTo (methods, 1); + + //add a suggestion + methods [0] = evtBind.CreateUniqueMethodName ((IComponent) Instance, evtBind.GetEvent (Property)); + + EventEditor combo = new EventEditor (evtBind, methods);
+
+ if (Value != null)
+ combo.Entry.Text = (string) Value;
+
+ combo.WidthRequest = 30; //Don't artificially inflate the width. It expands anyway. +
+ return combo;
+ } + + } + + class EventEditor: ComboBoxEntry, IPropertyEditor + { + bool isNull; + PropertyDescriptor prop; + IEventBindingService evtBind; + object component; + + public EventEditor (IEventBindingService evtBind, string[] ops): base (ops) + { + this.evtBind = evtBind; + } + + public void Initialize (EditSession session) + { + this.prop = session.Property; + component = session.Instance; + Entry.Destroyed += new EventHandler (entry_Changed);
+ Entry.Activated += new EventHandler (entry_Activated); + } + + public object Value { + get { + //if value was null and new value is empty, leave as null
+ if (Entry.Text.Length == 0 && isNull) + return null; + else + return Entry.Text; + } + set { + isNull = value == null; + if (isNull) + Entry.Text = ""; + else + Entry.Text = (string) value; + } + } + + protected override void OnChanged () + { + if (component == null) + return; + entry_Changed (this, null); + evtBind.ShowCode ((IComponent) component, evtBind.GetEvent (prop)); + } + + void entry_Activated (object sender, EventArgs e)
+ { + entry_Changed (sender, e); + evtBind.ShowCode ((IComponent) component, evtBind.GetEvent (prop)); + } + + void entry_Changed (object sender, EventArgs e)
+ { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } +
+ public event EventHandler ValueChanged; + }
+}
\ No newline at end of file diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs new file mode 100644 index 0000000000..83b471600a --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs @@ -0,0 +1,65 @@ +/*
+ * ExpandableObjectEditor.cs - Temporary editor until we get expandable object support in main grid
+ *
+ * Part of PropertyGrid - A Gtk# widget that displays and allows
+ * editing of all of an object's public properties
+ *
+ * Authors:
+ * Michael Hutchinson <m.j.hutchinson@gmail.com> + * Lluis Sanchez Gual
+ *
+ * Copyright (C) 2005 Michael Hutchinson
+ *
+ * This sourcecode is licenced under The MIT License:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */ + +using System;
+using Gtk;
+using System.ComponentModel; +using System.ComponentModel.Design;
+using System.Collections;
+
+namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
+{
+ class ExpandableObjectEditor : PropertyEditorCell
+ {
+ protected override string GetValueMarkup () + { + string val; + if (Property.Converter.CanConvertTo (typeof(string))) + val = Property.Converter.ConvertToString (Value); + else + val = Value != null ? Value.ToString () : ""; + + return "<b>" + GLib.Markup.EscapeText (val) + "</b>"; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, StateType state) + { + if (Property.Converter.CanConvertTo (typeof(string)) && Property.Converter.CanConvertFrom (typeof(string))) + return new TextEditor (); + else + return null; + } + + }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FlagsEditorCell.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FlagsEditorCell.cs new file mode 100644 index 0000000000..3f51ea4903 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FlagsEditorCell.cs @@ -0,0 +1,205 @@ +// +// FlagsEditorCell.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using Gtk; +using System; +using System.Collections; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors { + + public class FlagsEditorCell: PropertyEditorCell + { + protected override string GetValueText () + { + if (Value == null) + return ""; + + ulong value = Convert.ToUInt64 (Value); + Array values = System.Enum.GetValues (base.Property.PropertyType); + string txt = ""; + foreach (object val in values) { + if ((value & Convert.ToUInt64 (value)) != 0) { + if (txt.Length > 0) txt += ", "; + txt += val.ToString (); + } + } + return txt; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new FlagsEditor (); + } + } + + public class FlagsEditor : Gtk.HBox, IPropertyEditor + { + Hashtable flags; + Gtk.Entry flagsLabel; + string property; + Type propType; + Array values; + + public FlagsEditor () + { + } + + public void Initialize (EditSession session) + { + PropertyDescriptor prop = session.Property; + + if (!prop.PropertyType.IsEnum) + throw new ApplicationException ("Flags editor does not support editing values of type " + prop.PropertyType); + + Spacing = 3; + propType = prop.PropertyType; + + property = prop.Description; + if (property == null || property.Length == 0) + property = prop.Name; + + // For small enums, the editor is a list of checkboxes inside a frame + // For large enums (>5), use a selector dialog. + + values = System.Enum.GetValues (prop.PropertyType); + + if (values.Length < 6) + { + Gtk.VBox vbox = new Gtk.VBox (true, 3); + + flags = new Hashtable (); + + foreach (object value in values) { + Gtk.CheckButton check = new Gtk.CheckButton (value.ToString ()); + check.TooltipText = value.ToString (); + ulong uintVal = Convert.ToUInt64 (value); + flags[check] = uintVal; + flags[uintVal] = check; + + check.Toggled += FlagToggled; + vbox.PackStart (check, false, false, 0); + } + + Gtk.Frame frame = new Gtk.Frame (); + frame.Add (vbox); + frame.ShowAll (); + PackStart (frame, true, true, 0); + } + else + { + flagsLabel = new Gtk.Entry (); + flagsLabel.IsEditable = false; + flagsLabel.HasFrame = false; + flagsLabel.ShowAll (); + PackStart (flagsLabel, true, true, 0); + + Gtk.Button but = new Gtk.Button ("..."); + but.Clicked += OnSelectFlags; + but.ShowAll (); + PackStart (but, false, false, 0); + } + } + + protected override void OnDestroyed () + { + base.OnDestroyed (); + ((IDisposable)this).Dispose (); + } + + void IDisposable.Dispose () + { + } + + public object Value { + get { + return Enum.ToObject (propType, UIntValue); + } + set { + ulong newVal = Convert.ToUInt64 (value); + if (flagsLabel != null) { + string txt = ""; + foreach (object val in values) { + if ((newVal & Convert.ToUInt64(val)) != 0) { + if (txt.Length > 0) txt += ", "; + txt += val.ToString (); + } + } + flagsLabel.Text = txt; + UIntValue = newVal; + } + else { + for (ulong i = 1; i <= uintValue || i <= newVal; i = i << 1) { + if ((uintValue & i) != (newVal & i)) { + Gtk.CheckButton check = (Gtk.CheckButton)flags[i]; + if (check != null) + check.Active = !check.Active; + } + } + } + } + } + + public event EventHandler ValueChanged; + + ulong uintValue; + + ulong UIntValue { + get { + return uintValue; + } + set { + if (uintValue != value) { + uintValue = value; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } + } + + void FlagToggled (object o, EventArgs args) + { + Gtk.CheckButton check = (Gtk.CheckButton)o; + ulong val = (ulong)flags[o]; + + if (check.Active) + UIntValue |= val; + else + UIntValue &= ~val; + } + + void OnSelectFlags (object o, EventArgs args) + { + using (FlagsSelectorDialog dialog = new FlagsSelectorDialog (null, propType, UIntValue, property)) { + if (dialog.Run () == (int) ResponseType.Ok) { + Value = Enum.ToObject (propType, dialog.Value); + } + } + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FlagsSelectorDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FlagsSelectorDialog.cs new file mode 100644 index 0000000000..287073b5f9 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FlagsSelectorDialog.cs @@ -0,0 +1,117 @@ +// +// FlagsSelectorDialog.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + public class FlagsSelectorDialog: IDisposable + { + Gtk.TreeView treeView; + Gtk.Dialog dialog; + Gtk.ListStore store; + Gtk.Window parent; + ulong flags; + + public FlagsSelectorDialog (Gtk.Window parent, Type enumDesc, ulong flags, string title) + { + this.flags = flags; + this.parent = parent; + + Gtk.ScrolledWindow sc = new Gtk.ScrolledWindow (); + sc.HscrollbarPolicy = Gtk.PolicyType.Automatic; + sc.VscrollbarPolicy = Gtk.PolicyType.Automatic; + sc.ShadowType = Gtk.ShadowType.In; + sc.BorderWidth = 6; + + treeView = new Gtk.TreeView (); + sc.Add (treeView); + + dialog = new Gtk.Dialog (); + dialog.VBox.Add (sc); + dialog.AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel); + dialog.AddButton (Gtk.Stock.Ok, Gtk.ResponseType.Ok); + + store = new Gtk.ListStore (typeof(bool), typeof(string), typeof(ulong)); + treeView.Model = store; + treeView.HeadersVisible = false; + + Gtk.TreeViewColumn col = new Gtk.TreeViewColumn (); + + Gtk.CellRendererToggle tog = new Gtk.CellRendererToggle (); + tog.Toggled += new Gtk.ToggledHandler (OnToggled); + col.PackStart (tog, false); + col.AddAttribute (tog, "active", 0); + + Gtk.CellRendererText crt = new Gtk.CellRendererText (); + col.PackStart (crt, true); + col.AddAttribute (crt, "text", 1); + + treeView.AppendColumn (col); + + foreach (object value in System.Enum.GetValues (enumDesc)) { + ulong val = Convert.ToUInt64 (value); + store.AppendValues (((flags & val) != 0), value.ToString (), val); + } + } + + public int Run () + { + dialog.DefaultWidth = 500; + dialog.DefaultHeight = 400; + dialog.ShowAll (); + dialog.TransientFor = parent; + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + + void OnToggled (object s, Gtk.ToggledArgs args) + { + Gtk.TreeIter iter; + if (!store.GetIterFromString (out iter, args.Path)) + return; + + bool oldValue = (bool) store.GetValue (iter, 0); + ulong flag = (ulong) store.GetValue (iter, 2); + store.SetValue (iter, 0, !oldValue); + + if (oldValue) + flags &= ~flag; + else + flags |= flag; + } + + public ulong Value { + get { return flags; } + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FloatRange.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FloatRange.cs new file mode 100644 index 0000000000..8a3e7134dc --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FloatRange.cs @@ -0,0 +1,69 @@ +// +// FloatRange.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType (typeof (Double))]
+ [PropertyEditorType (typeof (Single))]
+ public class FloatRange : Gtk.SpinButton, IPropertyEditor + { + Type propType; + + public FloatRange (): base (0, 0, 0.01) + { + } + + public void Initialize (EditSession session) + { + propType = session.Property.PropertyType; + + double min, max; + + if (propType == typeof(double)) { + min = Double.MinValue; + max = Double.MaxValue; + } else if (propType == typeof(float)) { + min = float.MinValue; + max = float.MaxValue; + } else + throw new ApplicationException ("FloatRange editor does not support editing values of type " + propType); + + SetRange (min, max); + + Digits = 2; + } + + object IPropertyEditor.Value { + get { return Convert.ChangeType (base.Value, propType); } + set { base.Value = (double) Convert.ChangeType (value, typeof(double)); } + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/IntRange.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/IntRange.cs new file mode 100644 index 0000000000..ed7bc4fe74 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/IntRange.cs @@ -0,0 +1,103 @@ +// +// FlagsSelectorDialog.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType (typeof (byte))]
+ [PropertyEditorType (typeof (sbyte))]
+ [PropertyEditorType (typeof (Int16))]
+ [PropertyEditorType (typeof (UInt16))]
+ [PropertyEditorType (typeof (Int32))]
+ [PropertyEditorType (typeof (UInt32))]
+ [PropertyEditorType (typeof (Int64))]
+ [PropertyEditorType (typeof (UInt64))]
+ [PropertyEditorType (typeof (Decimal))]
+ public class IntRangeEditor : Gtk.SpinButton, IPropertyEditor + { + Type propType; + + public IntRangeEditor () : base (0, 0, 1.0) + { + this.HasFrame = false; + } + + public void Initialize (EditSession session) + { + propType = session.Property.PropertyType; + + double min, max; + + switch (Type.GetTypeCode (propType)) { + case TypeCode.Int16: + min = (double) Int16.MinValue; + max = (double) Int16.MaxValue; + break; + case TypeCode.UInt16: + min = (double) UInt16.MinValue; + max = (double) UInt16.MaxValue; + break; + case TypeCode.Int32: + min = (double) Int32.MinValue; + max = (double) Int32.MaxValue; + break; + case TypeCode.UInt32: + min = (double) UInt32.MinValue; + max = (double) UInt32.MaxValue; + break; + case TypeCode.Int64: + min = (double) Int64.MinValue; + max = (double) Int64.MaxValue; + break; + case TypeCode.UInt64: + min = (double) UInt64.MinValue; + max = (double) UInt64.MaxValue; + break; + case TypeCode.Byte: + min = (double) Byte.MinValue; + max = (double) Byte.MaxValue; + break; + case TypeCode.SByte: + min = (double) SByte.MinValue; + max = (double) SByte.MaxValue; + break; + default: + throw new ApplicationException ("IntRange editor does not support editing values of type " + session.Property.PropertyType); + } + + SetRange (min, max); + } + + object IPropertyEditor.Value { + get { return Convert.ChangeType (base.Value, propType); } + set { base.Value = (double) Convert.ChangeType (value, typeof(double)); } + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs new file mode 100644 index 0000000000..de866f675d --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs @@ -0,0 +1,193 @@ +// +// TextEditor.cs +// +// Author: +// Lluis Sanchez Gual +// Michael Hutchinson +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; + +using Gtk; +using Gdk; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType (typeof (string))]
+ public class TextEditor: Gtk.HBox, IPropertyEditor + { + EditSession session; + bool disposed; + string initialText; + Entry entry; + + public TextEditor() + { + } + + public void Initialize (EditSession session) + { + this.session = session; + + //if standard values are supported by the converter, then + //we list them in a combo + if (session.Property.Converter.GetStandardValuesSupported (session)) + { + ListStore store = new ListStore (typeof (string)); + ComboBoxEntry combo = new ComboBoxEntry (store, 0); + PackStart (combo, true, true, 0); + combo.Changed += TextChanged; + entry = combo.Entry; + entry.HeightRequest = combo.SizeRequest ().Height; + + //but if the converter doesn't allow nonstandard values, + // then we make the entry uneditable + if (session.Property.Converter.GetStandardValuesExclusive (session)) { + entry.IsEditable = false; + entry.CanFocus = false; + } + + //fill the list + foreach (object stdValue in session.Property.Converter.GetStandardValues (session)) { + store.AppendValues (session.Property.Converter.ConvertToString (session, stdValue)); + } + + //a value of "--" gets rendered as a --, if typeconverter marked with UsesDashesForSeparator + object[] atts = session.Property.Converter.GetType () + .GetCustomAttributes (typeof (StandardValuesSeparatorAttribute), true); + if (atts.Length > 0) { + string separator = ((StandardValuesSeparatorAttribute)atts[0]).Separator; + combo.RowSeparatorFunc = delegate (TreeModel model, TreeIter iter) { + return separator == ((string) model.GetValue (iter, 0)); + }; + } + } + // no standard values, so just use an entry + else { + entry = new Entry (); + PackStart (entry, true, true, 0); + } + + //either way we have an entry to play with + entry.HasFrame = false; + entry.Activated += TextChanged; + + if (ShouldShowDialogButton ()) { + Button button = new Button ("..."); + PackStart (button, false, false, 0); + button.Clicked += ButtonClicked; + } + + Spacing = 3; + ShowAll (); + } + + protected virtual bool ShouldShowDialogButton () + { + //if the object's Localizable, show a dialog, since the text's likely to be more substantial + LocalizableAttribute at = (LocalizableAttribute) session.Property.Attributes [typeof(LocalizableAttribute)]; + return (at != null && at.IsLocalizable); + } + + void ButtonClicked (object s, EventArgs a) + { + using (TextEditorDialog dlg = new TextEditorDialog ()) { + dlg.TransientFor = this.Toplevel as Gtk.Window; + dlg.Text = entry.Text; + if (dlg.Run () == (int) ResponseType.Ok) { + entry.Text = dlg.Text; + TextChanged (null, null); + } + } + } + + void TextChanged (object s, EventArgs a) + { + if (initialText == entry.Text) + return; + + bool valid = false; + if (session.Property.Converter.IsValid (session, entry.Text)) { + try { + session.Property.Converter.ConvertFromString (session, entry.Text); + initialText = entry.Text; + if (ValueChanged != null) + ValueChanged (this, a); + valid = true; + } catch { + // Invalid format + } + } + + if (valid) + entry.ModifyFg (Gtk.StateType.Normal); + else + entry.ModifyFg (Gtk.StateType.Normal, new Gdk.Color (255, 0, 0)); + } + + // Gets/Sets the value of the editor. If the editor supports + // several value types, it is the responsibility of the editor + // to return values with the expected type. + public object Value { + get { + return session.Property.Converter.ConvertFromString (session, entry.Text); + } + set { + string val = session.Property.Converter.ConvertToString (session, value); + initialText = entry.Text; + entry.Text = val ?? string.Empty; + } + } + + protected override void OnDestroyed () + { + base.OnDestroyed (); + ((IDisposable)this).Dispose (); + } + + void IDisposable.Dispose () + { + if (!disposed && initialText != entry.Text) { + TextChanged (null, null); + } + disposed = true; + } + + // To be fired when the edited value changes. + public event EventHandler ValueChanged; + } + + public class StandardValuesSeparatorAttribute : Attribute + { + string separator; + + public string Separator { get { return separator; } } + + public StandardValuesSeparatorAttribute (string separator) + { + this.separator = separator; + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditorDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditorDialog.cs new file mode 100644 index 0000000000..a43d26e6a1 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditorDialog.cs @@ -0,0 +1,78 @@ +// +// TextEditorDialog.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + public class TextEditorDialog: IDisposable + { + Gtk.TextView textview; + Gtk.Dialog dialog; + + public TextEditorDialog () + { + Gtk.ScrolledWindow sc = new Gtk.ScrolledWindow (); + sc.HscrollbarPolicy = Gtk.PolicyType.Automatic; + sc.VscrollbarPolicy = Gtk.PolicyType.Automatic; + sc.ShadowType = Gtk.ShadowType.In; + sc.BorderWidth = 6; + + textview = new Gtk.TextView (); + sc.Add (textview); + + dialog = new Gtk.Dialog (); + dialog.AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel); + dialog.AddButton (Gtk.Stock.Ok, Gtk.ResponseType.Ok); + dialog.VBox.Add (sc); + } + + public Gtk.Window TransientFor { + set { dialog.TransientFor = value; } + } + + public string Text { + get { return textview.Buffer.Text; } + set { textview.Buffer.Text = value; } + } + + public int Run () + { + dialog.DefaultWidth = 500; + dialog.DefaultHeight = 400; + dialog.ShowAll (); + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + } +} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TimeSpanEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TimeSpanEditor.cs new file mode 100644 index 0000000000..eaeb855ab3 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TimeSpanEditor.cs @@ -0,0 +1,93 @@ +// +// TimeSpanEditorCell.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using Gtk; +using Gdk; +using System.Text; +using System.ComponentModel; + +namespace MonoDevelop.Components.PropertyGrid.PropertyEditors +{ + [PropertyEditorType (typeof (TimeSpan))]
+ public class TimeSpanEditorCell: PropertyEditorCell + { + protected override string GetValueText () + { + return ((TimeSpan)Value).ToString (); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new TimeSpanEditor (); + } + } + + public class TimeSpanEditor: Gtk.HBox, IPropertyEditor + { + Gtk.Entry entry; + TimeSpan time; + + public TimeSpanEditor() + { + entry = new Gtk.Entry (); + entry.Changed += OnChanged; + entry.HasFrame = false; + PackStart (entry, true, true, 0); + ShowAll (); + } + + public void Initialize (EditSession session) + { + } + + public object Value { + get { return time; } + set { + time = (TimeSpan) value; + entry.Changed -= OnChanged; + entry.Text = time.ToString (); + entry.Changed += OnChanged; + } + } + + void OnChanged (object o, EventArgs a) + { + string s = entry.Text; + + try { + time = TimeSpan.Parse (s); + if (ValueChanged != null) + ValueChanged (this, a); + } catch { + } + } + + public event EventHandler ValueChanged; + } +} |