From 12a7256c291fbef761c85512e78b5a0f7d446e05 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Wed, 10 Oct 2012 15:39:18 +0000
Subject: [PATCH] [WIP] Some more work on Properties Dock plugin...

---
 Build/Plugins/PropertiesDock.dll              | Bin 14336 -> 33792 bytes
 Build/Plugins/PropertiesDock.pdb              | Bin 36352 -> 0 bytes
 Source/Plugins/PropertiesDock/BuilderPlug.cs  |   4 +-
 .../Controls/PropertiesDocker.Designer.cs     |  90 +-
 .../Controls/PropertiesDocker.cs              | 109 +-
 .../PropertiesDock/Data/MapElementsData.cs    |  24 +
 .../PropertiesDock/Data/PropertyBag.cs        | 979 ++++++++++++++++++
 .../PropertiesDock/Info/IMapElementInfo.cs    |   2 +
 .../Plugins/PropertiesDock/Info/ThingInfo.cs  |  80 ++
 .../Plugins/PropertiesDock/Info/VertexInfo.cs |  44 +-
 .../Properties/Resources.Designer.cs          |  77 ++
 .../PropertiesDock/Properties/Resources.resx  | 127 +++
 .../PropertiesDock/PropertiesDock.csproj      |  18 +
 .../Plugins/PropertiesDock/Resources/Add.png  | Bin 0 -> 491 bytes
 .../PropertiesDock/Resources/Remove.png       | Bin 0 -> 1178 bytes
 15 files changed, 1505 insertions(+), 49 deletions(-)
 delete mode 100644 Build/Plugins/PropertiesDock.pdb
 create mode 100644 Source/Plugins/PropertiesDock/Data/MapElementsData.cs
 create mode 100644 Source/Plugins/PropertiesDock/Data/PropertyBag.cs
 create mode 100644 Source/Plugins/PropertiesDock/Info/ThingInfo.cs
 create mode 100644 Source/Plugins/PropertiesDock/Properties/Resources.Designer.cs
 create mode 100644 Source/Plugins/PropertiesDock/Properties/Resources.resx
 create mode 100644 Source/Plugins/PropertiesDock/Resources/Add.png
 create mode 100644 Source/Plugins/PropertiesDock/Resources/Remove.png

