[WIP] Some more work on Properties Dock plugin...

This commit is contained in:
MaxED 2012-10-10 15:39:18 +00:00
parent 9aa5e27425
commit 12a7256c29
15 changed files with 1505 additions and 49 deletions

Binary file not shown.

Binary file not shown.

View file

@ -38,6 +38,8 @@ namespace CodeImp.DoomBuilder.PropertiesDock
// This is called after a map has been successfully opened
public override void OnMapOpenEnd() {
MapElementsData.Init();
if(propertiesDocker == null) {
propertiesDocker = new PropertiesDocker();
docker = new Docker("propertiesdockerpanel", "Properties", propertiesDocker);

View file

@ -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();
}
@ -156,9 +197,12 @@
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 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;
}
}

View file

@ -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 (tabControl.TabPages.Count > 1) {
if(count != -1)
tabControl.TabPages[0].Text = count > 1 ? count + " vertices:" : "Vertex "+index+":";
}
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));
}
}
}
}
}

View file

@ -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);
}
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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;
[CategoryAttribute("Position"), DefaultValueAttribute(0f)]
public float Y { get { return y; } set { y = value; } }
private float y;
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;
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;
}
}
}
}
}

View file

@ -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));
}
}
}
}

View file

@ -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>

View file

@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB