From dd0ecf1b9604c7a7a6a8a56c62662b2c8be85712 Mon Sep 17 00:00:00 2001 From: MaxED Date: Thu, 11 Oct 2012 14:59:12 +0000 Subject: [PATCH] [WIP] Some more work on Properties Dock plugin... --- Build/Plugins/PropertiesDock.dll | Bin 33792 -> 26624 bytes Source/Core/Plugins/Plug.cs | 8 + Source/Core/Types/TypeHandlerAttribute.cs | 2 +- Source/Plugins/PropertiesDock/BuilderPlug.cs | 11 +- .../Controls/PropertiesDocker.Designer.cs | 37 +- .../Controls/PropertiesDocker.cs | 4 + .../Data/CustomPropertiesCollection.cs | 135 +++ .../PropertiesDock/Data/CustomProperty.cs | 41 + .../Data/CustomPropertyDescriptor.cs | 84 ++ .../PropertiesDock/Data/MapElementsData.cs | 13 +- .../PropertiesDock/Data/PropertyBag.cs | 979 ------------------ .../PropertiesDock/Data/VertexPosition.cs | 70 -- .../Plugins/PropertiesDock/Info/VertexInfo.cs | 35 +- .../PropertiesDock/PropertiesDock.csproj | 5 +- 14 files changed, 325 insertions(+), 1099 deletions(-) create mode 100644 Source/Plugins/PropertiesDock/Data/CustomPropertiesCollection.cs create mode 100644 Source/Plugins/PropertiesDock/Data/CustomProperty.cs create mode 100644 Source/Plugins/PropertiesDock/Data/CustomPropertyDescriptor.cs delete mode 100644 Source/Plugins/PropertiesDock/Data/PropertyBag.cs delete mode 100644 Source/Plugins/PropertiesDock/Data/VertexPosition.cs diff --git a/Build/Plugins/PropertiesDock.dll b/Build/Plugins/PropertiesDock.dll index c21b458af23fac405c9014569555b96cb034be13..2ca75f0c93c60f65043d4f79e3429d571648a964 100644 GIT binary patch literal 26624 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 literal 33792 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 + /// Add CustomProperty to Collectionbase List + /// + /// + public void Add(CustomProperty Value) { + base.List.Add(Value); + } + + /// + /// Remove item from List + /// + /// + public void Remove(string Name) { + foreach (CustomProperty prop in base.List) { + if (prop.Name == Name) { + base.List.Remove(prop); + return; + } + } + } + + /// + /// Indexer + /// + public CustomProperty this[int index] { + get { + return (CustomProperty)base.List[index]; + } + set { + base.List[index] = (CustomProperty)value; + } + } + + + #region "TypeDescriptor Implementation" + /// + /// Get Class Name + /// + /// String + public String GetClassName() { + return TypeDescriptor.GetClassName(this, true); + } + + /// + /// GetAttributes + /// + /// AttributeCollection + public AttributeCollection GetAttributes() { + return TypeDescriptor.GetAttributes(this, true); + } + + /// + /// GetComponentName + /// + /// String + public String GetComponentName() { + return TypeDescriptor.GetComponentName(this, true); + } + + /// + /// GetConverter + /// + /// TypeConverter + public TypeConverter GetConverter() { + return TypeDescriptor.GetConverter(this, true); + } + + /// + /// GetDefaultEvent + /// + /// EventDescriptor + public EventDescriptor GetDefaultEvent() { + return TypeDescriptor.GetDefaultEvent(this, true); + } + + /// + /// GetDefaultProperty + /// + /// PropertyDescriptor + public PropertyDescriptor GetDefaultProperty() { + return TypeDescriptor.GetDefaultProperty(this, true); + } + + /// + /// GetEditor + /// + /// editorBaseType + /// object + public object GetEditor(Type editorBaseType) { + return TypeDescriptor.GetEditor(this, editorBaseType, true); + } + + public EventDescriptorCollection GetEvents(Attribute[] attributes) { + return TypeDescriptor.GetEvents(this, attributes, true); + } + + public EventDescriptorCollection GetEvents() { + return TypeDescriptor.GetEvents(this, true); + } + + public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { + PropertyDescriptor[] newProps = new PropertyDescriptor[this.Count]; + for (int i = 0; i < this.Count; i++) { + CustomProperty prop = (CustomProperty)this[i]; + newProps[i] = new CustomPropertyDescriptor(ref prop, attributes); + } + + return new PropertyDescriptorCollection(newProps); + } + + public PropertyDescriptorCollection GetProperties() { + PropertyDescriptorCollection c = TypeDescriptor.GetProperties(this, true); + + return TypeDescriptor.GetProperties(this, true); + /*PropertyDescriptor[] newProps = new PropertyDescriptor[this.Count]; + for (int i = 0; i < this.Count; i++) { + CustomProperty prop = (CustomProperty)this[i]; + newProps[i] = new CustomPropertyDescriptor(ref prop); + } + + return new PropertyDescriptorCollection(newProps);*/ + } + + public object GetPropertyOwner(PropertyDescriptor pd) { + return this; + } + #endregion + } +} diff --git a/Source/Plugins/PropertiesDock/Data/CustomProperty.cs b/Source/Plugins/PropertiesDock/Data/CustomProperty.cs new file mode 100644 index 00000000..4ceb2780 --- /dev/null +++ b/Source/Plugins/PropertiesDock/Data/CustomProperty.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Collections.Generic; + +namespace CodeImp.DoomBuilder.PropertiesDock { + public class CustomProperty { + public bool ReadOnly { get { return bReadOnly; } } + public string Name { get { return sName; } } + public string Category { get { return category; } } + public bool Visible { get { return bVisible; } } + public object Value { get { return objValue; } set { objValue = value; } } + + private string sName = string.Empty; + private string category = string.Empty; + private bool bReadOnly = false; + private bool bVisible = true; + private object objValue = null; + //private Attribute[] attributes; + + public CustomProperty(string sName, object value, bool bReadOnly, bool bVisible) { + this.sName = sName; + this.objValue = value; + this.bReadOnly = bReadOnly; + this.bVisible = bVisible; + //this.attributes = new Attribute[0]; + } + + //mxd + public CustomProperty(string sName, object value, string category, bool bReadOnly, bool bVisible) : this(sName, value, bReadOnly, bVisible) { + //attributes = attrs; + this.category = category; + } + + /*public Attribute[] Attributes { + get { + return attributes; + } + }*/ + } +} diff --git a/Source/Plugins/PropertiesDock/Data/CustomPropertyDescriptor.cs b/Source/Plugins/PropertiesDock/Data/CustomPropertyDescriptor.cs new file mode 100644 index 00000000..91b7004c --- /dev/null +++ b/Source/Plugins/PropertiesDock/Data/CustomPropertyDescriptor.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Collections.Generic; + +namespace CodeImp.DoomBuilder.PropertiesDock { + public class CustomPropertyDescriptor : PropertyDescriptor { + CustomProperty m_Property; + public CustomPropertyDescriptor(ref CustomProperty myProperty, Attribute[] attrs) + : base(myProperty.Name, attrs) { + m_Property = myProperty; + } + /*public CustomPropertyDescriptor(ref CustomProperty myProperty, Attribute[] attrs) + : base(myProperty.Name, combineAttributes(attrs, myProperty.Attributes)) { + m_Property = myProperty; + }*/ + + /*private static Attribute[] combineAttributes(Attribute[] attrs, Attribute[] attribute) { + List l = new List(); + l.AddRange(attrs); + l.AddRange(attribute); + return l.ToArray(); + }*/ + + #region PropertyDescriptor specific + + public override bool CanResetValue(object component) { + return false; + } + + public override Type ComponentType { + get { + return null; + } + } + + public override object GetValue(object component) { + return m_Property.Value; + } + + public override string Description { + get { + return m_Property.Name; + } + } + + public override string Category { + get { + return m_Property.Category; + } + } + + public override string DisplayName { + get { + return m_Property.Name; + } + + } + + public override bool IsReadOnly { + get { + return m_Property.ReadOnly; + } + } + + public override void ResetValue(object component) { + //Have to implement + } + + public override bool ShouldSerializeValue(object component) { + return false; + } + + public override void SetValue(object component, object value) { + m_Property.Value = value; + } + + public override Type PropertyType { + get { return m_Property.Value.GetType(); } + } + + #endregion + } +} diff --git a/Source/Plugins/PropertiesDock/Data/MapElementsData.cs b/Source/Plugins/PropertiesDock/Data/MapElementsData.cs index 08ae5468..7c8576eb 100644 --- a/Source/Plugins/PropertiesDock/Data/MapElementsData.cs +++ b/Source/Plugins/PropertiesDock/Data/MapElementsData.cs @@ -3,14 +3,15 @@ using System.Collections.Generic; using System.Text; using CodeImp.DoomBuilder.Config; +using CodeImp.DoomBuilder.Types; namespace CodeImp.DoomBuilder.PropertiesDock { - public static class MapElementsData { + internal static class MapElementsData { - public static Dictionary ThingTypeDescriptions { get { return thingTypeDescriptions;}} + internal static Dictionary ThingTypeDescriptions { get { return thingTypeDescriptions; } } private static Dictionary thingTypeDescriptions; - - public static void Init() { + + internal static void Init() { //thing types thingTypeDescriptions = new Dictionary(); @@ -20,5 +21,9 @@ namespace CodeImp.DoomBuilder.PropertiesDock { } } } + + internal static void InitTypes(TypeHandlerAttribute[] types) { + + } } } diff --git a/Source/Plugins/PropertiesDock/Data/PropertyBag.cs b/Source/Plugins/PropertiesDock/Data/PropertyBag.cs deleted file mode 100644 index 0bf7ce03..00000000 --- a/Source/Plugins/PropertiesDock/Data/PropertyBag.cs +++ /dev/null @@ -1,979 +0,0 @@ -/******************************************************************** - * - * PropertyBag.cs - * -------------- - * Copyright (C) 2002 Tony Allowatt - * Last Update: 12/14/2002 - * - * THE SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS", WITHOUT WARRANTY - * OF ANY KIND, EXPRESS OR IMPLIED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF THIS - * SOFTWARE. - * - * Public types defined in this file: - * ---------------------------------- - * namespace Flobbster.Windows.Forms - * class PropertySpec - * class PropertySpecEventArgs - * delegate PropertySpecEventHandler - * class PropertyBag - * class PropertyBag.PropertySpecCollection - * class PropertyTable - * - ********************************************************************/ - -using System; -using System.Collections; -using System.ComponentModel; -using System.Drawing.Design; - -namespace CodeImp.DoomBuilder.PropertiesDock { - /// - /// Represents a single property in a PropertySpec. - /// - public class PropertySpec { - private Attribute[] attributes; - private string category; - private object defaultValue; - private string description; - private string editor; - private string name; - private string type; - private string typeConverter; - private object currentValue; //mxd - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - public PropertySpec(string name, string type) : this(name, type, null, null, null) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - public PropertySpec(string name, Type type) : - this(name, type.AssemblyQualifiedName, null, null, null) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - /// The category under which the property is displayed in the - /// property grid. - public PropertySpec(string name, string type, string category) : this(name, type, category, null, null) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - /// - public PropertySpec(string name, Type type, string category) : - this(name, type.AssemblyQualifiedName, category, null, null) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - public PropertySpec(string name, string type, string category, string description) : - this(name, type, category, description, null) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - public PropertySpec(string name, Type type, string category, string description) : - this(name, type.AssemblyQualifiedName, category, description, null) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - public PropertySpec(string name, string type, string category, string description, object defaultValue) { - this.name = name; - this.type = type; - this.category = category; - this.description = description; - this.defaultValue = defaultValue; - this.attributes = null; - this.currentValue = defaultValue; //mxd - } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - public PropertySpec(string name, Type type, string category, string description, object defaultValue) : - this(name, type.AssemblyQualifiedName, category, description, defaultValue) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The fully qualified name of the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The fully qualified name of the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, string type, string category, string description, object defaultValue, - string editor, string typeConverter) - : this(name, type, category, description, defaultValue) { - this.editor = editor; - this.typeConverter = typeConverter; - } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The fully qualified name of the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The fully qualified name of the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, Type type, string category, string description, object defaultValue, - string editor, string typeConverter) : - this(name, type.AssemblyQualifiedName, category, description, defaultValue, editor, typeConverter) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The Type that represents the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The fully qualified name of the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, string type, string category, string description, object defaultValue, - Type editor, string typeConverter) : - this(name, type, category, description, defaultValue, editor.AssemblyQualifiedName, - typeConverter) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The Type that represents the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The fully qualified name of the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, Type type, string category, string description, object defaultValue, - Type editor, string typeConverter) : - this(name, type.AssemblyQualifiedName, category, description, defaultValue, - editor.AssemblyQualifiedName, typeConverter) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The fully qualified name of the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The Type that represents the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, string type, string category, string description, object defaultValue, - string editor, Type typeConverter) : - this(name, type, category, description, defaultValue, editor, typeConverter.AssemblyQualifiedName) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The fully qualified name of the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The Type that represents the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, Type type, string category, string description, object defaultValue, - string editor, Type typeConverter) : - this(name, type.AssemblyQualifiedName, category, description, defaultValue, editor, - typeConverter.AssemblyQualifiedName) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// The fully qualified name of the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The Type that represents the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The Type that represents the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, string type, string category, string description, object defaultValue, - Type editor, Type typeConverter) : - this(name, type, category, description, defaultValue, editor.AssemblyQualifiedName, - typeConverter.AssemblyQualifiedName) { } - - /// - /// Initializes a new instance of the PropertySpec class. - /// - /// The name of the property displayed in the property grid. - /// A Type that represents the type of the property. - /// The category under which the property is displayed in the - /// property grid. - /// A string that is displayed in the help area of the - /// property grid. - /// The default value of the property, or null if there is - /// no default value. - /// The Type that represents the type of the editor for this - /// property. This type must derive from UITypeEditor. - /// The Type that represents the type of the type - /// converter for this property. This type must derive from TypeConverter. - public PropertySpec(string name, Type type, string category, string description, object defaultValue, - Type editor, Type typeConverter) : - this(name, type.AssemblyQualifiedName, category, description, defaultValue, - editor.AssemblyQualifiedName, typeConverter.AssemblyQualifiedName) { } - - /// - /// Gets or sets a collection of additional Attributes for this property. This can - /// be used to specify attributes beyond those supported intrinsically by the - /// PropertySpec class, such as ReadOnly and Browsable. - /// - public Attribute[] Attributes { - get { return attributes; } - set { attributes = value; } - } - - /// - /// Gets or sets the category name of this property. - /// - public string Category { - get { return category; } - set { category = value; } - } - - /// - /// Gets or sets the fully qualified name of the type converter - /// type for this property. - /// - public string ConverterTypeName { - get { return typeConverter; } - set { typeConverter = value; } - } - - /// - /// Gets or sets the default value of this property. - /// - public object DefaultValue { - get { return defaultValue; } - set { defaultValue = value; } - } - - //mxd - /// - /// Gets or sets the value of this property. - /// - public object Value { - get { return currentValue; } - set { currentValue = value; } - } - - /// - /// Gets or sets the help text description of this property. - /// - public string Description { - get { return description; } - set { description = value; } - } - - /// - /// Gets or sets the fully qualified name of the editor type for - /// this property. - /// - public string EditorTypeName { - get { return editor; } - set { editor = value; } - } - - /// - /// Gets or sets the name of this property. - /// - public string Name { - get { return name; } - set { name = value; } - } - - /// - /// Gets or sets the fully qualfied name of the type of this - /// property. - /// - public string TypeName { - get { return type; } - set { type = value; } - } - } - - /// - /// Provides data for the GetValue and SetValue events of the PropertyBag class. - /// - public class PropertySpecEventArgs : EventArgs { - private PropertySpec property; - private object val; - - /// - /// Initializes a new instance of the PropertySpecEventArgs class. - /// - /// The PropertySpec that represents the property whose - /// value is being requested or set. - /// The current value of the property. - public PropertySpecEventArgs(PropertySpec property, object val) { - this.property = property; - this.val = val; - } - - /// - /// Gets the PropertySpec that represents the property whose value is being - /// requested or set. - /// - public PropertySpec Property { - get { return property; } - } - - /// - /// Gets or sets the current value of the property. - /// - public object Value { - get { return val; } - set { val = value; } - } - } - - /// - /// Represents the method that will handle the GetValue and SetValue events of the - /// PropertyBag class. - /// - public delegate void PropertySpecEventHandler(object sender, PropertySpecEventArgs e); - - /// - /// Represents a collection of custom properties that can be selected into a - /// PropertyGrid to provide functionality beyond that of the simple reflection - /// normally used to query an object's properties. - /// - public class PropertyBag : ICustomTypeDescriptor { - #region PropertySpecCollection class definition - /// - /// Encapsulates a collection of PropertySpec objects. - /// - [Serializable] - public class PropertySpecCollection : IList { - private ArrayList innerArray; - - /// - /// Initializes a new instance of the PropertySpecCollection class. - /// - public PropertySpecCollection() { - innerArray = new ArrayList(); - } - - /// - /// Gets the number of elements in the PropertySpecCollection. - /// - /// - /// The number of elements contained in the PropertySpecCollection. - /// - public int Count { - get { return innerArray.Count; } - } - - /// - /// Gets a value indicating whether the PropertySpecCollection has a fixed size. - /// - /// - /// true if the PropertySpecCollection has a fixed size; otherwise, false. - /// - public bool IsFixedSize { - get { return false; } - } - - /// - /// Gets a value indicating whether the PropertySpecCollection is read-only. - /// - public bool IsReadOnly { - get { return false; } - } - - /// - /// Gets a value indicating whether access to the collection is synchronized (thread-safe). - /// - /// - /// true if access to the PropertySpecCollection is synchronized (thread-safe); otherwise, false. - /// - public bool IsSynchronized { - get { return false; } - } - - /// - /// Gets an object that can be used to synchronize access to the collection. - /// - /// - /// An object that can be used to synchronize access to the collection. - /// - object ICollection.SyncRoot { - get { return null; } - } - - /// - /// Gets or sets the element at the specified index. - /// In C#, this property is the indexer for the PropertySpecCollection class. - /// - /// The zero-based index of the element to get or set. - /// - /// The element at the specified index. - /// - public PropertySpec this[int index] { - get { return (PropertySpec)innerArray[index]; } - set { innerArray[index] = value; } - } - - /// - /// Adds a PropertySpec to the end of the PropertySpecCollection. - /// - /// The PropertySpec to be added to the end of the PropertySpecCollection. - /// The PropertySpecCollection index at which the value has been added. - public int Add(PropertySpec value) { - int index = innerArray.Add(value); - - return index; - } - - /// - /// Adds the elements of an array of PropertySpec objects to the end of the PropertySpecCollection. - /// - /// The PropertySpec array whose elements should be added to the end of the - /// PropertySpecCollection. - public void AddRange(PropertySpec[] array) { - innerArray.AddRange(array); - } - - /// - /// Removes all elements from the PropertySpecCollection. - /// - public void Clear() { - innerArray.Clear(); - } - - /// - /// Determines whether a PropertySpec is in the PropertySpecCollection. - /// - /// The PropertySpec to locate in the PropertySpecCollection. The element to locate - /// can be a null reference (Nothing in Visual Basic). - /// true if item is found in the PropertySpecCollection; otherwise, false. - public bool Contains(PropertySpec item) { - return innerArray.Contains(item); - } - - /// - /// Determines whether a PropertySpec with the specified name is in the PropertySpecCollection. - /// - /// The name of the PropertySpec to locate in the PropertySpecCollection. - /// true if item is found in the PropertySpecCollection; otherwise, false. - public bool Contains(string name) { - foreach (PropertySpec spec in innerArray) - if (spec.Name == name) - return true; - - return false; - } - - /// - /// Copies the entire PropertySpecCollection to a compatible one-dimensional Array, starting at the - /// beginning of the target array. - /// - /// The one-dimensional Array that is the destination of the elements copied - /// from PropertySpecCollection. The Array must have zero-based indexing. - public void CopyTo(PropertySpec[] array) { - innerArray.CopyTo(array); - } - - /// - /// Copies the PropertySpecCollection or a portion of it to a one-dimensional array. - /// - /// The one-dimensional Array that is the destination of the elements copied - /// from the collection. - /// The zero-based index in array at which copying begins. - public void CopyTo(PropertySpec[] array, int index) { - innerArray.CopyTo(array, index); - } - - /// - /// Returns an enumerator that can iterate through the PropertySpecCollection. - /// - /// An IEnumerator for the entire PropertySpecCollection. - public IEnumerator GetEnumerator() { - return innerArray.GetEnumerator(); - } - - /// - /// Searches for the specified PropertySpec and returns the zero-based index of the first - /// occurrence within the entire PropertySpecCollection. - /// - /// The PropertySpec to locate in the PropertySpecCollection. - /// The zero-based index of the first occurrence of value within the entire PropertySpecCollection, - /// if found; otherwise, -1. - public int IndexOf(PropertySpec value) { - return innerArray.IndexOf(value); - } - - /// - /// Searches for the PropertySpec with the specified name and returns the zero-based index of - /// the first occurrence within the entire PropertySpecCollection. - /// - /// The name of the PropertySpec to locate in the PropertySpecCollection. - /// The zero-based index of the first occurrence of value within the entire PropertySpecCollection, - /// if found; otherwise, -1. - public int IndexOf(string name) { - int i = 0; - - foreach (PropertySpec spec in innerArray) { - if (spec.Name == name) - return i; - - i++; - } - - return -1; - } - - /// - /// Inserts a PropertySpec object into the PropertySpecCollection at the specified index. - /// - /// The zero-based index at which value should be inserted. - /// The PropertySpec to insert. - public void Insert(int index, PropertySpec value) { - innerArray.Insert(index, value); - } - - /// - /// Removes the first occurrence of a specific object from the PropertySpecCollection. - /// - /// The PropertySpec to remove from the PropertySpecCollection. - public void Remove(PropertySpec obj) { - innerArray.Remove(obj); - } - - /// - /// Removes the property with the specified name from the PropertySpecCollection. - /// - /// The name of the PropertySpec to remove from the PropertySpecCollection. - public void Remove(string name) { - int index = IndexOf(name); - RemoveAt(index); - } - - /// - /// Removes the object at the specified index of the PropertySpecCollection. - /// - /// The zero-based index of the element to remove. - public void RemoveAt(int index) { - innerArray.RemoveAt(index); - } - - /// - /// Copies the elements of the PropertySpecCollection to a new PropertySpec array. - /// - /// A PropertySpec array containing copies of the elements of the PropertySpecCollection. - public PropertySpec[] ToArray() { - return (PropertySpec[])innerArray.ToArray(typeof(PropertySpec)); - } - - #region Explicit interface implementations for ICollection and IList - /// - /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. - /// - void ICollection.CopyTo(Array array, int index) { - CopyTo((PropertySpec[])array, index); - } - - /// - /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. - /// - int IList.Add(object value) { - return Add((PropertySpec)value); - } - - /// - /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. - /// - bool IList.Contains(object obj) { - return Contains((PropertySpec)obj); - } - - /// - /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. - /// - object IList.this[int index] { - get { - return ((PropertySpecCollection)this)[index]; - } - set { - ((PropertySpecCollection)this)[index] = (PropertySpec)value; - } - } - - /// - /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. - /// - int IList.IndexOf(object obj) { - return IndexOf((PropertySpec)obj); - } - - /// - /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. - /// - void IList.Insert(int index, object value) { - Insert(index, (PropertySpec)value); - } - - /// - /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code. - /// - void IList.Remove(object value) { - Remove((PropertySpec)value); - } - #endregion - } - #endregion - #region PropertySpecDescriptor class definition - private class PropertySpecDescriptor : PropertyDescriptor { - private PropertyBag bag; - private PropertySpec item; - - public PropertySpecDescriptor(PropertySpec item, PropertyBag bag, string name, Attribute[] attrs) : - base(name, attrs) { - this.bag = bag; - this.item = item; - } - - public override Type ComponentType { - get { return item.GetType(); } - } - - public override bool IsReadOnly { - get { return (Attributes.Matches(ReadOnlyAttribute.Yes)); } - } - - public override Type PropertyType { - get { return Type.GetType(item.TypeName); } - } - - public override bool CanResetValue(object component) { - if (item.DefaultValue == null) - return false; - else - return !this.GetValue(component).Equals(item.DefaultValue); - } - - public override object GetValue(object component) { - // Have the property bag raise an event to get the current value - // of the property. - - PropertySpecEventArgs e = new PropertySpecEventArgs(item, null); - bag.OnGetValue(e); - return e.Value; - } - - public override void ResetValue(object component) { - SetValue(component, item.DefaultValue); - } - - public override void SetValue(object component, object value) { - // Have the property bag raise an event to set the current value - // of the property. - - PropertySpecEventArgs e = new PropertySpecEventArgs(item, value); - bag.OnSetValue(e); - } - - public override bool ShouldSerializeValue(object component) { - object val = this.GetValue(component); - - if (item.DefaultValue == null && val == null) - return false; - else if (item.DefaultValue != null && val == null)//mxd - return true; - else - return !val.Equals(item.DefaultValue); - } - } - #endregion - - private string defaultProperty; - protected PropertySpecCollection properties; //mxd - - /// - /// Initializes a new instance of the PropertyBag class. - /// - public PropertyBag() { - defaultProperty = null; - properties = new PropertySpecCollection(); - } - - /// - /// Gets or sets the name of the default property in the collection. - /// - public string DefaultProperty { - get { return defaultProperty; } - set { defaultProperty = value; } - } - - /// - /// Gets the collection of properties contained within this PropertyBag. - /// - public PropertySpecCollection Properties { - get { return properties; } - } - - /// - /// Occurs when a PropertyGrid requests the value of a property. - /// - public event PropertySpecEventHandler GetValue; - - /// - /// Occurs when the user changes the value of a property in a PropertyGrid. - /// - public event PropertySpecEventHandler SetValue; - - /// - /// Raises the GetValue event. - /// - /// A PropertySpecEventArgs that contains the event data. - protected virtual void OnGetValue(PropertySpecEventArgs e) { - if (GetValue != null) - GetValue(this, e); - } - - /// - /// Raises the SetValue event. - /// - /// A PropertySpecEventArgs that contains the event data. - protected virtual void OnSetValue(PropertySpecEventArgs e) { - //mxd - e.Property.Value = e.Value; - - if (SetValue != null) - SetValue(this, e); - } - - #region ICustomTypeDescriptor explicit interface definitions - // Most of the functions required by the ICustomTypeDescriptor are - // merely pssed on to the default TypeDescriptor for this type, - // which will do something appropriate. The exceptions are noted - // below. - AttributeCollection ICustomTypeDescriptor.GetAttributes() { - return TypeDescriptor.GetAttributes(this, true); - } - - string ICustomTypeDescriptor.GetClassName() { - return TypeDescriptor.GetClassName(this, true); - } - - string ICustomTypeDescriptor.GetComponentName() { - return TypeDescriptor.GetComponentName(this, true); - } - - TypeConverter ICustomTypeDescriptor.GetConverter() { - return TypeDescriptor.GetConverter(this, true); - } - - EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { - return TypeDescriptor.GetDefaultEvent(this, true); - } - - PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { - // This function searches the property list for the property - // with the same name as the DefaultProperty specified, and - // returns a property descriptor for it. If no property is - // found that matches DefaultProperty, a null reference is - // returned instead. - - PropertySpec propertySpec = null; - if (defaultProperty != null) { - int index = properties.IndexOf(defaultProperty); - propertySpec = properties[index]; - } - - if (propertySpec != null) - return new PropertySpecDescriptor(propertySpec, this, propertySpec.Name, null); - else - return null; - } - - object ICustomTypeDescriptor.GetEditor(Type editorBaseType) { - return TypeDescriptor.GetEditor(this, editorBaseType, true); - } - - EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { - return TypeDescriptor.GetEvents(this, true); - } - - EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) { - return TypeDescriptor.GetEvents(this, attributes, true); - } - - PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { - return ((ICustomTypeDescriptor)this).GetProperties(new Attribute[0]); - } - - PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) { - // Rather than passing this function on to the default TypeDescriptor, - // which would return the actual properties of PropertyBag, I construct - // a list here that contains property descriptors for the elements of the - // Properties list in the bag. - - ArrayList props = new ArrayList(); - - foreach (PropertySpec property in properties) { - ArrayList attrs = new ArrayList(); - - // If a category, description, editor, or type converter are specified - // in the PropertySpec, create attributes to define that relationship. - if (property.Category != null) - attrs.Add(new CategoryAttribute(property.Category)); - - if (property.Description != null) - attrs.Add(new DescriptionAttribute(property.Description)); - - if (property.EditorTypeName != null) - attrs.Add(new EditorAttribute(property.EditorTypeName, typeof(UITypeEditor))); - - if (property.ConverterTypeName != null) - attrs.Add(new TypeConverterAttribute(property.ConverterTypeName)); - - // Additionally, append the custom attributes associated with the - // PropertySpec, if any. - if (property.Attributes != null) - attrs.AddRange(property.Attributes); - - Attribute[] attrArray = (Attribute[])attrs.ToArray(typeof(Attribute)); - - // Create a new property descriptor for the property item, and add - // it to the list. - PropertySpecDescriptor pd = new PropertySpecDescriptor(property, - this, property.Name, attrArray); - props.Add(pd); - } - - // Convert the list of PropertyDescriptors to a collection that the - // ICustomTypeDescriptor can use, and return it. - PropertyDescriptor[] propArray = (PropertyDescriptor[])props.ToArray( - typeof(PropertyDescriptor)); - return new PropertyDescriptorCollection(propArray); - } - - object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { - return this; - } - #endregion - } - - /// - /// An extension of PropertyBag that manages a table of property values, in - /// addition to firing events when property values are requested or set. - /// - public class PropertyTable : PropertyBag { - private Hashtable propValues; - - /// - /// Initializes a new instance of the PropertyTable class. - /// - public PropertyTable() { - propValues = new Hashtable(); - } - - /// - /// Gets or sets the value of the property with the specified name. - ///