diff --git a/Build/Plugins/PropertiesDock.dll b/Build/Plugins/PropertiesDock.dll
index b5cf4a461169dc7aedffa36be3973696d681488d..c21b458af23fac405c9014569555b96cb034be13 100644
GIT binary patch
literal 33792
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
OiX)f*{rvyuf&T*&wDQOR

literal 14336
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
MHGeSTcl5yj0Q9dfQ2+n{

diff --git a/Build/Plugins/PropertiesDock.pdb b/Build/Plugins/PropertiesDock.pdb
deleted file mode 100644
index e8cbabed6a18cc795839e82d845ada6a3d5bf555..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 36352
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%0DP8evpdjL`)=a%X;uHK2UxSVS#KYyc-lPE
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

diff --git a/Source/Plugins/PropertiesDock/BuilderPlug.cs b/Source/Plugins/PropertiesDock/BuilderPlug.cs
index e2bc19ded..7790085aa 100644
--- a/Source/Plugins/PropertiesDock/BuilderPlug.cs
+++ b/Source/Plugins/PropertiesDock/BuilderPlug.cs
@@ -38,7 +38,9 @@ namespace CodeImp.DoomBuilder.PropertiesDock
 
 		// This is called after a map has been successfully opened
 		public override void OnMapOpenEnd() {
-			if(propertiesDocker == null) {
+            MapElementsData.Init();
+            
+            if(propertiesDocker == null) {
 				propertiesDocker = new PropertiesDocker();
 				docker = new Docker("propertiesdockerpanel", "Properties", propertiesDocker);
 				General.Interface.AddDocker(docker);
diff --git a/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.Designer.cs b/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.Designer.cs
index a5c37c0c9..864477dc6 100644
--- a/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.Designer.cs
+++ b/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.Designer.cs
@@ -29,14 +29,18 @@
             this.tabPage1 = new System.Windows.Forms.TabPage();
             this.propertyGrid1 = new System.Windows.Forms.PropertyGrid();
             this.tabPage2 = new System.Windows.Forms.TabPage();
-            this.textBox1 = new System.Windows.Forms.TextBox();
             this.propertyGrid2 = new System.Windows.Forms.PropertyGrid();
             this.tabPage3 = new System.Windows.Forms.TabPage();
             this.propertyGrid3 = new System.Windows.Forms.PropertyGrid();
+            this.gbCustomFields = new System.Windows.Forms.GroupBox();
+            this.cbFieldType = new System.Windows.Forms.ComboBox();
+            this.bAddField = new System.Windows.Forms.Button();
+            this.tbFieldName = new System.Windows.Forms.TextBox();
             this.tabControl.SuspendLayout();
             this.tabPage1.SuspendLayout();
             this.tabPage2.SuspendLayout();
             this.tabPage3.SuspendLayout();
+            this.gbCustomFields.SuspendLayout();
             this.SuspendLayout();
             // 
             // tabControl
@@ -48,10 +52,10 @@
             this.tabControl.Controls.Add(this.tabPage2);
             this.tabControl.Controls.Add(this.tabPage3);
             this.tabControl.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
-            this.tabControl.Location = new System.Drawing.Point(3, 3);
+            this.tabControl.Location = new System.Drawing.Point(3, 56);
             this.tabControl.Name = "tabControl";
             this.tabControl.SelectedIndex = 0;
-            this.tabControl.Size = new System.Drawing.Size(266, 288);
+            this.tabControl.Size = new System.Drawing.Size(266, 341);
             this.tabControl.TabIndex = 0;
             // 
             // tabPage1
@@ -60,7 +64,7 @@
             this.tabPage1.Location = new System.Drawing.Point(4, 23);
             this.tabPage1.Name = "tabPage1";
             this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
-            this.tabPage1.Size = new System.Drawing.Size(258, 261);
+            this.tabPage1.Size = new System.Drawing.Size(258, 314);
             this.tabPage1.TabIndex = 0;
             this.tabPage1.Text = "tabPage1";
             this.tabPage1.UseVisualStyleBackColor = true;
@@ -73,7 +77,7 @@
             this.propertyGrid1.HelpVisible = false;
             this.propertyGrid1.Location = new System.Drawing.Point(6, 6);
             this.propertyGrid1.Name = "propertyGrid1";
-            this.propertyGrid1.Size = new System.Drawing.Size(246, 249);
+            this.propertyGrid1.Size = new System.Drawing.Size(246, 302);
             this.propertyGrid1.TabIndex = 0;
             this.propertyGrid1.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid1_PropertyValueChanged);
             // 
@@ -83,21 +87,11 @@
             this.tabPage2.Location = new System.Drawing.Point(4, 23);
             this.tabPage2.Name = "tabPage2";
             this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
-            this.tabPage2.Size = new System.Drawing.Size(258, 261);
+            this.tabPage2.Size = new System.Drawing.Size(258, 308);
             this.tabPage2.TabIndex = 1;
             this.tabPage2.Text = "tabPage2";
             this.tabPage2.UseVisualStyleBackColor = true;
             // 
-            // textBox1
-            // 
-            this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
-                        | System.Windows.Forms.AnchorStyles.Right)));
-            this.textBox1.Location = new System.Drawing.Point(3, 293);
-            this.textBox1.Multiline = true;
-            this.textBox1.Name = "textBox1";
-            this.textBox1.Size = new System.Drawing.Size(266, 104);
-            this.textBox1.TabIndex = 1;
-            // 
             // propertyGrid2
             // 
             this.propertyGrid2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@@ -106,7 +100,7 @@
             this.propertyGrid2.HelpVisible = false;
             this.propertyGrid2.Location = new System.Drawing.Point(6, 6);
             this.propertyGrid2.Name = "propertyGrid2";
-            this.propertyGrid2.Size = new System.Drawing.Size(246, 249);
+            this.propertyGrid2.Size = new System.Drawing.Size(246, 296);
             this.propertyGrid2.TabIndex = 1;
             this.propertyGrid2.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid2_PropertyValueChanged);
             // 
@@ -115,7 +109,7 @@
             this.tabPage3.Controls.Add(this.propertyGrid3);
             this.tabPage3.Location = new System.Drawing.Point(4, 23);
             this.tabPage3.Name = "tabPage3";
-            this.tabPage3.Size = new System.Drawing.Size(258, 261);
+            this.tabPage3.Size = new System.Drawing.Size(258, 308);
             this.tabPage3.TabIndex = 2;
             this.tabPage3.Text = "tabPage3";
             this.tabPage3.UseVisualStyleBackColor = true;
@@ -128,15 +122,61 @@
             this.propertyGrid3.HelpVisible = false;
             this.propertyGrid3.Location = new System.Drawing.Point(6, 6);
             this.propertyGrid3.Name = "propertyGrid3";
-            this.propertyGrid3.Size = new System.Drawing.Size(246, 249);
+            this.propertyGrid3.Size = new System.Drawing.Size(246, 296);
             this.propertyGrid3.TabIndex = 1;
             this.propertyGrid3.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid3_PropertyValueChanged);
             // 
+            // gbCustomFields
+            // 
+            this.gbCustomFields.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbCustomFields.Controls.Add(this.tbFieldName);
+            this.gbCustomFields.Controls.Add(this.bAddField);
+            this.gbCustomFields.Controls.Add(this.cbFieldType);
+            this.gbCustomFields.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.gbCustomFields.Location = new System.Drawing.Point(3, 3);
+            this.gbCustomFields.Name = "gbCustomFields";
+            this.gbCustomFields.Size = new System.Drawing.Size(266, 47);
+            this.gbCustomFields.TabIndex = 1;
+            this.gbCustomFields.TabStop = false;
+            this.gbCustomFields.Text = "Add custom field:";
+            // 
+            // cbFieldType
+            // 
+            this.cbFieldType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.cbFieldType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cbFieldType.FormattingEnabled = true;
+            this.cbFieldType.Location = new System.Drawing.Point(148, 19);
+            this.cbFieldType.Name = "cbFieldType";
+            this.cbFieldType.Size = new System.Drawing.Size(80, 22);
+            this.cbFieldType.TabIndex = 0;
+            // 
+            // bAddField
+            // 
+            this.bAddField.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.bAddField.Image = global::CodeImp.DoomBuilder.PropertiesDock.Properties.Resources.Add;
+            this.bAddField.Location = new System.Drawing.Point(232, 19);
+            this.bAddField.Name = "bAddField";
+            this.bAddField.Size = new System.Drawing.Size(28, 23);
+            this.bAddField.TabIndex = 1;
+            this.bAddField.UseVisualStyleBackColor = true;
+            this.bAddField.Click += new System.EventHandler(this.bAddField_Click);
+            // 
+            // tbFieldName
+            // 
+            this.tbFieldName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.tbFieldName.Location = new System.Drawing.Point(10, 20);
+            this.tbFieldName.Name = "tbFieldName";
+            this.tbFieldName.Size = new System.Drawing.Size(134, 20);
+            this.tbFieldName.TabIndex = 3;
+            // 
             // PropertiesDocker
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
-            this.Controls.Add(this.textBox1);
+            this.Controls.Add(this.gbCustomFields);
             this.Controls.Add(this.tabControl);
             this.Font = new System.Drawing.Font("Arial Narrow", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
             this.Name = "PropertiesDocker";
@@ -145,8 +185,9 @@
             this.tabPage1.ResumeLayout(false);
             this.tabPage2.ResumeLayout(false);
             this.tabPage3.ResumeLayout(false);
+            this.gbCustomFields.ResumeLayout(false);
+            this.gbCustomFields.PerformLayout();
             this.ResumeLayout(false);
-            this.PerformLayout();
 
 		}
 
@@ -155,10 +196,13 @@
 		private System.Windows.Forms.TabControl tabControl;
 		private System.Windows.Forms.TabPage tabPage1;
 		private System.Windows.Forms.TabPage tabPage2;
-		private System.Windows.Forms.PropertyGrid propertyGrid1;
-        private System.Windows.Forms.TextBox textBox1;
+        private System.Windows.Forms.PropertyGrid propertyGrid1;
         private System.Windows.Forms.PropertyGrid propertyGrid2;
         private System.Windows.Forms.TabPage tabPage3;
         private System.Windows.Forms.PropertyGrid propertyGrid3;
+        private System.Windows.Forms.GroupBox gbCustomFields;
+        private System.Windows.Forms.Button bAddField;
+        private System.Windows.Forms.ComboBox cbFieldType;
+        private System.Windows.Forms.TextBox tbFieldName;
 	}
 }
diff --git a/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.cs b/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.cs
index 7bac3006c..3b7486db0 100644
--- a/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.cs
+++ b/Source/Plugins/PropertiesDock/Controls/PropertiesDocker.cs
@@ -16,12 +16,24 @@ namespace CodeImp.DoomBuilder.PropertiesDock
         private TabPage page3;
 
         private string currentMode;
+        private static PropertiesDocker me;
         
         public PropertiesDocker() {
 			InitializeComponent();
 
+            me = this;
             page2 = tabControl.TabPages[1];
             page3 = tabControl.TabPages[2];
+
+            if (!General.Map.UDMF) {
+                gbCustomFields.Visible = false;
+                tabControl.Top = 3;
+            } else {
+                //todo: add "Delete field" button
+
+                //todo: sort this out...
+                //cbFieldType.Items.AddRange(General.Types.GetCustomUseAttributes());
+            }
 		}
 
 //SHOW HIGHLIGHT INFO
@@ -34,12 +46,13 @@ namespace CodeImp.DoomBuilder.PropertiesDock
         }
 
         public void ShowThingInfo(Thing t) {
-
+            propertyGrid1.SelectedObject = new ThingInfo(t);
+            viewThings(1, t.Index, true);
         }
 
         public void ShowVertexInfo(Vertex v) {
             propertyGrid1.SelectedObject = new VertexInfo(v);
-            viewVertices(true);
+            viewVertices(1, v.Index, true);
         }
 
         public void OnHighlightLost() {
@@ -47,9 +60,28 @@ namespace CodeImp.DoomBuilder.PropertiesDock
         }
 
 //SHOW SELECTION INFO
+        private void showSelectedThingsInfo() {
+            //anything selected?
+            List<Thing> things = (List<Thing>)General.Map.Map.GetSelectedThings(true);
+
+            if (things.Count > 0) {
+                ThingInfo[] infos = new ThingInfo[things.Count];
+                int i = 0;
+
+                foreach (Thing t in things) {
+                    infos[i++] = new ThingInfo(t);
+                }
+
+                propertyGrid1.SelectedObjects = infos;
+                viewThings(things.Count, things.Count == 1 ? things[0].Index : -1, true);
+            } else {
+                viewThings(-1, -1, false);
+            }
+        }
+        
         private void showSelectedVerticesInfo() {
             //anything selected?
-            ICollection<Vertex> verts = General.Map.Map.GetSelectedVertices(true);
+            List<Vertex> verts = (List<Vertex>)General.Map.Map.GetSelectedVertices(true);
 
             if (verts.Count > 0) {
                 VertexInfo[] infos = new VertexInfo[verts.Count];
@@ -60,30 +92,52 @@ namespace CodeImp.DoomBuilder.PropertiesDock
                 }
 
                 propertyGrid1.SelectedObjects = infos;
-                viewVertices(true);
+                viewVertices(verts.Count, verts.Count == 1 ? verts[0].Index : -1, true);
             } else {
-                //propertyGrid1.SelectedObjects = null;
-                viewVertices(false);
+                viewVertices(-1, -1, false);
             }
         }
 
 //PANELS UPDATE
-        private void viewVertices(bool enabled) {
-            propertyGrid1.Enabled = enabled;
-            tabControl.TabPages[0].Text = "Vertex:";
+        private void viewVertices(int count, int index, bool enabled) {
+            updateTabs(enabled, false);
+
+            if(count != -1)
+                tabControl.TabPages[0].Text = count > 1 ? count + " vertices:" : "Vertex "+index+":";
+        }
 
-            if (tabControl.TabPages.Count > 1) {
-                tabControl.TabPages.Remove(page2);
-                tabControl.TabPages.Remove(page3);
+        private void viewThings(int count, int index, bool enabled) {
+            updateTabs(enabled, false);
+
+            if (count != -1)
+                tabControl.TabPages[0].Text = count > 1 ? count + " things:" : "Thing " + index + ":";
+        }
+
+        private void updateTabs(bool enabled, bool showAllTabs) {
+            if (showAllTabs) {
+                if (tabControl.TabPages.Count == 1) {
+                    tabControl.TabPages.Add(page2);
+                    tabControl.TabPages.Add(page3);
+                }
+                propertyGrid2.Enabled = enabled;
+                propertyGrid3.Enabled = enabled;
+
+            } else {
+                if (tabControl.TabPages.Count == 3) {
+                    tabControl.TabPages.Remove(page2);
+                    tabControl.TabPages.Remove(page3);
+                }
             }
+            propertyGrid1.Enabled = enabled;
         }
 
 //util
         public void ChangeEditMode(string name) {
-            textBox1.AppendText("Mode Changed to " + name + Environment.NewLine);
+            //textBox1.AppendText("Mode Changed to " + name + Environment.NewLine);
             
             if (name == "ThingsMode") {
                 currentMode = name;
+                showSelectedThingsInfo();
 
             } else if (name == "SectorsMode") {
                 currentMode = name;
@@ -105,6 +159,12 @@ namespace CodeImp.DoomBuilder.PropertiesDock
             ChangeEditMode(currentMode);
         }
 
+        public static void Refresh() {
+            me.propertyGrid1.Refresh();
+            me.propertyGrid2.Refresh();
+            me.propertyGrid3.Refresh();
+        }
+
         private void saveChanges() {
             if (currentMode == "ThingsMode" && propertyGrid1.Enabled) {
                 applyThingChanges();
@@ -120,7 +180,7 @@ namespace CodeImp.DoomBuilder.PropertiesDock
         }
 
         private void applyThingChanges() {
-            throw new NotImplementedException();
+            //throw new NotImplementedException();
         }
 
         private void applySectorChanges() {
@@ -168,5 +228,26 @@ namespace CodeImp.DoomBuilder.PropertiesDock
         private void propertyGrid3_PropertyValueChanged(object s, PropertyValueChangedEventArgs e) {
             saveChanges();
         }
+
+        private void bAddField_Click(object sender, EventArgs e) {
+            PropertyGrid g = null;
+            
+            if (tbFieldName.Text.Length > 0) {
+                if (tabControl.SelectedIndex == 0) {
+                    g = propertyGrid1;
+                } else if (tabControl.SelectedIndex == 1) {
+                    g = propertyGrid2;
+                } else if (tabControl.SelectedIndex == 2) {
+                    g = propertyGrid3;
+                }
+            }
+
+            if (g != null && g.Enabled && g.SelectedObjects.Length > 0) {
+                foreach (object o in g.SelectedObjects) {
+                    //todo: set correct type
+                    ((IMapElementInfo)o).AddCustomProperty(tbFieldName.Text, typeof(string));
+                }
+            }
+        }
 	}
 }
diff --git a/Source/Plugins/PropertiesDock/Data/MapElementsData.cs b/Source/Plugins/PropertiesDock/Data/MapElementsData.cs
new file mode 100644
index 000000000..08ae54687
--- /dev/null
+++ b/Source/Plugins/PropertiesDock/Data/MapElementsData.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using CodeImp.DoomBuilder.Config;
+
+namespace CodeImp.DoomBuilder.PropertiesDock {
+    public static class MapElementsData {
+
+        public static Dictionary<int, string> ThingTypeDescriptions { get { return thingTypeDescriptions;}}
+        private static Dictionary<int, string> thingTypeDescriptions;
+        
+        public static void Init() {
+            //thing types
+            thingTypeDescriptions = new Dictionary<int, string>();
+
+            foreach (ThingCategory tc in General.Map.Data.ThingCategories) {
+                foreach (ThingTypeInfo ti in tc.Things) {
+                    thingTypeDescriptions.Add(ti.Index, ti.Title);
+                }
+            }
+        }
+    }
+}
diff --git a/Source/Plugins/PropertiesDock/Data/PropertyBag.cs b/Source/Plugins/PropertiesDock/Data/PropertyBag.cs
new file mode 100644
index 000000000..0bf7ce037
--- /dev/null
+++ b/Source/Plugins/PropertiesDock/Data/PropertyBag.cs
@@ -0,0 +1,979 @@
+/********************************************************************
+ *
+ *  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 {
+    /// <summary>
+    /// Represents a single property in a PropertySpec.
+    /// </summary>
+    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
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        public PropertySpec(string name, string type) : this(name, type, null, null, null) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        public PropertySpec(string name, Type type) :
+            this(name, type.AssemblyQualifiedName, null, null, null) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        public PropertySpec(string name, string type, string category) : this(name, type, category, null, null) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        /// <param name="category"></param>
+        public PropertySpec(string name, Type type, string category) :
+            this(name, type.AssemblyQualifiedName, category, null, null) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        public PropertySpec(string name, string type, string category, string description) :
+            this(name, type, category, description, null) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        public PropertySpec(string name, Type type, string category, string description) :
+            this(name, type.AssemblyQualifiedName, category, description, null) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        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
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        public PropertySpec(string name, Type type, string category, string description, object defaultValue) :
+            this(name, type.AssemblyQualifiedName, category, description, defaultValue) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The fully qualified name of the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The fully qualified name of the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The fully qualified name of the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The fully qualified name of the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The Type that represents the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The fully qualified name of the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The Type that represents the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The fully qualified name of the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The fully qualified name of the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The Type that represents the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The fully qualified name of the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The Type that represents the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">The fully qualified name of the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The Type that represents the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The Type that represents the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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) { }
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpec class.
+        /// </summary>
+        /// <param name="name">The name of the property displayed in the property grid.</param>
+        /// <param name="type">A Type that represents the type of the property.</param>
+        /// <param name="category">The category under which the property is displayed in the
+        /// property grid.</param>
+        /// <param name="description">A string that is displayed in the help area of the
+        /// property grid.</param>
+        /// <param name="defaultValue">The default value of the property, or null if there is
+        /// no default value.</param>
+        /// <param name="editor">The Type that represents the type of the editor for this
+        /// property.  This type must derive from UITypeEditor.</param>
+        /// <param name="typeConverter">The Type that represents the type of the type
+        /// converter for this property.  This type must derive from TypeConverter.</param>
+        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) { }
+
+        /// <summary>
+        /// 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.
+        /// </summary>
+        public Attribute[] Attributes {
+            get { return attributes; }
+            set { attributes = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the category name of this property.
+        /// </summary>
+        public string Category {
+            get { return category; }
+            set { category = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the fully qualified name of the type converter
+        /// type for this property.
+        /// </summary>
+        public string ConverterTypeName {
+            get { return typeConverter; }
+            set { typeConverter = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the default value of this property.
+        /// </summary>
+        public object DefaultValue {
+            get { return defaultValue; }
+            set { defaultValue = value; }
+        }
+
+        //mxd
+        /// <summary>
+        /// Gets or sets the value of this property.
+        /// </summary>
+        public object Value {
+            get { return currentValue; }
+            set { currentValue = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the help text description of this property.
+        /// </summary>
+        public string Description {
+            get { return description; }
+            set { description = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the fully qualified name of the editor type for
+        /// this property.
+        /// </summary>
+        public string EditorTypeName {
+            get { return editor; }
+            set { editor = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the name of this property.
+        /// </summary>
+        public string Name {
+            get { return name; }
+            set { name = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the fully qualfied name of the type of this
+        /// property.
+        /// </summary>
+        public string TypeName {
+            get { return type; }
+            set { type = value; }
+        }
+    }
+
+    /// <summary>
+    /// Provides data for the GetValue and SetValue events of the PropertyBag class.
+    /// </summary>
+    public class PropertySpecEventArgs : EventArgs {
+        private PropertySpec property;
+        private object val;
+
+        /// <summary>
+        /// Initializes a new instance of the PropertySpecEventArgs class.
+        /// </summary>
+        /// <param name="property">The PropertySpec that represents the property whose
+        /// value is being requested or set.</param>
+        /// <param name="val">The current value of the property.</param>
+        public PropertySpecEventArgs(PropertySpec property, object val) {
+            this.property = property;
+            this.val = val;
+        }
+
+        /// <summary>
+        /// Gets the PropertySpec that represents the property whose value is being
+        /// requested or set.
+        /// </summary>
+        public PropertySpec Property {
+            get { return property; }
+        }
+
+        /// <summary>
+        /// Gets or sets the current value of the property.
+        /// </summary>
+        public object Value {
+            get { return val; }
+            set { val = value; }
+        }
+    }
+
+    /// <summary>
+    /// Represents the method that will handle the GetValue and SetValue events of the
+    /// PropertyBag class.
+    /// </summary>
+    public delegate void PropertySpecEventHandler(object sender, PropertySpecEventArgs e);
+
+    /// <summary>
+    /// 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.
+    /// </summary>
+    public class PropertyBag : ICustomTypeDescriptor {
+        #region PropertySpecCollection class definition
+        /// <summary>
+        /// Encapsulates a collection of PropertySpec objects.
+        /// </summary>
+        [Serializable]
+        public class PropertySpecCollection : IList {
+            private ArrayList innerArray;
+
+            /// <summary>
+            /// Initializes a new instance of the PropertySpecCollection class.
+            /// </summary>
+            public PropertySpecCollection() {
+                innerArray = new ArrayList();
+            }
+
+            /// <summary>
+            /// Gets the number of elements in the PropertySpecCollection.
+            /// </summary>
+            /// <value>
+            /// The number of elements contained in the PropertySpecCollection.
+            /// </value>
+            public int Count {
+                get { return innerArray.Count; }
+            }
+
+            /// <summary>
+            /// Gets a value indicating whether the PropertySpecCollection has a fixed size.
+            /// </summary>
+            /// <value>
+            /// true if the PropertySpecCollection has a fixed size; otherwise, false.
+            /// </value>
+            public bool IsFixedSize {
+                get { return false; }
+            }
+
+            /// <summary>
+            /// Gets a value indicating whether the PropertySpecCollection is read-only.
+            /// </summary>
+            public bool IsReadOnly {
+                get { return false; }
+            }
+
+            /// <summary>
+            /// Gets a value indicating whether access to the collection is synchronized (thread-safe).
+            /// </summary>
+            /// <value>
+            /// true if access to the PropertySpecCollection is synchronized (thread-safe); otherwise, false.
+            /// </value>
+            public bool IsSynchronized {
+                get { return false; }
+            }
+
+            /// <summary>
+            /// Gets an object that can be used to synchronize access to the collection.
+            /// </summary>
+            /// <value>
+            /// An object that can be used to synchronize access to the collection.
+            /// </value>
+            object ICollection.SyncRoot {
+                get { return null; }
+            }
+
+            /// <summary>
+            /// Gets or sets the element at the specified index.
+            /// In C#, this property is the indexer for the PropertySpecCollection class.
+            /// </summary>
+            /// <param name="index">The zero-based index of the element to get or set.</param>
+            /// <value>
+            /// The element at the specified index.
+            /// </value>
+            public PropertySpec this[int index] {
+                get { return (PropertySpec)innerArray[index]; }
+                set { innerArray[index] = value; }
+            }
+
+            /// <summary>
+            /// Adds a PropertySpec to the end of the PropertySpecCollection.
+            /// </summary>
+            /// <param name="value">The PropertySpec to be added to the end of the PropertySpecCollection.</param>
+            /// <returns>The PropertySpecCollection index at which the value has been added.</returns>
+            public int Add(PropertySpec value) {
+                int index = innerArray.Add(value);
+
+                return index;
+            }
+
+            /// <summary>
+            /// Adds the elements of an array of PropertySpec objects to the end of the PropertySpecCollection.
+            /// </summary>
+            /// <param name="array">The PropertySpec array whose elements should be added to the end of the
+            /// PropertySpecCollection.</param>
+            public void AddRange(PropertySpec[] array) {
+                innerArray.AddRange(array);
+            }
+
+            /// <summary>
+            /// Removes all elements from the PropertySpecCollection.
+            /// </summary>
+            public void Clear() {
+                innerArray.Clear();
+            }
+
+            /// <summary>
+            /// Determines whether a PropertySpec is in the PropertySpecCollection.
+            /// </summary>
+            /// <param name="item">The PropertySpec to locate in the PropertySpecCollection. The element to locate
+            /// can be a null reference (Nothing in Visual Basic).</param>
+            /// <returns>true if item is found in the PropertySpecCollection; otherwise, false.</returns>
+            public bool Contains(PropertySpec item) {
+                return innerArray.Contains(item);
+            }
+
+            /// <summary>
+            /// Determines whether a PropertySpec with the specified name is in the PropertySpecCollection.
+            /// </summary>
+            /// <param name="name">The name of the PropertySpec to locate in the PropertySpecCollection.</param>
+            /// <returns>true if item is found in the PropertySpecCollection; otherwise, false.</returns>
+            public bool Contains(string name) {
+                foreach (PropertySpec spec in innerArray)
+                    if (spec.Name == name)
+                        return true;
+
+                return false;
+            }
+
+            /// <summary>
+            /// Copies the entire PropertySpecCollection to a compatible one-dimensional Array, starting at the
+            /// beginning of the target array.
+            /// </summary>
+            /// <param name="array">The one-dimensional Array that is the destination of the elements copied
+            /// from PropertySpecCollection. The Array must have zero-based indexing.</param>
+            public void CopyTo(PropertySpec[] array) {
+                innerArray.CopyTo(array);
+            }
+
+            /// <summary>
+            /// Copies the PropertySpecCollection or a portion of it to a one-dimensional array.
+            /// </summary>
+            /// <param name="array">The one-dimensional Array that is the destination of the elements copied
+            /// from the collection.</param>
+            /// <param name="index">The zero-based index in array at which copying begins.</param>
+            public void CopyTo(PropertySpec[] array, int index) {
+                innerArray.CopyTo(array, index);
+            }
+
+            /// <summary>
+            /// Returns an enumerator that can iterate through the PropertySpecCollection.
+            /// </summary>
+            /// <returns>An IEnumerator for the entire PropertySpecCollection.</returns>
+            public IEnumerator GetEnumerator() {
+                return innerArray.GetEnumerator();
+            }
+
+            /// <summary>
+            /// Searches for the specified PropertySpec and returns the zero-based index of the first
+            /// occurrence within the entire PropertySpecCollection.
+            /// </summary>
+            /// <param name="value">The PropertySpec to locate in the PropertySpecCollection.</param>
+            /// <returns>The zero-based index of the first occurrence of value within the entire PropertySpecCollection,
+            /// if found; otherwise, -1.</returns>
+            public int IndexOf(PropertySpec value) {
+                return innerArray.IndexOf(value);
+            }
+
+            /// <summary>
+            /// Searches for the PropertySpec with the specified name and returns the zero-based index of
+            /// the first occurrence within the entire PropertySpecCollection.
+            /// </summary>
+            /// <param name="name">The name of the PropertySpec to locate in the PropertySpecCollection.</param>
+            /// <returns>The zero-based index of the first occurrence of value within the entire PropertySpecCollection,
+            /// if found; otherwise, -1.</returns>
+            public int IndexOf(string name) {
+                int i = 0;
+
+                foreach (PropertySpec spec in innerArray) {
+                    if (spec.Name == name)
+                        return i;
+
+                    i++;
+                }
+
+                return -1;
+            }
+
+            /// <summary>
+            /// Inserts a PropertySpec object into the PropertySpecCollection at the specified index.
+            /// </summary>
+            /// <param name="index">The zero-based index at which value should be inserted.</param>
+            /// <param name="value">The PropertySpec to insert.</param>
+            public void Insert(int index, PropertySpec value) {
+                innerArray.Insert(index, value);
+            }
+
+            /// <summary>
+            /// Removes the first occurrence of a specific object from the PropertySpecCollection.
+            /// </summary>
+            /// <param name="obj">The PropertySpec to remove from the PropertySpecCollection.</param>
+            public void Remove(PropertySpec obj) {
+                innerArray.Remove(obj);
+            }
+
+            /// <summary>
+            /// Removes the property with the specified name from the PropertySpecCollection.
+            /// </summary>
+            /// <param name="name">The name of the PropertySpec to remove from the PropertySpecCollection.</param>
+            public void Remove(string name) {
+                int index = IndexOf(name);
+                RemoveAt(index);
+            }
+
+            /// <summary>
+            /// Removes the object at the specified index of the PropertySpecCollection.
+            /// </summary>
+            /// <param name="index">The zero-based index of the element to remove.</param>
+            public void RemoveAt(int index) {
+                innerArray.RemoveAt(index);
+            }
+
+            /// <summary>
+            /// Copies the elements of the PropertySpecCollection to a new PropertySpec array.
+            /// </summary>
+            /// <returns>A PropertySpec array containing copies of the elements of the PropertySpecCollection.</returns>
+            public PropertySpec[] ToArray() {
+                return (PropertySpec[])innerArray.ToArray(typeof(PropertySpec));
+            }
+
+            #region Explicit interface implementations for ICollection and IList
+            /// <summary>
+            /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+            /// </summary>
+            void ICollection.CopyTo(Array array, int index) {
+                CopyTo((PropertySpec[])array, index);
+            }
+
+            /// <summary>
+            /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+            /// </summary>
+            int IList.Add(object value) {
+                return Add((PropertySpec)value);
+            }
+
+            /// <summary>
+            /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+            /// </summary>
+            bool IList.Contains(object obj) {
+                return Contains((PropertySpec)obj);
+            }
+
+            /// <summary>
+            /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+            /// </summary>
+            object IList.this[int index] {
+                get {
+                    return ((PropertySpecCollection)this)[index];
+                }
+                set {
+                    ((PropertySpecCollection)this)[index] = (PropertySpec)value;
+                }
+            }
+
+            /// <summary>
+            /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+            /// </summary>
+            int IList.IndexOf(object obj) {
+                return IndexOf((PropertySpec)obj);
+            }
+
+            /// <summary>
+            /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+            /// </summary>
+            void IList.Insert(int index, object value) {
+                Insert(index, (PropertySpec)value);
+            }
+
+            /// <summary>
+            /// This member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
+            /// </summary>
+            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
+
+        /// <summary>
+        /// Initializes a new instance of the PropertyBag class.
+        /// </summary>
+        public PropertyBag() {
+            defaultProperty = null;
+            properties = new PropertySpecCollection();
+        }
+
+        /// <summary>
+        /// Gets or sets the name of the default property in the collection.
+        /// </summary>
+        public string DefaultProperty {
+            get { return defaultProperty; }
+            set { defaultProperty = value; }
+        }
+
+        /// <summary>
+        /// Gets the collection of properties contained within this PropertyBag.
+        /// </summary>
+        public PropertySpecCollection Properties {
+            get { return properties; }
+        }
+
+        /// <summary>
+        /// Occurs when a PropertyGrid requests the value of a property.
+        /// </summary>
+        public event PropertySpecEventHandler GetValue;
+
+        /// <summary>
+        /// Occurs when the user changes the value of a property in a PropertyGrid.
+        /// </summary>
+        public event PropertySpecEventHandler SetValue;
+
+        /// <summary>
+        /// Raises the GetValue event.
+        /// </summary>
+        /// <param name="e">A PropertySpecEventArgs that contains the event data.</param>
+        protected virtual void OnGetValue(PropertySpecEventArgs e) {
+            if (GetValue != null)
+                GetValue(this, e);
+        }
+
+        /// <summary>
+        /// Raises the SetValue event.
+        /// </summary>
+        /// <param name="e">A PropertySpecEventArgs that contains the event data.</param>
+        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
+    }
+
+    /// <summary>
+    /// An extension of PropertyBag that manages a table of property values, in
+    /// addition to firing events when property values are requested or set.
+    /// </summary>
+    public class PropertyTable : PropertyBag {
+        private Hashtable propValues;
+
+        /// <summary>
+        /// Initializes a new instance of the PropertyTable class.
+        /// </summary>
+        public PropertyTable() {
+            propValues = new Hashtable();
+        }
+
+        /// <summary>
+        /// Gets or sets the value of the property with the specified name.
+        /// <p>In C#, this property is the indexer of the PropertyTable class.</p>
+        /// </summary>
+        public object this[string key] {
+            get { return propValues[key]; }
+            set { propValues[key] = value; }
+        }
+
+        /// <summary>
+        /// This member overrides PropertyBag.OnGetValue.
+        /// </summary>
+        protected override void OnGetValue(PropertySpecEventArgs e) {
+            e.Value = propValues[e.Property.Name];
+            base.OnGetValue(e);
+        }
+
+        /// <summary>
+        /// This member overrides PropertyBag.OnSetValue.
+        /// </summary>
+        protected override void OnSetValue(PropertySpecEventArgs e) {
+            propValues[e.Property.Name] = e.Value;
+            base.OnSetValue(e);
+        }
+    }
+}
diff --git a/Source/Plugins/PropertiesDock/Info/IMapElementInfo.cs b/Source/Plugins/PropertiesDock/Info/IMapElementInfo.cs
index c7e6bd423..624ca45a8 100644
--- a/Source/Plugins/PropertiesDock/Info/IMapElementInfo.cs
+++ b/Source/Plugins/PropertiesDock/Info/IMapElementInfo.cs
@@ -6,5 +6,7 @@ using System.Text;
 namespace CodeImp.DoomBuilder.PropertiesDock {
     interface IMapElementInfo {
         void ApplyChanges();
+        void AddCustomProperty(string name, Type type);
+        void RemoveCustomProperty(string name);
     }
 }
diff --git a/Source/Plugins/PropertiesDock/Info/ThingInfo.cs b/Source/Plugins/PropertiesDock/Info/ThingInfo.cs
new file mode 100644
index 000000000..f51c1a085
--- /dev/null
+++ b/Source/Plugins/PropertiesDock/Info/ThingInfo.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.ComponentModel;
+using CodeImp.DoomBuilder.Map;
+using System.Globalization;
+
+namespace CodeImp.DoomBuilder.PropertiesDock {
+    public class ThingInfo : IMapElementInfo {
+
+        [TypeConverterAttribute(typeof(ThingTypeConverter)), CategoryAttribute("General"), DefaultValueAttribute(0)]
+        public int Type { get { return type; } set { type = value; } }
+        private int type;
+
+        private Thing thing;
+
+        public ThingInfo(Thing t) {
+            thing = t;
+            type = t.Type;
+        }
+
+        public void ApplyChanges() {
+
+        }
+
+        public void AddCustomProperty(string name, Type type) {
+            //properties.Add(new PropertySpec(name + ":", value.GetType(), "Custom properties:"));
+        }
+
+        public void RemoveCustomProperty(string name) {
+            /*string n = name.ToUpperInvariant().Trim();
+            foreach (PropertySpec ps in properties) {
+                string cn = ps.Name.ToUpperInvariant();
+                if (cn.IndexOf(n) == 0 && cn.Length == n.Length + 1) {
+                    properties.Remove(name);
+                    return;
+                }
+            }*/
+        }
+    }
+
+    public class ThingTypeConverter : TypeConverter {
+
+        public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType) {
+            if (destinationType == typeof(int))
+                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 int) {
+                int type = (int)value;
+                if (MapElementsData.ThingTypeDescriptions.ContainsKey(type)) {
+                    return type + " - " + MapElementsData.ThingTypeDescriptions[type];
+                }
+
+                return type + " - Unknown Thing";
+            }
+            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) {
+                int type = 0;
+                if (!int.TryParse((string)value, out type)) {
+                    //throw new ArgumentException("'" + (string)value + "' is not a valid Thing type");
+                    General.ShowErrorMessage("'" + (string)value + "' is not a valid Thing type", System.Windows.Forms.MessageBoxButtons.OK);
+                }
+                return type;
+            }
+            return base.ConvertFrom(context, culture, value);
+        }
+    }
+}
diff --git a/Source/Plugins/PropertiesDock/Info/VertexInfo.cs b/Source/Plugins/PropertiesDock/Info/VertexInfo.cs
index e1165ed18..623facbe9 100644
--- a/Source/Plugins/PropertiesDock/Info/VertexInfo.cs
+++ b/Source/Plugins/PropertiesDock/Info/VertexInfo.cs
@@ -6,29 +6,51 @@ using System.Text;
 using CodeImp.DoomBuilder.Map;
 
 namespace CodeImp.DoomBuilder.PropertiesDock {
-    public class VertexInfo : IMapElementInfo {
-        [CategoryAttribute("Position"), DefaultValueAttribute(0f)]
-        public float X { get { return x; } set { x = value; } }
-        private float x;
+    
+    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;
+        /*[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;
 
         private Vertex vertex;
 
-        public VertexInfo(Vertex v) {
+        public VertexInfo(Vertex v) : base() {
             vertex = v;
-            x = v.Position.x;
-            y = v.Position.y;
+            //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));
         }
 
         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(x, min, max), General.Clamp(y, min, max)));
+            vertex.Move(new CodeImp.DoomBuilder.Geometry.Vector2D(General.Clamp((float)properties[0].Value, min, max), General.Clamp((float)properties[1].Value, min, max)));
             
             //todo: add custom fields support
         }
+
+        public void AddCustomProperty(string name, Type type) {
+            properties.Add(new PropertySpec(name + ":", type, "Custom properties:"));
+        }
+
+        public void RemoveCustomProperty(string name){
+            string n = name.ToUpperInvariant().Trim();
+            foreach (PropertySpec ps in properties) {
+                string cn = ps.Name.ToUpperInvariant();
+                if (cn.IndexOf(n) == 0 && cn.Length == n.Length + 1) {
+                    properties.Remove(name);
+                    return;
+                }
+            }
+        }
     }
 }
diff --git a/Source/Plugins/PropertiesDock/Properties/Resources.Designer.cs b/Source/Plugins/PropertiesDock/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..6fc6cbb8a
--- /dev/null
+++ b/Source/Plugins/PropertiesDock/Properties/Resources.Designer.cs
@@ -0,0 +1,77 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     Этот код создан программой.
+//     Исполняемая версия:2.0.50727.4927
+//
+//     Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
+//     повторной генерации кода.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CodeImp.DoomBuilder.PropertiesDock.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
+    /// </summary>
+    // Этот класс создан автоматически классом StronglyTypedResourceBuilder
+    // с помощью такого средства, как ResGen или Visual Studio.
+    // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
+    // с параметром /str или перестройте свой проект VS.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeImp.DoomBuilder.PropertiesDock.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Перезаписывает свойство CurrentUICulture текущего потока для всех
+        ///   обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Add {
+            get {
+                object obj = ResourceManager.GetObject("Add", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Remove {
+            get {
+                object obj = ResourceManager.GetObject("Remove", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
diff --git a/Source/Plugins/PropertiesDock/Properties/Resources.resx b/Source/Plugins/PropertiesDock/Properties/Resources.resx
new file mode 100644
index 000000000..00a8973d7
--- /dev/null
+++ b/Source/Plugins/PropertiesDock/Properties/Resources.resx
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="Add" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Remove" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Remove.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/PropertiesDock/PropertiesDock.csproj b/Source/Plugins/PropertiesDock/PropertiesDock.csproj
index 34291d181..e88d90f62 100644
--- a/Source/Plugins/PropertiesDock/PropertiesDock.csproj
+++ b/Source/Plugins/PropertiesDock/PropertiesDock.csproj
@@ -50,10 +50,18 @@
     <Compile Include="Controls\PropertiesDocker.Designer.cs">
       <DependentUpon>PropertiesDocker.cs</DependentUpon>
     </Compile>
+    <Compile Include="Data\MapElementsData.cs" />
+    <Compile Include="Data\PropertyBag.cs" />
     <Compile Include="Data\VertexPosition.cs" />
     <Compile Include="Info\IMapElementInfo.cs" />
+    <Compile Include="Info\ThingInfo.cs" />
     <Compile Include="Info\VertexInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\Core\Builder.csproj">
@@ -66,6 +74,16 @@
     <EmbeddedResource Include="Controls\PropertiesDocker.resx">
       <DependentUpon>PropertiesDocker.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\Add.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\Remove.png" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
diff --git a/Source/Plugins/PropertiesDock/Resources/Add.png b/Source/Plugins/PropertiesDock/Resources/Add.png
new file mode 100644
index 0000000000000000000000000000000000000000..79f062aa94e5c5cff258bb52c2ff79fa1387b6c2
GIT binary patch
literal 491
zcmV<H0Tlj;P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00059Nkl<Zc-muR
zzykV@@cl;@E42B<h)pdcE(0=5pEEpSn9U%^kjgOQv?S>Us4F=#eEIs4L4Z$|;p*+3
zq#K|jZ_V)a+ZzTxUP*?V_YRO|K<^=e|BABu3_pK;X5i)&Ww?F+Btx<N2kZuP?GyeF
zGl~(&f`y*Ej55RTzdso`+4&gmKDdTrBTP-1(_2Qy_Fdxt3+(TK0}KX00k`hH6~o`Z
ze;AmUm>GhVj$_DAIH<%>>GqP5v3Z;He<gWYhF|~RgUyDxf)T|<$hLymY)oPdcOTwk
zsP%fv$XLHo@xPK1FT<aIUyxM7bTdN5pvHhh;XeaAlL*7@yRR7<{qHj}R<BY0kLo!_
z21cM}dF5YF+y65>xXTVv@Sg$6Ees5;A-5T^hHUu?t^bN@A0Ql{`UkfK7&;=Zp{Q-$
zq9<GJbLlZw14@?Y{a4g@3AP;s?%j}J=!v;Rd^#vxVDw*E`ytrtAO&}?%QN)HpCjIY
z{COt-Ei5_U{1eB2FicE3L$m>+Km%T(3jz%g@JMF=3S=??@t+-YfBwT}fH)8f05LZZ
h^P$Pzg3`~B1p%Q@rV#+WrRx9y002ovPDHLkV1j^q;v)b6

literal 0
HcmV?d00001

diff --git a/Source/Plugins/PropertiesDock/Resources/Remove.png b/Source/Plugins/PropertiesDock/Resources/Remove.png
new file mode 100644
index 0000000000000000000000000000000000000000..9f5eda7d5d79583d6d7d07b53ddb94181ae3b861
GIT binary patch
literal 1178
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+m=!WZB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+*
zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn
zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV
z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj
z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPA<wUD9OyvQvjKmn3P{y
zVygsnDZ~r81#n~YilM;-3^4tQ!~%UoJp+)JU<!SG@hi>Eg{v+u2}(t{7puX=A(aKG
z`a!A1`K3k4z=%sz23b{L<y@4SSdw29lAoUg3&ntp{F40QjQj!x=U`KX@XWlF{PJS3
zYF}R~&%EN2#JuEGPZwJypnko~%oHm#7h^{=Crd+TBS%+5Lsvr!H%DhzHxpMQH)jiD
z6E_2xUYGpj(%jU%5}4i;gkB?@dO-;xw*Y9fOKMSOS!#+~QGTuh*uz$tINf65hSNN#
z-W1$!F~F%;ALtl;P_!aNGfW7Wc0f#cq6Ko`$v!m?nAVGciQ1#(o(Tg3qkyN2V@SoV
zq(A@v+cT>+2;OYC9MzN1_j2q1o*N>`Q`sdM4lOrnyfX8D0#BOrQO=W#z09;73}z|S
zeDYBUpR<QgWt+CsoG-umnGdT)vRyv<|DYdRqJXpt+qC3{6|Aov`I<F*dj1!8Jylp_
zzu)mi%XNXOMva!V=S?f#)*hMgSzd@wqmjc*g>lu7>*iMkQkt{kK1i*TJj}2|(at7f
zan7k}`Wmww8(3o}?o^vl@tt=yV}hm0ffl**4;X&`<kxOv)w$Nfa$SbIL{Ypig}q4P
zgunu+iX^AbbOGK&#{_I<GBzdF7__ZwUCO+HF~K#$<gk!Xo1(|34@<0OGwx2yX;V0z
pyo6bxS1$C&6G_dp=NK5-7&?zTvHbhDe<P^0@O1TaS?83{1OP1pih=+D

literal 0
HcmV?d00001

-- 
GitLab