diff options
author | Marius Ungureanu <marius.ungureanu@xamarin.com> | 2015-03-02 12:16:53 +0300 |
---|---|---|
committer | Marius Ungureanu <marius.ungureanu@xamarin.com> | 2015-03-02 12:16:53 +0300 |
commit | b5eab357b72488cb9a31150c144d5b991f3abbbf (patch) | |
tree | 32bdc5633d5140c65133dbe5b6b1a14a22b5b1ef /main/src/core/MonoDevelop.Ide | |
parent | fe288a7f9e8bf5392a9c6180cda5e547715ffe2c (diff) | |
parent | fb49f5b17bced266244831c07c28f9fc93915cb1 (diff) |
Merge remote-tracking branch 'mono/master' into new-xm-toolbar
Diffstat (limited to 'main/src/core/MonoDevelop.Ide')
10 files changed, 291 insertions, 211 deletions
diff --git a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs index 76ef581848..df2563993f 100644 --- a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs +++ b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs @@ -16,3 +16,5 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("UnitTests")] [assembly: InternalsVisibleTo("MonoDevelop.Refactoring")] [assembly: InternalsVisibleTo("Xamarin.Ide")] +[assembly: InternalsVisibleTo("MonoDevelop.SourceEditor")] +[assembly: InternalsVisibleTo("MonoDevelop.SourceEditor2")] 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 deleted file mode 100644 index fbbbc9fbc5..0000000000 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/ExpandableObjectEditor.cs +++ /dev/null @@ -1,61 +0,0 @@ -/*
- * 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 Gtk;
-
-namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
-{
- class ExpandableObjectEditor : PropertyEditorCell
- {
- protected override string GetValueMarkup () - { - string val; - if (Property.Converter.CanConvertTo (Context, typeof(string))) - val = Property.Converter.ConvertToString (Context, 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 (Context, typeof(string)) && Property.Converter.CanConvertFrom (Context, typeof(string))) - return new TextEditor (); - else - return null; - } - - }
-}
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 index e4d9711678..87777184d3 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs @@ -36,17 +36,16 @@ using Gdk; namespace MonoDevelop.Components.PropertyGrid.PropertyEditors { [PropertyEditorType (typeof (string))]
- public class TextEditor: Gtk.HBox, IPropertyEditor + public class TextEditor: HBox, IPropertyEditor { EditSession session; bool disposed; string initialText; + object currentValue; Entry entry; - - public TextEditor() - { - } - + ComboBox combo; + ListStore store; + public void Initialize (EditSession session) { this.session = session; @@ -55,23 +54,26 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors //we list them in a combo if (session.Property.Converter.GetStandardValuesSupported (session)) { - ListStore store = new ListStore (typeof (string)); - ComboBoxEntry combo = new ComboBoxEntry (store, 0); + store = new ListStore (typeof(string), typeof(object)); + + //if converter doesn't allow nonstandard values, or can't convert from strings, don't have an entry + if (session.Property.Converter.GetStandardValuesExclusive (session) || !session.Property.Converter.CanConvertFrom (session, typeof(string))) { + combo = new ComboBox (store); + var crt = new CellRendererText (); + combo.PackStart (crt, true); + combo.AddAttribute (crt, "text", 0); + } else { + combo = new ComboBoxEntry (store, 0); + entry = ((ComboBoxEntry)combo).Entry; + entry.HeightRequest = combo.SizeRequest ().Height; + } + 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)); + store.AppendValues (session.Property.Converter.ConvertToString (session, stdValue), ObjectBox.Box (stdValue)); } //a value of "--" gets rendered as a --, if typeconverter marked with UsesDashesForSeparator @@ -79,9 +81,7 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors .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)); - }; + combo.RowSeparatorFunc = (model, iter) => separator == ((string)model.GetValue (iter, 0)); } } // no standard values, so just use an entry @@ -89,13 +89,15 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors 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 ("..."); + + //if we have an entry, fix it up a little + if (entry != null) { + entry.HasFrame = false; + entry.Activated += TextChanged; + } + + if (entry != null && ShouldShowDialogButton ()) { + var button = new Button ("..."); PackStart (button, false, false, 0); button.Clicked += ButtonClicked; } @@ -107,14 +109,14 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors 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)]; + var 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; + using (var dlg = new TextEditorDialog ()) { + dlg.TransientFor = Toplevel as Gtk.Window; dlg.Text = entry.Text; if (dlg.Run () == (int) ResponseType.Ok) { entry.Text = dlg.Text; @@ -122,44 +124,106 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors } } } + + bool GetValue (out object value) + { + //combo box, just find the active value + if (store != null && entry == null) { + TreeIter it; + if (combo.GetActiveIter (out it)) { + value = ObjectBox.Unbox (store.GetValue (it, 1)); + return true; + } + value = null; + return false; + } + + var text = entry.Text; + + // combo plus entry, try to find matching value + if (store != null) { + TreeIter it; + if (store.GetIterFirst (out it)) { + do { + if ((string)store.GetValue (it, 0) == text) { + value = ObjectBox.Unbox (store.GetValue (it, 1)); + return false; + } + } while (store.IterNext (ref it)); + } + } + + //finally, convert the value + try { + value = session.Property.Converter.ConvertFromString (session, entry.Text); + return true; + } catch { + // Invalid format + value = null; + return false; + } + } 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 + //ignore if nothing changed + if (entry != null) { + if (initialText == entry.Text) { + return; } + initialText = entry.Text; + } + + object val; + if (GetValue (out val)) { + currentValue = val; + if (ValueChanged != null) + ValueChanged (this, a); + if (entry != null) + entry.ModifyFg (StateType.Normal); + } else { + entry.ModifyFg (StateType.Normal, new Color (255, 0, 0)); } - - 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); - } + get { return currentValue; } set { - string val = session.Property.Converter.ConvertToString (session, value); - entry.Text = val ?? string.Empty; - initialText = entry.Text; + currentValue = value; + if (combo != null) { + int index; + if (FindComboValue (value, out index)) { + combo.Active = index; + initialText = combo.ActiveText; + return; + } + } + if (entry != null) { + string val = session.Property.Converter.ConvertToString (session, value); + entry.Text = val ?? string.Empty; + initialText = entry.Text; + } } } + + bool FindComboValue (object val, out int index) + { + index = 0; + TreeIter it; + if (!store.GetIterFirst (out it)) { + return false; + } + do { + if (object.Equals (ObjectBox.Unbox (store.GetValue (it, 1)), val)) { + return true; + } + index++; + } while (store.IterNext (ref it)); + return false; + } protected override void OnDestroyed () { @@ -169,19 +233,39 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors void IDisposable.Dispose () { - if (!disposed && initialText != entry.Text) { + if (!disposed && entry != null && initialText != entry.Text) { TextChanged (null, null); } disposed = true; } // To be fired when the edited value changes. - public event EventHandler ValueChanged; + public event EventHandler ValueChanged; + + //GTK# doesn't like it when you put a string in a column of type Object + class ObjectBox + { + public object Value; + public static object Box (object o) + { + if (o is string) + return new ObjectBox { Value = o }; + return o; + } + public static object Unbox (object o) + { + var b = o as ObjectBox; + if (b == null) + return o; + return b.Value; + } + } + } public class StandardValuesSeparatorAttribute : Attribute { - string separator; + readonly string separator; public string Separator { get { return separator; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs index 4282737e98..918ec9865a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/EditorManager.cs @@ -74,13 +74,13 @@ namespace MonoDevelop.Components.PropertyGrid }
}
- public PropertyEditorCell GetEditor (PropertyDescriptor pd)
+ public PropertyEditorCell GetEditor (ITypeDescriptorContext context)
{ - var cell = pd.GetEditor (typeof(PropertyEditorCell)) as PropertyEditorCell; + var cell = context.PropertyDescriptor.GetEditor (typeof(PropertyEditorCell)) as PropertyEditorCell; if (cell != null) return cell; - Type editorType = GetEditorType (pd); + Type editorType = GetEditorType (context); if (editorType == null) return Default; @@ -88,8 +88,7 @@ namespace MonoDevelop.Components.PropertyGrid if (!typeof(Gtk.Widget).IsAssignableFrom (editorType)) throw new Exception ("The property editor '" + editorType + "' must be a Gtk Widget"); return Default; - } -
+ }
if (cellCache.TryGetValue (editorType, out cell)) { return cell;
@@ -101,10 +100,12 @@ namespace MonoDevelop.Components.PropertyGrid cell = (PropertyEditorCell) Activator.CreateInstance (editorType); cellCache [editorType] = cell; return cell; - } - - public Type GetEditorType (PropertyDescriptor pd)
- { + }
+ + public Type GetEditorType (ITypeDescriptorContext context)
+ {
+ var pd = context.PropertyDescriptor;
+ //try to find a custom editor
//TODO: Find a way to provide a IWindowsFormsEditorService so this can work directly
//for now, substitute GTK#-based editors
@@ -124,8 +125,8 @@ namespace MonoDevelop.Components.PropertyGrid //TODO: find most derived type? foreach (var kvp in inheritingEditors) if (editType.IsSubclassOf (kvp.Key))
- return kvp.Value; - + return kvp.Value;
+ if (pd.PropertyType.IsEnum) { if (pd.PropertyType.IsDefined (typeof(FlagsAttribute), true))
return typeof(FlagsEditorCell); @@ -145,17 +146,7 @@ namespace MonoDevelop.Components.PropertyGrid // ((System.ComponentModel.Design.CollectionEditor)UITypeEd). //can we use a type converter with a built-in editor? - TypeConverter tc = pd.Converter; -
- //TODO: support expandable objects with custom editors - if (tc is ExpandableObjectConverter)
- return typeof(ExpandableObjectEditor); - - //This is a temporary workaround *and* and optimisation - //First, most unknown types will be most likely to convert to/from strings - //Second, System.Web.UI.WebControls/UnitConverter.cs dies on non-strings - if (tc.CanConvertFrom (typeof (string)) && tc.CanConvertTo (typeof(string))) - return typeof(TextEditor);
+ TypeConverter tc = pd.Converter;
//TODO: find best match, not first
foreach (var kvp in editors)
@@ -166,6 +157,10 @@ namespace MonoDevelop.Components.PropertyGrid if (tc.CanConvertFrom (kvp.Key) && tc.CanConvertTo (kvp.Key))
return kvp.Value;
+ if (tc.CanConvertTo (typeof(string)) || tc.GetStandardValuesSupported (context)) {
+ return typeof(TextEditor);
+ }
+
//nothing found - just display type
return null;
} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs index 87d06f4e07..c727deb565 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyEditorCell.cs @@ -27,12 +27,9 @@ // using System; -using System.Reflection; -using System.Collections; using System.ComponentModel; -using MonoDevelop.Components.PropertyGrid.PropertyEditors; -using Gtk; using Gdk; +using Gtk; using Mono.TextEditor; namespace MonoDevelop.Components.PropertyGrid @@ -41,7 +38,7 @@ namespace MonoDevelop.Components.PropertyGrid { Pango.Layout layout; ITypeDescriptorContext context; - Gtk.Widget container; + Widget container; EditorManager editorManager; public object Instance { @@ -56,7 +53,7 @@ namespace MonoDevelop.Components.PropertyGrid get { return context; } } - public Gtk.Widget Container { + public Widget Container { get { return container; } } @@ -79,9 +76,9 @@ namespace MonoDevelop.Components.PropertyGrid Initialize (); } - public EditSession StartEditing (Gdk.Rectangle cell_area, StateType state) + public EditSession StartEditing (Rectangle cellArea, StateType state) { - IPropertyEditor ed = CreateEditor (cell_area, state); + IPropertyEditor ed = CreateEditor (cellArea, state); if (ed == null) return null; return new EditSession (container, context, ed); @@ -109,12 +106,11 @@ namespace MonoDevelop.Components.PropertyGrid if (i == -1) return s; - s = s.TrimStart ('\n',' ','\t'); + s = s.TrimStart ('\n', ' ', '\t'); i = s.IndexOf ('\n'); if (i != -1) return s.Substring (0, i) + "..."; - else - return s; + return s; } public object Value { @@ -135,7 +131,7 @@ namespace MonoDevelop.Components.PropertyGrid layout.GetPixelSize (out width, out height); } - public virtual void Render (Gdk.Drawable window, Cairo.Context ctx, Gdk.Rectangle bounds, StateType state) + public virtual void Render (Drawable window, Cairo.Context ctx, Rectangle bounds, StateType state) { int w, h; layout.GetPixelSize (out w, out h); @@ -148,17 +144,17 @@ namespace MonoDevelop.Components.PropertyGrid ctx.Restore (); } - protected virtual IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, StateType state) + protected virtual IPropertyEditor CreateEditor (Rectangle cellArea, StateType state) { if (DialogueEdit && (!Property.IsReadOnly || EditsReadOnlyObject)) { return new PropertyDialogueEditor (this, context); } else { - Type editorType = editorManager.GetEditorType (Property); + Type editorType = editorManager.GetEditorType (context); if (editorType == null) return null; - IPropertyEditor editor = Activator.CreateInstance (editorType) as IPropertyEditor; + var editor = Activator.CreateInstance (editorType) as IPropertyEditor; if (editor == null) throw new Exception ("The property editor '" + editorType + "' must implement the interface IPropertyEditor"); return editor; @@ -184,19 +180,19 @@ namespace MonoDevelop.Components.PropertyGrid public virtual void LaunchDialogue ()
{
- if (DialogueEdit)
- throw new NotImplementedException();
+ if (DialogueEdit) + throw new NotImplementedException ();
} } - class DefaultPropertyEditor: Gtk.Entry, IPropertyEditor + class DefaultPropertyEditor: Entry, IPropertyEditor { PropertyDescriptor property; public void Initialize (EditSession session) { - this.property = session.Property; + property = session.Property; } public object Value { @@ -223,14 +219,14 @@ namespace MonoDevelop.Components.PropertyGrid public class EditSession : ITypeDescriptorContext { - Gtk.Widget container; + Widget container; IPropertyEditor currentEditor; bool syncing; - ITypeDescriptorContext context; + readonly ITypeDescriptorContext context; public event EventHandler Changed; - internal EditSession (Gtk.Widget container, ITypeDescriptorContext context, IPropertyEditor currentEditor) + internal EditSession (Widget container, ITypeDescriptorContext context, IPropertyEditor currentEditor) { this.context = context; this.container = container; @@ -260,7 +256,7 @@ namespace MonoDevelop.Components.PropertyGrid get { return context.PropertyDescriptor; } } - public Gtk.Widget Container { + public Widget Container { get { return container; } } @@ -324,7 +320,7 @@ namespace MonoDevelop.Components.PropertyGrid IContainer ITypeDescriptorContext.Container { get { return context.Container; } } } - class CellRendererWidget: Gtk.DrawingArea + class CellRendererWidget: DrawingArea { readonly PropertyEditorCell cell; readonly ITypeDescriptorContext context; @@ -335,7 +331,7 @@ namespace MonoDevelop.Components.PropertyGrid this.cell = cell; this.context = context; em = cell.EditorManager; - this.ModifyBg (Gtk.StateType.Normal, this.Style.White); + this.ModifyBg (StateType.Normal, this.Style.White); } protected override bool OnExposeEvent (EventExpose evnt) @@ -343,11 +339,11 @@ namespace MonoDevelop.Components.PropertyGrid bool res = base.OnExposeEvent (evnt); cell.Initialize (this, em, context); - Gdk.Rectangle rect = Allocation; + Rectangle rect = Allocation; rect.Inflate (-3, 0);// Add some margin - using (Cairo.Context ctx = Gdk.CairoHelper.Create (this.GdkWindow)) { - cell.Render (this.GdkWindow, ctx, rect, StateType.Normal); + using (Cairo.Context ctx = CairoHelper.Create (GdkWindow)) { + cell.Render (GdkWindow, ctx, rect, StateType.Normal); } return res; } @@ -367,9 +363,9 @@ namespace MonoDevelop.Components.PropertyGrid buttonLabel.Xpad = 0; buttonLabel.Ypad = 0;
buttonLabel.Markup = "<span size=\"small\">...</span>";
Button dialogueButton = new Button (buttonLabel);
- dialogueButton.Clicked += new EventHandler (DialogueButtonClicked);
+ dialogueButton.Clicked += DialogueButtonClicked;
PackStart (dialogueButton, false, false, 0); - this.ModifyBg (Gtk.StateType.Normal, this.Style.White); + this.ModifyBg (StateType.Normal, this.Style.White); ShowAll ();
} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs index e99ae2e7e2..5f5e6d9e95 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs @@ -279,7 +279,7 @@ namespace MonoDevelop.Components.PropertyGrid QueueDraw (); }
- void Populate () + internal void Populate () { PropertyDescriptorCollection properties; @@ -298,7 +298,7 @@ namespace MonoDevelop.Components.PropertyGrid } } tree.RestoreStatus ();
- } + }
void Update () { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs index e3a676ac88..f85a949c75 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs @@ -70,7 +70,7 @@ namespace MonoDevelop.Components.PropertyGrid class TableRow : ITypeDescriptorContext { - PropertyGrid parentGrid; + readonly PropertyGrid parentGrid; public TableRow (PropertyGrid parentGrid) { @@ -164,14 +164,45 @@ namespace MonoDevelop.Components.PropertyGrid EndEditing (); } - HashSet<string> expandedStatus; + Dictionary<object,List<string>> expandedStatus; + + class ReferenceEqualityComparer<T> : IEqualityComparer<T> + { + public bool Equals (T x, T y) + { + return object.ReferenceEquals (x, y); + } + public int GetHashCode (T obj) + { + return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode (obj); + } + } public void SaveStatus () { - expandedStatus = new HashSet<string> (); - foreach (var r in rows.Where (r => r.IsCategory)) - if (!r.Expanded) - expandedStatus.Add (r.Label); + //when the tree is rebuilt, there isn't a reliable way to match up new nodes to existing nodes + //since the tree can be built dynamically, and there can be multiple instances of each type. + //make a best attempt using reference equality to match objects and the name to match their properties. + expandedStatus = new Dictionary<object,List<string>>(new ReferenceEqualityComparer<object> ()); + foreach (var r in rows.Where (r => r.IsExpandable && r.Expanded)) { + object key; + string val; + if (r.IsCategory) { + key = this; + val = r.Label; + } else { + key = r.Instance; + val = r.Property.Name; + } + if (key == null) { + continue; + } + List<string> list; + if (!expandedStatus.TryGetValue (key, out list)) { + expandedStatus [key] = list = new List<string> (); + } + list.Add (val); + } } public void RestoreStatus () @@ -179,8 +210,19 @@ namespace MonoDevelop.Components.PropertyGrid if (expandedStatus == null) return; - foreach (var row in rows.Where (r => r.IsCategory)) - row.Expanded = !expandedStatus.Contains (row.Label); + foreach (var r in rows.Where (r => r.IsExpandable)) { + object key; + string val; + if (r.IsCategory) { + key = this; + val = r.Label; + } else { + key = r.Instance; + val = r.Property.Name; + } + List<string> list; + r.Expanded = expandedStatus.TryGetValue (key, out list) && list.Any (l => string.Equals (l, val)); + } expandedStatus = null; @@ -287,14 +329,17 @@ namespace MonoDevelop.Components.PropertyGrid object cob = prop.GetValue (instance); row.ChildRows = new List<TableRow> (); //TODO: should we support TypeDescriptor extensibility? how to merge with TypeConverter? - foreach (PropertyDescriptor cprop in tc.GetProperties (row, cob)) - AppendProperty (row.ChildRows, cprop, cob); + foreach (PropertyDescriptor cprop in tc.GetProperties (row, cob)) { + if (cprop.IsBrowsable) { + AppendProperty (row.ChildRows, cprop, cob); + } + } } } PropertyEditorCell GetCell (TableRow row) { - var e = editorManager.GetEditor (row.Property); + var e = editorManager.GetEditor (row); e.Initialize (this, editorManager, row); return e; } @@ -657,7 +702,7 @@ namespace MonoDevelop.Components.PropertyGrid s.AppendLine (); s.AppendLine (); s.Append (GLib.Markup.EscapeText (row.Property.Description)); - if (row.Property.Converter.CanConvertTo (typeof(string))) { + if (row.Property.Converter.CanConvertTo (row, typeof(string))) { var value = Convert.ToString (row.Property.GetValue (row.Instance)); if (!string.IsNullOrEmpty (value)) { const int chunkLength = 200; @@ -770,10 +815,21 @@ namespace MonoDevelop.Components.PropertyGrid currentEditor.CanFocus = true; currentEditor.GrabFocus (); ConnectTabEvent (currentEditor); + + var refreshAtt = row.Property.Attributes.OfType<RefreshPropertiesAttribute> ().FirstOrDefault (); + var refresh = refreshAtt == null ? RefreshProperties.None : refreshAtt.RefreshProperties; editSession.Changed += delegate { + if (refresh == RefreshProperties.Repaint) { + parentGrid.Refresh (); + } else if (refresh == RefreshProperties.All) { + parentGrid.Populate(); + } + if (Changed != null) Changed (this, EventArgs.Empty); + }; + var vs = ((Gtk.Viewport)Parent).Vadjustment; if (row.EditorBounds.Top < vs.Value) vs.Value = row.EditorBounds.Top; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs index 22273a734e..0af5978317 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs @@ -131,8 +131,11 @@ namespace MonoDevelop.Components startIn = DefaultPath; string path = ShowBrowseDialog (BrowserTitle, startIn); - if (path != null) + if (path != null) { Path = path; + // Path setter suppresses change events so fire the event ourselves + OnTextChanged (null, null); + } } void OnTextChanged (object o, EventArgs args) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs index ebe74b0b42..b0ee5718b8 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindReplace.cs @@ -108,33 +108,39 @@ namespace MonoDevelop.Ide.FindInFiles } var results = new List<SearchResult>(); - Parallel.ForEach (contents, content => { - if (monitor.IsCancelRequested)
- return; - try { - Interlocked.Increment (ref searchedFilesCount); - content.Item3.AddRange(FindAll (monitor, content.Item1, content.Item2, pattern, replacePattern, filter)); - lock (results) { - results.AddRange (content.Item3); - } - FoundMatchesCount += content.Item3.Count; - if (searchedFilesCount % step == 0) - monitor.Step (1); - } catch (Exception e) { - LoggingService.LogError("Exception during search.", e); - } - }); - - if (replacePattern != null) { + if (filter.RegexSearch && replacePattern != null) { foreach (var content in contents) { - if (content.Item3.Count == 0) - continue; + results.AddRange (RegexSearch (monitor, content.Item1, content.Item2, replacePattern, filter)); + } + } else { + Parallel.ForEach (contents, content => { + if (monitor.IsCancelRequested)
+ return; try { - content.Item1.BeginReplace (content.Item2); - Replace (content.Item1, content.Item3, replacePattern); - content.Item1.EndReplace (); + Interlocked.Increment (ref searchedFilesCount); + content.Item3.AddRange(FindAll (monitor, content.Item1, content.Item2, pattern, replacePattern, filter)); + lock (results) { + results.AddRange (content.Item3); + } + FoundMatchesCount += content.Item3.Count; + if (searchedFilesCount % step == 0) + monitor.Step (1); } catch (Exception e) { - LoggingService.LogError("Exception during replace.", e); + LoggingService.LogError("Exception during search.", e); + } + }); + + if (replacePattern != null) { + foreach (var content in contents) { + if (content.Item3.Count == 0) + continue; + try { + content.Item1.BeginReplace (content.Item2); + Replace (content.Item1, content.Item3, replacePattern); + content.Item1.EndReplace (); + } catch (Exception e) { + LoggingService.LogError("Exception during replace.", e); + } } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj index 2dd835bc7d..298d9f79f2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj @@ -2858,7 +2858,6 @@ <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\DefaultEditor.cs" /> <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\EnumerationEditorCell.cs" /> <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\EventEditor.cs" /> - <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\ExpandableObjectEditor.cs" /> <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\FlagsEditorCell.cs" /> <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\FlagsSelectorDialog.cs" /> <Compile Include="MonoDevelop.Components.PropertyGrid.Editors\FloatRange.cs" /> |