In C#, this property is the indexer of the PropertyTable class.

- ///
- public object this[string key] { - get { return propValues[key]; } - set { propValues[key] = value; } - } - - /// - /// This member overrides PropertyBag.OnGetValue. - /// - protected override void OnGetValue(PropertySpecEventArgs e) { - e.Value = propValues[e.Property.Name]; - base.OnGetValue(e); - } - - /// - /// This member overrides PropertyBag.OnSetValue. - /// - protected override void OnSetValue(PropertySpecEventArgs e) { - propValues[e.Property.Name] = e.Value; - base.OnSetValue(e); - } - } -} diff --git a/Source/Plugins/PropertiesDock/Data/VertexPosition.cs b/Source/Plugins/PropertiesDock/Data/VertexPosition.cs deleted file mode 100644 index 4b6ca0d0..00000000 --- a/Source/Plugins/PropertiesDock/Data/VertexPosition.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.ComponentModel; -using System.Globalization; - -namespace CodeImp.DoomBuilder.PropertiesDock { - - /*[TypeConverterAttribute(typeof(VertexPositionConverter)), DescriptionAttribute("Vertex position.")] - public class VertexPosition { - [DefaultValueAttribute(0f)] - public float X { get { return x; } set { x = value; } } - private float x; - - [DefaultValueAttribute(0f)] - public float Y { get { return y; } set { y = value; } } - private float y; - - public VertexPosition(float x, float y) { - this.x = x; - this.y = y; - } - } - - public class VertexPositionConverter : ExpandableObjectConverter { - public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType) { - if (destinationType == typeof(VertexPosition)) - return true; - return base.CanConvertTo(context, destinationType); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, System.Type destinationType) { - if (destinationType == typeof(System.String) && value is VertexPosition) { - VertexPosition tp = (VertexPosition)value; - return "X:" + tp.X + ", Y: " + tp.Y; - } - return base.ConvertTo(context, culture, value, destinationType); - } - - public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType) { - if (sourceType == typeof(string)) - return true; - return base.CanConvertFrom(context, sourceType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { - if (value is string) { - try { - string s = (string)value; - int colon = s.IndexOf(':'); - int comma = s.IndexOf(','); - - if (colon != -1 && comma != -1) { - string px = s.Substring(colon + 1, (comma - colon - 1)); - colon = s.IndexOf(':', comma + 1); - - if (colon != -1) { - string py = s.Substring(colon + 1, s.Length - (colon + 1)); - VertexPosition tp = new VertexPosition(float.Parse(px), float.Parse(py)); - return tp; - } - } - } catch { - throw new ArgumentException("Can not convert '" + (string)value + "' to type TestPosition"); - } - } - return base.ConvertFrom(context, culture, value); - } - }*/ -} diff --git a/Source/Plugins/PropertiesDock/Info/VertexInfo.cs b/Source/Plugins/PropertiesDock/Info/VertexInfo.cs index 623facbe..38db0a8c 100644 --- a/Source/Plugins/PropertiesDock/Info/VertexInfo.cs +++ b/Source/Plugins/PropertiesDock/Info/VertexInfo.cs @@ -6,48 +6,41 @@ using System.Text; using CodeImp.DoomBuilder.Map; namespace CodeImp.DoomBuilder.PropertiesDock { - - public class VertexInfo : PropertyBag, IMapElementInfo { - /*[CategoryAttribute("Position"), DefaultValueAttribute(0f)] - public float X { get { return x; } set { x = value; } }*/ - //private float x; - - /*[CategoryAttribute("Position"), DefaultValueAttribute(0f)] - public float Y { get { return y; } set { y = value; } }*/ - //private float y; - - //public PropertyBag Properties { get { return properties; } } - //private PropertyBag properties; + public class VertexInfo : CustomPropertiesCollection, IMapElementInfo { private Vertex vertex; public VertexInfo(Vertex v) : base() { vertex = v; - //x = v.Position.x; - //y = v.Position.y; - //properties = new PropertyBag(); - properties.Add(new PropertySpec("X:", typeof(float), "Position:", null, v.Position.x)); - properties.Add(new PropertySpec("Y:", typeof(float), "Position:", null, v.Position.y)); + Add(new CustomProperty("X:", v.Position.x, "Position:", false, true)); + Add(new CustomProperty("Y:", v.Position.y, "Position:", false, true)); + + //todo: add custom fields + if (v.Fields != null && v.Fields.Count > 0) { + foreach (KeyValuePair group in v.Fields) { + Add(new CustomProperty(group.Key, group.Value.Value, "Custom properties:", false, true)); + } + } } public void ApplyChanges() { float min = (float)General.Map.FormatInterface.MinCoordinate; float max = (float)General.Map.FormatInterface.MaxCoordinate; - vertex.Move(new CodeImp.DoomBuilder.Geometry.Vector2D(General.Clamp((float)properties[0].Value, min, max), General.Clamp((float)properties[1].Value, min, max))); + vertex.Move(new CodeImp.DoomBuilder.Geometry.Vector2D(General.Clamp((float)this[0].Value, min, max), General.Clamp((float)this[1].Value, min, max))); //todo: add custom fields support } public void AddCustomProperty(string name, Type type) { - properties.Add(new PropertySpec(name + ":", type, "Custom properties:")); + Add(new CustomProperty(name, Activator.CreateInstance(type), "Custom properties:", false, true)); } public void RemoveCustomProperty(string name){ string n = name.ToUpperInvariant().Trim(); - foreach (PropertySpec ps in properties) { + foreach (CustomProperty ps in this) { string cn = ps.Name.ToUpperInvariant(); if (cn.IndexOf(n) == 0 && cn.Length == n.Length + 1) { - properties.Remove(name); + Remove(name); return; } } diff --git a/Source/Plugins/PropertiesDock/PropertiesDock.csproj b/Source/Plugins/PropertiesDock/PropertiesDock.csproj index e88d90f6..5801871c 100644 --- a/Source/Plugins/PropertiesDock/PropertiesDock.csproj +++ b/Source/Plugins/PropertiesDock/PropertiesDock.csproj @@ -50,9 +50,10 @@ PropertiesDocker.cs + + + - -