diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs index 3cdff448bce..2f745c851ff 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/Styles.cs @@ -29,6 +29,7 @@ public class PropertyPadStyle public NSColor Checkerboard0 { get; internal set; } public NSColor Checkerboard1 { get; internal set; } public NSColor ValueBlockBackgroundColor { get; internal set; } + public NSColor FrameBoxButtonBackgroundColor { get; internal set; } public NSColor TabBorderColor { get; internal set; } public NSColor PanelTabBackground { get; internal set; } } @@ -48,14 +49,16 @@ public static void LoadStyles () ToolbarBackgroundColor = NSColor.White; CellBackgroundSelectedColor = NSColor.FromRgb (0.36f, 0.54f, 0.90f); + PropertyPad = new PropertyPadStyle { Checkerboard0 = NSColor.FromRgb (255, 255, 255), Checkerboard1 = NSColor.FromRgb (217, 217, 217), PanelTabBackground = NSColor.FromRgb (248, 247, 248), TabBorderColor = NSColor.FromRgba (0, 0, 0, 25), - ValueBlockBackgroundColor = NSColor.FromRgba (0, 0, 0, 20) - }; - } else { + ValueBlockBackgroundColor = NSColor.FromRgba (0, 0, 0, 20), + FrameBoxButtonBackgroundColor = NSColor.FromRgb (0.36f, 0.54f, 0.90f) + }; + } else { CellBackgroundSelectedColor = NSColor.FromRgb (0.38f, 0.55f, 0.91f); HeaderBackgroundColor = NSColor.FromRgb (0.29f, 0.29f, 0.29f); HeaderBorderBackgroundColor = NSColor.FromRgb (0.29f, 0.29f, 0.29f); @@ -67,8 +70,9 @@ public static void LoadStyles () Checkerboard1 = NSColor.FromRgb (0, 0, 0), PanelTabBackground = NSColor.FromRgb (85, 85, 85), TabBorderColor = NSColor.FromRgba (255, 255, 255, 0), - ValueBlockBackgroundColor = NSColor.FromRgba (255, 255, 255, 25) - }; + ValueBlockBackgroundColor = NSColor.FromRgba (255, 255, 255, 25), + FrameBoxButtonBackgroundColor = NSColor.FromRgb (0.38f, 0.55f, 0.91f) + }; } } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj index 55d7a153a52..24a02a42a4b 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.csproj @@ -135,18 +135,17 @@ - - - - - - - - - + + + + + + + + - - + + diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs index 3232c62145e..488d513d117 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MacPropertyGrid.cs @@ -30,29 +30,20 @@ #if MAC -using MonoDevelop.Ide.Gui; -using MonoDevelop.Components.Commands; using System; using MonoDevelop.Components; using Xamarin.PropertyEditing; using Xamarin.PropertyEditing.Mac; -using MonoDevelop.Components.Mac; -using MonoDevelop.Ide; -using MonoDevelop.Ide.Commands; -using MonoDevelop.Components.Theming; using AppKit; using CoreGraphics; -using Foundation; namespace MonoDevelop.DesignerSupport { - class MacPropertyGrid : NSStackView, IPropertyGrid + class MacPropertyGrid : NSView, IPropertyGrid { - MacPropertyEditorPanel propertyEditorPanel; - - PropertyPadEditorProvider editorProvider; - - NSScrollView scrollView; + readonly MacPropertyEditorPanel propertyEditorPanel; + ComponentModelEditorProvider editorProvider; + ComponentModelTarget currentSelectedObject; public event EventHandler Focused; @@ -62,66 +53,39 @@ class MacPropertyGrid : NSStackView, IPropertyGrid public MacPropertyGrid () { - Orientation = NSUserInterfaceLayoutOrientation.Vertical; - Alignment = NSLayoutAttribute.Leading; - Spacing = 10; - Distribution = NSStackViewDistribution.Fill; - - propertyEditorPanel = new MacPropertyEditorPanel (new MonoDevelopHostResourceProvider ()); - - scrollView = new NSScrollView () { - HasVerticalScroller = true, - HasHorizontalScroller = false, + propertyEditorPanel = new MacPropertyEditorPanel (new MonoDevelopHostResourceProvider ()) { + ShowHeader = false }; - scrollView.WantsLayer = true; - scrollView.BackgroundColor = Styles.HeaderBackgroundColor; - scrollView.DocumentView = propertyEditorPanel; + AddSubview (propertyEditorPanel); - AddArrangedSubview (scrollView); - - propertyEditorPanel.Focused += PropertyEditorPanel_Focused; + editorProvider = new ComponentModelEditorProvider (); + editorProvider.PropertyChanged += EditorProvider_PropertyChanged; - //propertyEditorPanel.PropertiesChanged += PropertyEditorPanel_PropertiesChanged; - } - - void Widget_Focused (object o, Gtk.FocusedArgs args) - { - propertyEditorPanel.Window.MakeFirstResponder (propertyEditorPanel); + propertyEditorPanel.TargetPlatform = new TargetPlatform (editorProvider) { + AutoExpandAll = true + }; + propertyEditorPanel.ArrangeMode = PropertyArrangeMode.Category; } - void PropertyEditorPanel_Focused (object sender, EventArgs e) => Focused?.Invoke (this, EventArgs.Empty); + private void EditorProvider_PropertyChanged (object sender, EventArgs e) => + PropertyGridChanged?.Invoke (this, EventArgs.Empty); public override void SetFrameSize (CGSize newSize) { - scrollView.SetFrameSize (newSize); base.SetFrameSize (newSize); + propertyEditorPanel.SetFrameSize (newSize); } - void PropertyEditorPanel_PropertiesChanged (object sender, EventArgs e) => PropertyGridChanged?.Invoke (this, e); - public void BlankPad () { propertyEditorPanel.SelectedItems.Clear (); currentSelectedObject = null; } - public void OnPadContentShown () - { - if (editorProvider == null) { - editorProvider = new PropertyPadEditorProvider (); - propertyEditorPanel.TargetPlatform = new TargetPlatform (editorProvider) { - AutoExpandGroups = new string [] { "Build", "Misc", "NuGet", "Reference" } - }; - propertyEditorPanel.ArrangeMode = PropertyArrangeMode.Category; - } - } - - PropertyPadItem currentSelectedObject; - public void SetCurrentObject (object lastComponent, object [] propertyProviders) { if (lastComponent != null) { - var selection = new PropertyPadItem (lastComponent, propertyProviders); + var selection = new ComponentModelTarget (lastComponent, propertyProviders); if (currentSelectedObject != selection) { propertyEditorPanel.SelectedItems.Clear (); propertyEditorPanel.SelectedItems.Add (selection); @@ -130,23 +94,32 @@ public void SetCurrentObject (object lastComponent, object [] propertyProviders) } } - protected override void Dispose (bool disposing) + public void Populate (bool saveEditSession) { - if (propertyEditorPanel != null) { - propertyEditorPanel.Focused -= PropertyEditorPanel_Focused; - } - base.Dispose (disposing); + //not implemented } - public void Populate (bool saveEditSession) + public void SetToolbarProvider (Components.PropertyGrid.PropertyGrid.IToolbarProvider toolbarProvider) { //not implemented } - public void SetToolbarProvider (Components.PropertyGrid.PropertyGrid.IToolbarProvider toolbarProvider) + public void OnPadContentShown () { //not implemented } + + protected override void Dispose (bool disposing) + { + if (disposing) { + if (editorProvider != null) { + editorProvider.PropertyChanged -= EditorProvider_PropertyChanged; + editorProvider.Dispose (); + editorProvider = null; + } + } + base.Dispose (disposing); + } } class MacPropertyEditorPanel : PropertyEditorPanel diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MonoDevelopHostResourceProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MonoDevelopHostResourceProvider.cs index e730dacf417..0e67f77c01f 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MonoDevelopHostResourceProvider.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/MonoDevelopHostResourceProvider.cs @@ -60,8 +60,10 @@ public override NSColor GetNamedColor (string name) return Styles.PropertyPad.TabBorderColor; case ValueBlockBackgroundColor: return Styles.PropertyPad.ValueBlockBackgroundColor; + case FrameBoxButtonBackgroundColor: + return Styles.PropertyPad.FrameBoxButtonBackgroundColor; } - return base.GetNamedColor (name); + return NSColor.FromName (name); } } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelEditorProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelEditorProvider.cs new file mode 100644 index 00000000000..c9422c765fb --- /dev/null +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelEditorProvider.cs @@ -0,0 +1,165 @@ +// +// PropertyPadEditorProvider.cs +// +// Author: +// jmedrano +// +// Copyright (c) 2018 +// +// 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. + +#if MAC + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xamarin.PropertyEditing; + +namespace MonoDevelop.DesignerSupport +{ + class ComponentModelEditorProvider + : IEditorProvider, IDisposable + { + public event EventHandler PropertyChanged; + + public IReadOnlyDictionary KnownTypes { + get; + } = new Dictionary (); + + ComponentModelTarget target; + ComponentModelObjectEditor currentEditor; + + Task IEditorProvider.GetObjectEditorAsync(object item) + { + target = item as ComponentModelTarget; + if (target == null) { + throw new ArgumentException (string.Format ("Cannot get editor for type {0} only ComponentModelObjectEditor types are allowed", item.GetType ().Name)); + } + + if (currentEditor != null) { + currentEditor.PropertyChanged -= CurrentEditor_PropertyChanged; + } + + currentEditor = new ComponentModelObjectEditor (target); + currentEditor.PropertyChanged += CurrentEditor_PropertyChanged; + + //on each editor we store current used providers + return Task.FromResult(currentEditor); + } + + void CurrentEditor_PropertyChanged (object sender, EventArgs e) + => PropertyChanged?.Invoke (this, e); + + public Task CreateObjectAsync (ITypeInfo type) + { + var realType = GetRealType (type); + if (realType == null) + return Task.FromResult (null); + return Task.FromResult (Activator.CreateInstance (realType)); + } + + public Task> GetPropertiesForTypeAsync (ITypeInfo type) + { + var prov = target?.Providers ?? Array.Empty (); + var providers = (IReadOnlyCollection)GetPropertiesForProviders (prov); + return Task.FromResult (providers); + } + + public static IReadOnlyList GetPropertiesForProviders (object[] providers) + { + var collection = new List (); + + foreach (object propertyProvider in providers) { + //get the current properties for this provider + var currentType = propertyProvider.GetType (); + + //we want all property descriptors for this propertyProvider type + var propertyDescriptors = System.ComponentModel.TypeDescriptor.GetProperties (currentType); + + foreach (System.ComponentModel.PropertyDescriptor propertyDescriptor in propertyDescriptors) { + if (propertyDescriptor.IsBrowsable) { + var propertyInfo = CreatePropertyInfo (propertyDescriptor, propertyProvider); + collection.Add (propertyInfo); + } + } + } + return collection.AsReadOnly (); + } + + protected static DescriptorPropertyInfo CreatePropertyInfo (System.ComponentModel.PropertyDescriptor propertyDescriptor, object propertyProvider) + { + var typeDescriptorContext = new TypeDescriptorContext (propertyProvider, propertyDescriptor); + + var valueSources = ValueSources.Local | ValueSources.Default; + if (propertyDescriptor.PropertyType.IsEnum) { + if (propertyDescriptor.PropertyType.IsDefined (typeof (FlagsAttribute), inherit: false)) + return new FlagDescriptorPropertyInfo (typeDescriptorContext, valueSources); + return new EnumDescriptorPropertyInfo (typeDescriptorContext, valueSources); + } + + if (propertyDescriptor.PropertyType.IsAssignableFrom (typeof (Core.FilePath))) { + //var isDirectoryPropertyDescriptor = GetPropertyDescriptor (propertyDescriptor.GetChildProperties (), nameof (Core.FilePath.IsDirectory)); + //if (isDirectoryPropertyDescriptor != null && (bool)isDirectoryPropertyDescriptor.GetValue (propertyItem)) { + // return new DirectoryPathPropertyInfo (propertyDescriptor, PropertyProvider, valueSources); + //} + return new FilePathPropertyInfo (typeDescriptorContext, valueSources); + } + + if (HasStandardValues (propertyDescriptor)) { + var standardValues = propertyDescriptor.Converter.GetStandardValues (typeDescriptorContext); + if (standardValues.Count > 0) { + return new StringStandardValuesPropertyInfo (standardValues, typeDescriptorContext, valueSources); + } + } + + return new DescriptorPropertyInfo (typeDescriptorContext, valueSources); + } + + static bool HasStandardValues (System.ComponentModel.PropertyDescriptor propertyDescriptor) + { + if (propertyDescriptor.Converter.GetStandardValuesSupported ()) { + if (!propertyDescriptor.Converter.GetStandardValuesExclusive () && propertyDescriptor.Converter.CanConvertFrom (typeof (string))) { + return true; + } + } + return false; + } + + public ITypeInfo GetRealType (T item) + => DescriptorPropertyInfo.ToTypeInfo(item.GetType ()); + + public static Type GetRealType (ITypeInfo type) + => Type.GetType ($"{type.NameSpace}.{type.Name}, {type.Assembly.Name}"); + + public Task GetAssignableTypesAsync (ITypeInfo type, bool childTypes) + => ComponentModelObjectEditor.GetAssignableTypes (); + + public Task> GetChildrenAsync (object item) + => Task.FromResult> (Array.Empty ()); + + public void Dispose () + { + if (currentEditor != null) { + currentEditor.PropertyChanged -= CurrentEditor_PropertyChanged; + } + } + } +} + +#endif \ No newline at end of file diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelObjectEditor.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelObjectEditor.cs new file mode 100644 index 00000000000..a12c908d117 --- /dev/null +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelObjectEditor.cs @@ -0,0 +1,139 @@ +// +// PropertyPadObjectEditor.cs +// +// Author: +// jmedrano +// +// Copyright (c) 2018 +// +// 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. + +#if MAC + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using MonoDevelop.Core; +using Xamarin.PropertyEditing; + +namespace MonoDevelop.DesignerSupport +{ + class ComponentModelObjectEditor + : IObjectEditor, INameableObject + { + internal const string ComboSeparatorString = "--"; + + private readonly ComponentModelTarget propertyItem; + public string Name { get; private set; } + + static IReadOnlyList defaultHandlerList = new List ().AsReadOnly (); + static AssignableTypesResult defaultAssignableTypeResult = new AssignableTypesResult (new List ().AsReadOnly ()); + private static readonly IObjectEditor [] EmptyDirectChildren = Array.Empty (); + + private readonly List properties = new List (); + private readonly List events = new List (); + + public object Target => this.propertyItem; + + public ITypeInfo TargetType => ToTypeInfo (Target.GetType ()); + + public static ITypeInfo ToTypeInfo (Type type, bool isRelevant = true) + { + var asm = type.Assembly.GetName ().Name; + return new TypeInfo (new AssemblyInfo (asm, isRelevant), type.Namespace, type.Name); + } + + public IReadOnlyCollection Properties => this.properties; + + public IReadOnlyDictionary KnownProperties => null; + + public IObjectEditor Parent => null; + + public IReadOnlyList DirectChildren => EmptyDirectChildren; + public IReadOnlyCollection Events => this.events; + + internal static Task GetAssignableTypes () + => Task.FromResult (defaultAssignableTypeResult); + + public event EventHandler PropertyChanged; + + public ComponentModelObjectEditor (ComponentModelTarget propertyItem) + { + this.propertyItem = propertyItem; + this.properties.AddRange (ComponentModelEditorProvider.GetPropertiesForProviders (propertyItem.Providers)); + } + + public Task GetAssignableTypesAsync (IPropertyInfo property, bool childTypes) + => Task.FromResult(new AssignableTypesResult (Array.Empty ())); + + public Task> GetHandlersAsync (IEventInfo ev) => Task.FromResult(defaultHandlerList); + + public Task GetNameAsync () => Task.FromResult (Name); + + public Task> GetPropertyVariantsAsync (IPropertyInfo property) + => Task.FromResult> (Array.Empty ()); + + public Task> GetValueAsync (IPropertyInfo property, PropertyVariation variations = null) + { + if (property == null) + return Task.FromException> (new ArgumentNullException (nameof (property))); + + if (!(property is DescriptorPropertyInfo propertyInfo)) { + return Task.FromException> (new ArgumentException ($"Property should be a {nameof (DescriptorPropertyInfo)}", nameof (property))); + } + + T value = propertyInfo.GetValue (this); + var valueInfo = new ValueInfo { + Value = value, + Source = ValueSource.Local, + }; + return Task.FromResult (valueInfo); + } + + public Task RemovePropertyVariantAsync (IPropertyInfo property, PropertyVariation variant) => Task.CompletedTask; + + public Task SetNameAsync (string name) + { + Name = name; + return Task.CompletedTask; + } + + public Task SetValueAsync (IPropertyInfo propertyInfo, ValueInfo value, PropertyVariation variations = null) + { + try { + if (propertyInfo == null) + return Task.FromException (new ArgumentNullException (nameof (propertyInfo))); + + if (propertyInfo is DescriptorPropertyInfo info && info.CanWrite) { + info.SetValue (this, value.Value); + RaisePropertyChanged (info); + } else { + return Task.FromException (new ArgumentException ($"Property should be a writeable {nameof (DescriptorPropertyInfo)}.", nameof (propertyInfo))); + } + } catch (Exception ex) { + LoggingService.LogError ("Error setting the value", ex); + } + return Task.CompletedTask; + } + + protected void RaisePropertyChanged (IPropertyInfo property) => PropertyChanged?.Invoke (this, new EditorPropertyChangedEventArgs (property)); + } +} + +#endif \ No newline at end of file diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyProviderTypeInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelTarget.cs similarity index 70% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyProviderTypeInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelTarget.cs index 2ac8c97afea..7614cb468df 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyProviderTypeInfo.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/ComponentModelTarget.cs @@ -1,5 +1,5 @@ -// -// DescriptorPropertyInfo.cs +// +// PropertyPadItem.cs // // Author: // jmedrano @@ -26,21 +26,21 @@ #if MAC -using Xamarin.PropertyEditing; -using System.ComponentModel; - namespace MonoDevelop.DesignerSupport { - class PropertyProviderTypeInfo : TypeInfo + /// + /// This component model target allows include additional providers to handle properties + /// + class ComponentModelTarget { - public object PropertyProvider { get; } - public PropertyDescriptor PropertyDescriptor { get; } - - public PropertyProviderTypeInfo (PropertyDescriptor propertyDescriptor, object propertyProvider, IAssemblyInfo assembly, string nameSpace, string name) : base (assembly, nameSpace, name) + public ComponentModelTarget (object target, object [] providers) { - PropertyDescriptor = propertyDescriptor; - PropertyProvider = propertyProvider; + Target = target; + Providers = providers; } + + public object Target { get; } + public object[] Providers { get; } } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyDescriptorEventInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyDescriptorEventInfo.cs similarity index 100% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyDescriptorEventInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyDescriptorEventInfo.cs diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DescriptorPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/DescriptorPropertyInfo.cs similarity index 54% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DescriptorPropertyInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/DescriptorPropertyInfo.cs index 033470859b3..be7ead2146c 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DescriptorPropertyInfo.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/DescriptorPropertyInfo.cs @@ -39,20 +39,52 @@ namespace MonoDevelop.DesignerSupport { + class TypeDescriptorContext : ITypeDescriptorContext + { + public TypeDescriptorContext (object propertyProvider, PropertyDescriptor propertyDescriptor) + { + Instance = propertyProvider; + PropertyDescriptor = propertyDescriptor; + } + + public IContainer Container => null; + + public object Instance { get; } + + public PropertyDescriptor PropertyDescriptor { get; private set; } + + public object GetService (Type serviceType) + { + return null; + } + + public void OnComponentChanged () + { + //TODO ITypeDescriptorContext.OnComponentChanging + } + + public bool OnComponentChanging () + { + //TODO ITypeDescriptorContext.OnComponentChanging + return true; + } + } + class DescriptorPropertyInfo : IPropertyInfo, IEquatable { - public PropertyDescriptor PropertyDescriptor { get; private set; } - public object PropertyProvider { get; private set; } - readonly ValueSources valueSources; - static readonly IAvailabilityConstraint [] EmptyConstraints = new IAvailabilityConstraint [0]; - static readonly PropertyVariationOption [] EmptyVariationOptions = new PropertyVariationOption [0]; + public object PropertyProvider => typeDescriptorContext.Instance; + protected readonly TypeDescriptorContext typeDescriptorContext; + + public PropertyDescriptor PropertyDescriptor => typeDescriptorContext.PropertyDescriptor; - public DescriptorPropertyInfo (PropertyDescriptor propertyInfo, object propertyProvider, ValueSources valueSources) + static readonly IAvailabilityConstraint [] EmptyConstraints = Array.Empty (); + static readonly PropertyVariationOption [] EmptyVariationOptions = Array.Empty (); + + public DescriptorPropertyInfo (TypeDescriptorContext typeDescriptorContext, ValueSources valueSources) { - this.PropertyDescriptor = propertyInfo; - this.PropertyProvider = propertyProvider; - this.valueSources = valueSources; + this.typeDescriptorContext = typeDescriptorContext; + this.ValueSources = valueSources; } public string Name => PropertyDescriptor.DisplayName; @@ -61,13 +93,13 @@ public DescriptorPropertyInfo (PropertyDescriptor propertyInfo, object propertyP public virtual Type Type => PropertyDescriptor.PropertyType; - public ITypeInfo RealType => ToTypeInfo (PropertyDescriptor, PropertyProvider, Type); + public ITypeInfo RealType => ToTypeInfo (Type); public string Category => PropertyDescriptor.Category; public bool CanWrite => !PropertyDescriptor.IsReadOnly; - public ValueSources ValueSources => valueSources; + public ValueSources ValueSources { get; } public IReadOnlyList Variations => EmptyVariationOptions; @@ -105,50 +137,59 @@ public static Type GetCollectionItemType (Type colType) return null; } - public static ITypeInfo ToTypeInfo (PropertyDescriptor propertyDescriptor, object propertyProvider, Type type, bool isRelevant = true) + public static ITypeInfo ToTypeInfo (Type type, bool isRelevant = true) { var asm = type.Assembly.GetName ().Name; - return new PropertyProviderTypeInfo (propertyDescriptor, propertyProvider, new AssemblyInfo (asm, isRelevant), type.Namespace, type.Name); + return new Xamarin.PropertyEditing.TypeInfo (new AssemblyInfo (asm, isRelevant), type.Namespace, type.Name); } - const string ErrorOnGetValueMessage = "Error in GetValueAsync using property descriptor converter"; - protected void LogGetValueAsyncError (Exception ex) => LoggingService.LogError (ErrorOnGetValueMessage, ex); - - internal virtual Task GetValueAsync (object target) + internal virtual T GetValue (object target) { + T converted = default; object value = null; - + bool canConvert = false; try { value = PropertyDescriptor.GetValue (PropertyProvider); - TypeConverter tc = PropertyDescriptor.Converter; - if (tc.CanConvertTo (typeof (T))) { - value = tc.ConvertTo (value, typeof (T)); + var tc = PropertyDescriptor.Converter; + canConvert = tc.CanConvertTo (typeof (T)); + if (canConvert) { + converted = (T)tc.ConvertTo (value, typeof (T)); + } else { + converted = (T)value; } - return Task.FromResult ((T)value); } catch (Exception ex) { - LogGetValueAsyncError (ex); + LogInternalError ($"Error trying to get and convert value:'{value}' canconvert: {canConvert} T:{typeof (T).FullName} ", ex); } + return converted; + } - T converted = default; + internal virtual void SetValue (object target, T value) + { try { - if (value != null && !(value is T)) { - if (typeof (T) == typeof (string)) { - value = value.ToString (); - } else { - value = Convert.ChangeType (value, typeof (T)); - } + + var currentType = typeof (T) ; + + //TODO: Proppy in Boolean types uses bool? to handle it, but this will fail using converters + //thats because we need ensure take the underlying type + currentType = Nullable.GetUnderlyingType (currentType) ?? currentType; + object notNulleableValue = Convert.ChangeType (value, currentType); + + var tc = PropertyDescriptor.Converter; + if (tc.CanConvertFrom (currentType)) { + var result = tc.ConvertFrom (notNulleableValue); + PropertyDescriptor.SetValue (PropertyProvider, result); + } else { + notNulleableValue = Convert.ChangeType (value, this.Type); + PropertyDescriptor.SetValue (PropertyProvider, notNulleableValue); } - return Task.FromResult ((T)value); } catch (Exception ex) { - LogGetValueAsyncError (ex); + LogInternalError ($"Error trying to set and convert a value: {value} T:{typeof (T).FullName}", ex); } - return Task.FromResult (converted); } - internal virtual void SetValue (object target, T value) - { - PropertyDescriptor.SetValue (PropertyProvider, value); - } + protected void LogInternalError (string message, Exception ex = null) => + LoggingService.LogInternalError (string.Format ("[{0}][{1}] {2}", Name, GetType ().Name, message), ex); + } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DirectoryPathPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/DirectoryPathPropertyInfo.cs similarity index 100% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/DirectoryPathPropertyInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/DirectoryPathPropertyInfo.cs diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/EnumDescriptorPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/EnumDescriptorPropertyInfo.cs similarity index 61% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/EnumDescriptorPropertyInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/EnumDescriptorPropertyInfo.cs index dc5a6c03f38..f1140494dfa 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/EnumDescriptorPropertyInfo.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/EnumDescriptorPropertyInfo.cs @@ -33,18 +33,20 @@ using System.Collections; using System.Threading.Tasks; using MonoDevelop.Core; +using System.Linq; namespace MonoDevelop.DesignerSupport { class EnumDescriptorPropertyInfo - : DescriptorPropertyInfo, IHavePredefinedValues //, IValidator>, ICoerce> + : DescriptorPropertyInfo, IHavePredefinedValues { Hashtable names = new Hashtable (); Array values; - public EnumDescriptorPropertyInfo (PropertyDescriptor propertyDescriptor, object propertyProvider, ValueSources valueSources) - : base (propertyDescriptor, propertyProvider, valueSources) + public EnumDescriptorPropertyInfo (TypeDescriptorContext typeDescriptorContext, ValueSources valueSources) + : base (typeDescriptorContext, valueSources) { values = Enum.GetValues (PropertyDescriptor.PropertyType); + var fields = PropertyDescriptor.PropertyType.GetFields (); names = new Hashtable (); @@ -66,38 +68,60 @@ public EnumDescriptorPropertyInfo (PropertyDescriptor propertyDescriptor, object } } - internal override void SetValue (object target, T value) + static int GetIndexOfValue (Array values, string value) { - var tc = PropertyDescriptor.Converter; - if (tc.CanConvertFrom (typeof (T))) { - if (int.TryParse ((string)(object)value, out var index)) { - PropertyDescriptor.SetValue (PropertyProvider, values.GetValue (index)); - } else { - throw new Exception (string.Format ("Error in SetValue parsing {0} as integer in {1} (enum descriptor)", value, PropertyDescriptor.DisplayName)); + for (int i = 0; i < values.Length; i++) { + if (values.GetValue (i).ToString ().Equals (value)) { + return i; } } + return -1; } - internal override Task GetValueAsync (object target) + internal override T GetValue (object target) { //we need set the index of the selected item T result = default; try { - TypeConverter tc = PropertyDescriptor.Converter; - object cob = PropertyDescriptor.GetValue (PropertyProvider); - var index = Array.IndexOf (values, cob); + result = base.GetValue (target); + string cob = result as string; + var index = GetIndexOfValue (values, cob); if (index > -1) { - result = (T)(object) index.ToString (); + result = (T)(object)index.ToString (); + } else { + throw new InvalidCastException ($"Error in GetValueAsync parsing {index} as integer"); + } + } catch (Exception ex) { + LogInternalError ($"Error trying to get and convert a value T:{typeof (T).FullName}", ex); + } + return result; + } + + internal override void SetValue (object target, T value) + { + if (EqualityComparer.Default.Equals (value, default)) { + var defaultValue = PropertyDescriptor.GetValue (PropertyProvider); + PropertyDescriptor.SetValue (PropertyProvider, defaultValue); + return; + } + + try { + var intValue = (int)Convert.ChangeType (value, typeof (int)); + var objValue = values.GetValue (intValue); + var tc = PropertyDescriptor.Converter; + if (tc.CanConvertFrom (objValue.GetType ())) { + var result = tc.ConvertFrom (objValue); + PropertyDescriptor.SetValue (PropertyProvider, result); } else { - LoggingService.LogError ("Error in GetValueAsync parsing {0} as integer in {1} (enum descriptor)", index, PropertyDescriptor.DisplayName); + PropertyDescriptor.SetValue (PropertyProvider, objValue); } } catch (Exception ex) { - LogGetValueAsyncError (ex); + LogInternalError ($"Error trying to set and convert a value: {value} T:{typeof (T).FullName}... trying to use base converter...", ex); + base.SetValue (target, value); } - return Task.FromResult (result); } - public bool IsConstrainedToPredefined => false; + public bool IsConstrainedToPredefined => true; public bool IsValueCombinable { get; diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/FilePathPropertyInfo.cs similarity index 60% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/FilePathPropertyInfo.cs index 393416929af..c77542789c2 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FilePathPropertyInfo.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/FilePathPropertyInfo.cs @@ -36,7 +36,7 @@ namespace MonoDevelop.DesignerSupport class FilePathPropertyInfo : DescriptorPropertyInfo, IEquatable { - public FilePathPropertyInfo (PropertyDescriptor propertyInfo, object propertyProvider, ValueSources valueSources) : base (propertyInfo, propertyProvider, valueSources) + public FilePathPropertyInfo (TypeDescriptorContext typeDescriptorContext, ValueSources valueSources) : base (typeDescriptorContext, valueSources) { } @@ -44,21 +44,29 @@ public FilePathPropertyInfo (PropertyDescriptor propertyInfo, object propertyPro internal override void SetValue (object target, T value) { - if (value is Xamarin.PropertyEditing.Common.FilePath filePath) { - PropertyDescriptor.SetValue (PropertyProvider, new MonoDevelop.Core.FilePath (filePath.Source)); - } else { - throw new Exception (string.Format ("Value: {0} of type {1} is not a DirectoryPath", value, value.GetType ())); + try { + if (value is Xamarin.PropertyEditing.Common.FilePath filePath) { + PropertyDescriptor.SetValue (PropertyProvider, new MonoDevelop.Core.FilePath (filePath.Source)); + } else { + throw new Exception (string.Format ("Value: {0} of type {1} is not a DirectoryPath", value, value.GetType ())); + } + } catch (Exception ex) { + LogInternalError ($"Error trying to get and convert value:'{value}' T:{typeof (T).FullName} ", ex); } } - internal override Task GetValueAsync (object target) + internal override T GetValue (object target) { - if (target is MonoDevelop.Core.FilePath directoryPath) { - T result = (T)(object)new Xamarin.PropertyEditing.Common.FilePath (directoryPath.FullPath); - return Task.FromResult (result); + try { + var currentObject = PropertyDescriptor.GetValue (PropertyProvider); + if (currentObject is Core.FilePath filePath) { + T result = (T)(object)new Xamarin.PropertyEditing.Common.FilePath (filePath.FullPath); + return result; + } + } catch (Exception ex) { + LogInternalError ($"Error trying to get and convert value:'{target}' T:{typeof (T).FullName} ", ex); } - Core.LoggingService.LogWarning ("Value: {0} of type {1} is not a DirectoryPath", target, target.GetType ()); - return base.GetValueAsync (target); + return base.GetValue (target); } } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FlagDescriptorPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/FlagDescriptorPropertyInfo.cs similarity index 55% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FlagDescriptorPropertyInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/FlagDescriptorPropertyInfo.cs index d485704ca87..3bfad421846 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/FlagDescriptorPropertyInfo.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/FlagDescriptorPropertyInfo.cs @@ -28,9 +28,7 @@ using Xamarin.PropertyEditing; using System.ComponentModel; -using System.Threading.Tasks; using System; -using System.Collections; using System.Collections.Generic; namespace MonoDevelop.DesignerSupport @@ -38,10 +36,14 @@ namespace MonoDevelop.DesignerSupport class FlagDescriptorPropertyInfo : DescriptorPropertyInfo, IHavePredefinedValues { - public FlagDescriptorPropertyInfo (PropertyDescriptor propertyDescriptor, object propertyProvider, ValueSources valueSources) : base (propertyDescriptor, propertyProvider, valueSources) + Array elements; + public FlagDescriptorPropertyInfo (TypeDescriptorContext typeDescriptorContext, ValueSources valueSources) : base (typeDescriptorContext, valueSources) { IsValueCombinable = true; - foreach (object value in System.Enum.GetValues (propertyDescriptor.PropertyType)) { + + elements = Enum.GetValues (typeDescriptorContext.PropertyDescriptor.PropertyType); + + foreach (object value in elements) { ulong uintVal = Convert.ToUInt64 (value); predefinedValues.Add (value.ToString (), uintVal.ToString ()); } @@ -49,32 +51,47 @@ public FlagDescriptorPropertyInfo (PropertyDescriptor propertyDescriptor, object internal override void SetValue (object target, T value) { - var selectedValues = (System.String []) (object)value; - ulong result = default; - foreach (var selectedValue in selectedValues) { - result += Convert.ToUInt64 (selectedValue); + if (EqualityComparer.Default.Equals (value, default)) { + var defaultValue = PropertyDescriptor.GetValue (PropertyProvider); + PropertyDescriptor.SetValue (PropertyProvider, defaultValue); + return; + } + + try { + var selectedValues = (System.String []) (object)value; + ulong result = default; + foreach (var selectedValue in selectedValues) { + result += Convert.ToUInt64 (selectedValue); + } + PropertyDescriptor.SetValue (PropertyProvider, Enum.ToObject (PropertyDescriptor.PropertyType, result)); + } catch (Exception ex) { + LogInternalError ($"Error trying to set value: {value}", ex); } - PropertyDescriptor.SetValue (PropertyProvider, Enum.ToObject (PropertyDescriptor.PropertyType, result)); } - internal override Task GetValueAsync (object target) + internal override T GetValue (object target) { - //we need set the index of the selected item - try { - var myValue = (Enum)target; - var result = new List (); - foreach (Enum item in Enum.GetValues (target.GetType ())) - { - if (myValue.HasFlag (item)) { - ulong uintVal = Convert.ToUInt64 (item); - result.Add (uintVal.ToString ()); + if (typeof (T) == typeof (IReadOnlyList)) { + //we need set the index of the selected item + try { + var currentObject = PropertyDescriptor.GetValue (PropertyProvider); + var currentEnum = (Enum)currentObject; + var result = new List (); + foreach (Enum item in elements) { + if (currentEnum.HasFlag (item)) { + ulong uintVal = Convert.ToUInt64 (item); + result.Add (uintVal.ToString ()); + } } + + return (T)(object)result.AsReadOnly (); + } catch (Exception ex) { + LogInternalError ($"Error trying to get values from a Enum", ex); } - return Task.FromResult ((T)(object)result); - } catch (Exception ex) { - LogGetValueAsyncError (ex); } - return Task.FromResult (default); + + var baseValue = base.GetValue (target); + return baseValue; } public bool IsConstrainedToPredefined => true; diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/StringStandardValuesPropertyInfo.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/StringStandardValuesPropertyInfo.cs similarity index 51% rename from main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/StringStandardValuesPropertyInfo.cs rename to main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/StringStandardValuesPropertyInfo.cs index 6f1eb5d7247..bbc092153d0 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyInfo/StringStandardValuesPropertyInfo.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditor/PropertyInfo/StringStandardValuesPropertyInfo.cs @@ -29,28 +29,65 @@ using Xamarin.PropertyEditing; using System.ComponentModel; using System.Collections.Generic; +using System.Threading.Tasks; +using System; +using MonoDevelop.Core; +using System.Linq; namespace MonoDevelop.DesignerSupport { class StringStandardValuesPropertyInfo : DescriptorPropertyInfo, IHavePredefinedValues { - public StringStandardValuesPropertyInfo (PropertyDescriptor propertyDescriptor, object propertyProvider, ValueSources valueSources) : base (propertyDescriptor, propertyProvider, valueSources) + readonly Dictionary standardValues = new Dictionary (); + + public StringStandardValuesPropertyInfo (TypeConverter.StandardValuesCollection standardValuesCollection, TypeDescriptorContext typeDescriptorContext, ValueSources valueSources) : base (typeDescriptorContext, valueSources) { - foreach (object stdValue in PropertyDescriptor.Converter.GetStandardValues ()) { + foreach (object stdValue in standardValuesCollection) { var value = PropertyDescriptor.Converter.ConvertToString (stdValue); + if (value == ComponentModelObjectEditor.ComboSeparatorString) { + //TODO: we need implement in proppy a way to allow separators + continue; + } + standardValues.Add (value, stdValue); predefinedValues.Add (value, value); } } - public bool IsConstrainedToPredefined => false; - - public bool IsValueCombinable { - get; - } + public bool IsConstrainedToPredefined => true; + public bool IsValueCombinable { get; } protected Dictionary predefinedValues = new Dictionary (); public IReadOnlyDictionary PredefinedValues => predefinedValues; + + internal override TValue GetValue (object target) + { + return base.GetValue (target); + } + + internal override void SetValue (object target, T value) + { + if (EqualityComparer.Default.Equals (value, default)) { + var defaultValue = PropertyDescriptor.GetValue (PropertyProvider); + PropertyDescriptor.SetValue (PropertyProvider, defaultValue); + return; + } + + if (value is string textValue) { + try { + object objValue; + if (standardValues.TryGetValue (textValue,out objValue)) { + PropertyDescriptor.SetValue (PropertyProvider, objValue); + } else { + throw new Exception ("Value selected doesn't exists in the current standardValuesCollection"); + } + } catch (Exception ex) { + LogInternalError ($"Error trying to set and convert a value: {value} T:{typeof (T).FullName}", ex); + } + } else { + base.SetValue (target, value); + } + } } } diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs deleted file mode 100644 index 8752869230a..00000000000 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadEditorProvider.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// PropertyPadEditorProvider.cs -// -// Author: -// jmedrano -// -// Copyright (c) 2018 -// -// 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. - -#if MAC - -using System.Linq; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Xamarin.PropertyEditing; -using Xamarin.PropertyEditing.Common; -using Xamarin.PropertyEditing.Reflection; -using System.Reflection; -using System.ComponentModel; - -namespace MonoDevelop.DesignerSupport -{ - class PropertyPadEditorProvider - : IEditorProvider - { - public IReadOnlyDictionary KnownTypes { - get; - } = new Dictionary (); - - public Task GetObjectEditorAsync (object item) - { - if (item is PropertyPadItem propertyPadItem) { - return Task.FromResult (new PropertyPadObjectEditor (propertyPadItem)); - } - return Task.FromResult (null); - } - - public Task CreateObjectAsync (ITypeInfo type) - { - var realType = Type.GetType ($"{type.NameSpace}.{type.Name}, {type.Assembly.Name}"); - if (realType == null) - return Task.FromResult (null); - return Task.FromResult (Activator.CreateInstance (realType)); - } - - public Task> GetPropertiesForTypeAsync (ITypeInfo type) - => Task.FromResult> (new List ()); - - public Task GetAssignableTypesAsync (ITypeInfo type, bool childTypes) - => Task.FromResult (new AssignableTypesResult (new List ())); - - public Task> GetChildrenAsync (object item) - => Task.FromResult> (Array.Empty ()); - } -} - -#endif \ No newline at end of file diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadItem.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadItem.cs deleted file mode 100644 index ecd5235fd8f..00000000000 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadItem.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// PropertyPadItem.cs -// -// Author: -// jmedrano -// -// Copyright (c) 2018 -// -// 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. - -#if MAC - -using System; -using System.Threading.Tasks; -using MonoDevelop.Core; -using Xamarin.PropertyEditing; - -namespace MonoDevelop.DesignerSupport -{ - class PropertyPadItem - { - public PropertyPadItem (object target, object [] providers) - { - Target = target; - Providers = providers; - } - - public object Target { get; } - public object[] Providers { get; } - - public async Task> GetPropertyValueInfoAsProppyType (DescriptorPropertyInfo propertyInfo) - { - T value = await propertyInfo.GetValueAsync (this); - return new ValueInfo { - Value = value, - Source = ValueSource.Local, - //ValueDescriptor = valueInfoString.ValueDescriptor, - //CustomExpression = valueString - }; - } - - public void SetPropertyValueInfoAsProppyType (DescriptorPropertyInfo info, ValueInfo value, PropertyVariation variations) - { - try { - info.SetValue (this, value.Value); - } catch (Exception ex) { - LoggingService.LogError ("Error setting the value", ex); - } - } - } -} - -#endif \ No newline at end of file diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs deleted file mode 100644 index c272b78a4a4..00000000000 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/NativePropertyEditors/PropertyPadObjectEditor.cs +++ /dev/null @@ -1,212 +0,0 @@ -// -// PropertyPadObjectEditor.cs -// -// Author: -// jmedrano -// -// Copyright (c) 2018 -// -// 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. - -#if MAC - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Xamarin.PropertyEditing; -using Xamarin.PropertyEditing.Reflection; -using System.Linq; -using System.ComponentModel; -using System.Collections; -using MonoDevelop.Core; - -namespace MonoDevelop.DesignerSupport -{ - class PropertyPadObjectEditor - : IObjectEditor, INameableObject - { - private readonly PropertyPadItem propertyItem; - public string Name { - get; - private set; - } - - private readonly List properties = new List (); - private static readonly IObjectEditor [] EmptyDirectChildren = new IObjectEditor [0]; - private readonly List events = new List (); - - public object Target => this.propertyItem; - - public ITypeInfo TargetType => ToTypeInfo (Target.GetType ()); - - public static ITypeInfo ToTypeInfo (Type type, bool isRelevant = true) - { - var asm = type.Assembly.GetName ().Name; - return new TypeInfo (new AssemblyInfo (asm, isRelevant), type.Namespace, type.Name); - } - - public IReadOnlyCollection Properties => this.properties; - - public IReadOnlyDictionary KnownProperties => null; - - public IObjectEditor Parent => null; - - public IReadOnlyList DirectChildren => EmptyDirectChildren; - - public IReadOnlyCollection Events => this.events; - - public event EventHandler PropertyChanged; - - public PropertyPadObjectEditor (PropertyPadItem propertyItem) - { - this.propertyItem = propertyItem; - foreach (object propertyProvider in propertyItem.Providers) { - var props = GetProperties (propertyProvider, null); - - for (int i = 0; i < props.Count; i++) { - var prop = props [i] as PropertyDescriptor; - if (prop.IsBrowsable) { - properties.Add (CreatePropertyInfo (prop, propertyProvider)); - } - } - } - } - - bool HasStandardValues (PropertyDescriptor propertyDescriptor) - { - if (propertyDescriptor.Converter.GetStandardValuesSupported ()) { - if (!propertyDescriptor.Converter.GetStandardValuesExclusive () && propertyDescriptor.Converter.CanConvertFrom (typeof (string))) { - return true; - } - } - return false; - } - - PropertyDescriptor GetPropertyDescriptor (PropertyDescriptorCollection collection, string name) - { - for (int i = 0; i < collection.Count; i++) { - if (collection[i].Name == name) { - return collection [i]; - } - } - return null; - } - - protected IPropertyInfo CreatePropertyInfo (PropertyDescriptor propertyDescriptor, object PropertyProvider) - { - var valueSources = ValueSources.Local | ValueSources.Default; - if (propertyDescriptor.PropertyType.IsEnum) { - if (propertyDescriptor.PropertyType.IsDefined (typeof (FlagsAttribute), true)) - return new FlagDescriptorPropertyInfo (propertyDescriptor, PropertyProvider, valueSources); - return new EnumDescriptorPropertyInfo (propertyDescriptor, PropertyProvider, valueSources); - } - - if (propertyDescriptor.PropertyType.IsAssignableFrom (typeof (Core.FilePath))) { - //var isDirectoryPropertyDescriptor = GetPropertyDescriptor (propertyDescriptor.GetChildProperties (), nameof (Core.FilePath.IsDirectory)); - //if (isDirectoryPropertyDescriptor != null && (bool)isDirectoryPropertyDescriptor.GetValue (propertyItem)) { - // return new DirectoryPathPropertyInfo (propertyDescriptor, PropertyProvider, valueSources); - //} - return new FilePathPropertyInfo (propertyDescriptor, PropertyProvider, valueSources); - } - - if (HasStandardValues (propertyDescriptor)) { - return new StringStandardValuesPropertyInfo (propertyDescriptor, PropertyProvider, valueSources); - } - - return new DescriptorPropertyInfo (propertyDescriptor, PropertyProvider, valueSources); - } - - public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes) - { - if (component == null) - return new PropertyDescriptorCollection (new PropertyDescriptor [] { }); - return TypeDescriptor.GetProperties (component); - } - - public async Task GetAssignableTypesAsync (IPropertyInfo property, bool childTypes) - { - return new AssignableTypesResult (Array.Empty ()); - } - - public Task> GetHandlersAsync (IEventInfo ev) - { - if (ev == null) - throw new ArgumentNullException (nameof (ev)); - - if (!(ev is Xamarin.PropertyEditing.Reflection.ReflectionEventInfo info)) - throw new ArgumentException (); - - return Task.FromResult (info.GetHandlers (this.propertyItem)); - } - - public Task GetNameAsync () - { - return Task.FromResult (Name); - } - - public Task> GetPropertyVariantsAsync (IPropertyInfo property) - { - return Task.FromResult> (new PropertyVariation [0]); - } - - public async Task> GetValueAsync (IPropertyInfo property, PropertyVariation variations = null) - { - if (property == null) - throw new ArgumentNullException (nameof (property)); - - if (!(property is DescriptorPropertyInfo propertyInfo)) - throw new ArgumentException ("Property should be a DescriptorPropertyInfo", nameof (property)); - - return await propertyItem.GetPropertyValueInfoAsProppyType (propertyInfo); - } - - public Task RemovePropertyVariantAsync (IPropertyInfo property, PropertyVariation variant) - { - return Task.CompletedTask; - } - - public Task SetNameAsync (string name) - { - Name = name; - return Task.FromResult (true); - } - - public Task SetValueAsync (IPropertyInfo propertyInfo, ValueInfo value, PropertyVariation variations = null) - { - if (propertyInfo == null) - throw new ArgumentNullException (nameof (propertyInfo)); - - if (propertyInfo is DescriptorPropertyInfo info && info.CanWrite) { - - propertyItem.SetPropertyValueInfoAsProppyType (info, value, variations); - - OnPropertyChanged (info); - return Task.CompletedTask; - } - throw new ArgumentException ($"Property should be a writeable {nameof (DescriptorPropertyInfo)}.", nameof (propertyInfo)); - } - - protected virtual void OnPropertyChanged (IPropertyInfo property) - { - PropertyChanged?.Invoke (this, new EditorPropertyChangedEventArgs (property)); - } - } -} - -#endif \ No newline at end of file diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/PropertyPad.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/PropertyPad.cs index e7fc1f147a0..c666f5ad9ad 100644 --- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/PropertyPad.cs +++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/PropertyPad.cs @@ -70,19 +70,15 @@ public PropertyPad () frame = new InvisibleFrame (); #if MAC - isNative = FeatureSwitchService.IsFeatureEnabled ("NativePropertyPanel") ?? false; + isNative = true; if (isNative) { nativeGrid = new MacPropertyGrid (); propertyGrid = nativeGrid; + nativeGrid.PropertyGridChanged += Grid_Changed; + gtkWidget = new GtkNSViewHost (nativeGrid); - gtkWidget = Components.Mac.GtkMacInterop.NSViewToGtkWidget (nativeGrid); - gtkWidget.CanFocus = true; - gtkWidget.Sensitive = true; - gtkWidget.Focused += Widget_Focused; - - nativeGrid.Focused += PropertyGrid_Focused; frame.Add (gtkWidget); } else { #endif @@ -100,12 +96,7 @@ void Grid_Changed (object sender, EventArgs e) { PropertyGridChanged?.Invoke (this, e); } -#if MAC - void Widget_Focused (object o, Gtk.FocusedArgs args) - { - nativeGrid.Window.MakeFirstResponder (nativeGrid); - } -#endif + protected override void Initialize (IPadWindow container) { base.Initialize (container); @@ -136,8 +127,7 @@ public override void Dispose() #if MAC if (isNative) { container.PadContentShown -= Window_PadContentShown; - nativeGrid.Focused -= PropertyGrid_Focused; - gtkWidget.Focused -= Widget_Focused; + nativeGrid.PropertyGridChanged -= Grid_Changed; } else { #endif grid.Changed -= Grid_Changed; @@ -195,14 +185,7 @@ void Window_PadContentShown (object sender, EventArgs e) { propertyGrid.OnPadContentShown (); } -#if MAC - void PropertyGrid_Focused (object sender, EventArgs e) - { - if (!gtkWidget.HasFocus) { - gtkWidget.HasFocus = true; - } - } -#endif + void AttachToolbarIfCustomWidget () { if (customWidget) {