[mapguide-commits] r5039 - in sandbox/maestro-3.0: Generated Maestro.Editors Maestro.Editors/FeatureSource Maestro.Editors/FeatureSource/Extensions Maestro.Editors/LayerDefinition/Vector Maestro.Editors/MapDefinition Maestro.Editors/Properties Maestro.Shared.UI OSGeo.MapGuide.MaestroAPI/Feature

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon Jul 19 12:58:26 EDT 2010


Author: jng
Date: 2010-07-19 16:58:26 +0000 (Mon, 19 Jul 2010)
New Revision: 5039

Added:
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.Designer.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.resx
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.Designer.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.resx
   sandbox/maestro-3.0/Maestro.Shared.UI/CheckBoxBinder.cs
   sandbox/maestro-3.0/Maestro.Shared.UI/TextBoxBinder.cs
Modified:
   sandbox/maestro-3.0/Generated/FeatureSource-1.0.0.designer.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.Designer.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.resx
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.Designer.cs
   sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs
   sandbox/maestro-3.0/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs
   sandbox/maestro-3.0/Maestro.Editors/Maestro.Editors.csproj
   sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.Designer.cs
   sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs
   sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.Designer.cs
   sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs
   sandbox/maestro-3.0/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs
   sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.Designer.cs
   sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.resx
   sandbox/maestro-3.0/Maestro.Shared.UI/Maestro.Shared.UI.csproj
   sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Feature/FeatureSourceDescription.cs
Log:
This submission includes the first cut of the redesigned feature source extension editor.

Modified: sandbox/maestro-3.0/Generated/FeatureSource-1.0.0.designer.cs
===================================================================
--- sandbox/maestro-3.0/Generated/FeatureSource-1.0.0.designer.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Generated/FeatureSource-1.0.0.designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -1220,6 +1220,7 @@
             set {
                 if ((forceOneToOneField.Equals(value) != true)) {
                     this.forceOneToOneField = value;
+                    this.ForceOneToOneSpecified = true;
                     this.OnPropertyChanged("ForceOneToOne");
                 }
             }

Added: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.Designer.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.Designer.cs	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.Designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,112 @@
+namespace Maestro.Editors.FeatureSource.Extensions
+{
+    partial class CalculationSettings
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label1 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.txtName = new System.Windows.Forms.TextBox();
+            this.txtExpression = new System.Windows.Forms.TextBox();
+            this.lnkEdit = new System.Windows.Forms.LinkLabel();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(11, 13);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(130, 13);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Calculated Property Name";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(11, 62);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(58, 13);
+            this.label2.TabIndex = 1;
+            this.label2.Text = "Expression";
+            // 
+            // txtName
+            // 
+            this.txtName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtName.Location = new System.Drawing.Point(14, 29);
+            this.txtName.Name = "txtName";
+            this.txtName.Size = new System.Drawing.Size(461, 20);
+            this.txtName.TabIndex = 2;
+            // 
+            // txtExpression
+            // 
+            this.txtExpression.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtExpression.Location = new System.Drawing.Point(14, 78);
+            this.txtExpression.Multiline = true;
+            this.txtExpression.Name = "txtExpression";
+            this.txtExpression.ReadOnly = true;
+            this.txtExpression.Size = new System.Drawing.Size(461, 237);
+            this.txtExpression.TabIndex = 3;
+            // 
+            // lnkEdit
+            // 
+            this.lnkEdit.AutoSize = true;
+            this.lnkEdit.Location = new System.Drawing.Point(75, 62);
+            this.lnkEdit.Name = "lnkEdit";
+            this.lnkEdit.Size = new System.Drawing.Size(25, 13);
+            this.lnkEdit.TabIndex = 4;
+            this.lnkEdit.TabStop = true;
+            this.lnkEdit.Text = "Edit";
+            this.lnkEdit.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkEdit_LinkClicked);
+            // 
+            // CalculationSettings
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.lnkEdit);
+            this.Controls.Add(this.txtExpression);
+            this.Controls.Add(this.txtName);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.label1);
+            this.Name = "CalculationSettings";
+            this.Size = new System.Drawing.Size(491, 330);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.TextBox txtName;
+        private System.Windows.Forms.TextBox txtExpression;
+        private System.Windows.Forms.LinkLabel lnkEdit;
+    }
+}

Added: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.cs	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,63 @@
+#region Disclaimer / License
+// Copyright (C) 2010, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using OSGeo.MapGuide.ObjectModels.FeatureSource;
+using OSGeo.MapGuide.MaestroAPI;
+using Maestro.Shared.UI;
+
+namespace Maestro.Editors.FeatureSource.Extensions
+{
+    public partial class CalculationSettings : UserControl
+    {
+        private CalculationSettings()
+        {
+            InitializeComponent();
+        }
+
+        private IEditorService _edSvc;
+        private FeatureSourceDescription.FeatureSourceSchema _cls;
+        private FeatureSourceType _parent;
+
+        public CalculationSettings(IEditorService edSvc, FeatureSourceDescription.FeatureSourceSchema cls, FeatureSourceType parent, CalculatedPropertyType calc)
+            : this()
+        {
+            _edSvc = edSvc;
+            _cls = cls;
+            _parent = parent;
+            TextBoxBinder.BindText(txtExpression, calc, "Expression");
+            TextBoxBinder.BindText(txtName, calc, "Name");
+        }
+
+        private void lnkEdit_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            string expr = _edSvc.EditExpression(txtExpression.Text, _cls, _parent.Provider, _parent.ResourceID);
+            if (expr != null)
+            {
+                txtExpression.Text = expr;
+            }
+        }
+    }
+}

Added: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.resx
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.resx	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/CalculationSettings.resx	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,120 @@
+<?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>
+</root>
\ No newline at end of file

Added: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.Designer.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.Designer.cs	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.Designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,97 @@
+namespace Maestro.Editors.FeatureSource.Extensions
+{
+    partial class ExtendedClassSettings
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label1 = new System.Windows.Forms.Label();
+            this.txtExtendedName = new System.Windows.Forms.TextBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.cmbBaseClass = new System.Windows.Forms.ComboBox();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(14, 16);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(162, 13);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Name of Extended Feature Class";
+            // 
+            // txtExtendedName
+            // 
+            this.txtExtendedName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtExtendedName.Location = new System.Drawing.Point(17, 32);
+            this.txtExtendedName.Name = "txtExtendedName";
+            this.txtExtendedName.Size = new System.Drawing.Size(289, 20);
+            this.txtExtendedName.TabIndex = 1;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(14, 72);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(119, 13);
+            this.label2.TabIndex = 2;
+            this.label2.Text = "Feature Class to Extend";
+            // 
+            // cmbBaseClass
+            // 
+            this.cmbBaseClass.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbBaseClass.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbBaseClass.FormattingEnabled = true;
+            this.cmbBaseClass.Location = new System.Drawing.Point(17, 89);
+            this.cmbBaseClass.Name = "cmbBaseClass";
+            this.cmbBaseClass.Size = new System.Drawing.Size(289, 21);
+            this.cmbBaseClass.TabIndex = 3;
+            // 
+            // ExtendedClassSettings
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.cmbBaseClass);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.txtExtendedName);
+            this.Controls.Add(this.label1);
+            this.Name = "ExtendedClassSettings";
+            this.Size = new System.Drawing.Size(327, 212);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.TextBox txtExtendedName;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.ComboBox cmbBaseClass;
+    }
+}

Added: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,73 @@
+#region Disclaimer / License
+// Copyright (C) 2010, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using OSGeo.MapGuide.ObjectModels.FeatureSource;
+using OSGeo.MapGuide.MaestroAPI;
+using Maestro.Shared.UI;
+
+namespace Maestro.Editors.FeatureSource.Extensions
+{
+    public partial class ExtendedClassSettings : UserControl, IEditorBindable
+    {
+        private ExtendedClassSettings()
+        {
+            InitializeComponent();
+        }
+
+        public ExtendedClassSettings(FeatureSourceDescription.FeatureSourceSchema[] classes, FeatureSourceTypeExtension ext)
+            : this()
+        {
+            cmbBaseClass.DisplayMember = "Fullname";
+            cmbBaseClass.ValueMember = "Fullname";
+            cmbBaseClass.DataSource = classes;
+            
+            //txtExtendedName.DataBindings.Add("Text", ext, "Name");
+            TextBoxBinder.BindText(txtExtendedName, ext, "Name");
+            cmbBaseClass.DataBindings.Add("SelectedValue", ext, "FeatureClass");
+
+            ext.PropertyChanged += (sender, e) => { OnResourceChanged(); };
+        }
+
+        //private void txtExtendedName_TextChanged(object sender, EventArgs e)
+        //{
+        //    txtExtendedName.DataBindings[0].WriteValue();
+        //}
+
+        public void Bind(IEditorService service)
+        {
+            service.RegisterCustomNotifier(this);
+        }
+
+        private void OnResourceChanged()
+        {
+            var handler = this.ResourceChanged;
+            if (handler != null)
+                handler(this, EventArgs.Empty);
+        }
+
+        public event EventHandler ResourceChanged;
+    }
+}

Added: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.resx
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.resx	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/ExtendedClassSettings.resx	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,120 @@
+<?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>
+</root>
\ No newline at end of file

Modified: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.Designer.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.Designer.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.Designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -41,9 +41,18 @@
             this.rdRightOuter = new System.Windows.Forms.RadioButton();
             this.rdLeftOuter = new System.Windows.Forms.RadioButton();
             this.chkForceOneToOne = new System.Windows.Forms.CheckBox();
+            this.grdJoinKeys = new System.Windows.Forms.DataGridView();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.lnkDelete = new System.Windows.Forms.LinkLabel();
+            this.lnkAdd = new System.Windows.Forms.LinkLabel();
+            this.cmbSecondary = new System.Windows.Forms.ComboBox();
+            this.cmbPrimary = new System.Windows.Forms.ComboBox();
+            this.label6 = new System.Windows.Forms.Label();
             this.label5 = new System.Windows.Forms.Label();
-            this.grdJoinKeys = new System.Windows.Forms.DataGridView();
+            this.COL_PRIMARY = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.COL_SECONDARY = new System.Windows.Forms.DataGridViewTextBoxColumn();
             ((System.ComponentModel.ISupportInitialize)(this.grdJoinKeys)).BeginInit();
+            this.groupBox1.SuspendLayout();
             this.SuspendLayout();
             // 
             // label1
@@ -70,7 +79,7 @@
                         | System.Windows.Forms.AnchorStyles.Right)));
             this.txtJoinName.Location = new System.Drawing.Point(144, 12);
             this.txtJoinName.Name = "txtJoinName";
-            this.txtJoinName.Size = new System.Drawing.Size(195, 20);
+            this.txtJoinName.Size = new System.Drawing.Size(296, 20);
             this.txtJoinName.TabIndex = 2;
             // 
             // txtFeatureSource
@@ -79,18 +88,20 @@
                         | System.Windows.Forms.AnchorStyles.Right)));
             this.txtFeatureSource.Location = new System.Drawing.Point(144, 38);
             this.txtFeatureSource.Name = "txtFeatureSource";
-            this.txtFeatureSource.Size = new System.Drawing.Size(162, 20);
+            this.txtFeatureSource.ReadOnly = true;
+            this.txtFeatureSource.Size = new System.Drawing.Size(263, 20);
             this.txtFeatureSource.TabIndex = 3;
             // 
             // btnBrowse
             // 
             this.btnBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
-            this.btnBrowse.Location = new System.Drawing.Point(312, 36);
+            this.btnBrowse.Location = new System.Drawing.Point(413, 36);
             this.btnBrowse.Name = "btnBrowse";
             this.btnBrowse.Size = new System.Drawing.Size(27, 23);
             this.btnBrowse.TabIndex = 4;
             this.btnBrowse.Text = "...";
             this.btnBrowse.UseVisualStyleBackColor = true;
+            this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
             // 
             // label3
             // 
@@ -105,11 +116,15 @@
             // 
             this.cmbFeatureClass.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                         | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbFeatureClass.DisplayMember = "Fullname";
+            this.cmbFeatureClass.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
             this.cmbFeatureClass.FormattingEnabled = true;
             this.cmbFeatureClass.Location = new System.Drawing.Point(144, 65);
             this.cmbFeatureClass.Name = "cmbFeatureClass";
-            this.cmbFeatureClass.Size = new System.Drawing.Size(195, 21);
+            this.cmbFeatureClass.Size = new System.Drawing.Size(296, 21);
             this.cmbFeatureClass.TabIndex = 6;
+            this.cmbFeatureClass.ValueMember = "Fullname";
+            this.cmbFeatureClass.SelectionChangeCommitted += new System.EventHandler(this.cmbFeatureClass_SelectedIndexChanged);
             // 
             // label4
             // 
@@ -122,55 +137,56 @@
             // 
             // rdAssociation
             // 
-            this.rdAssociation.AutoSize = true;
             this.rdAssociation.Image = global::Maestro.Editors.Properties.Resources.databases_relation;
-            this.rdAssociation.Location = new System.Drawing.Point(243, 122);
+            this.rdAssociation.Location = new System.Drawing.Point(243, 115);
             this.rdAssociation.Name = "rdAssociation";
-            this.rdAssociation.Size = new System.Drawing.Size(95, 17);
+            this.rdAssociation.Size = new System.Drawing.Size(105, 24);
             this.rdAssociation.TabIndex = 11;
             this.rdAssociation.TabStop = true;
             this.rdAssociation.Text = "Association";
             this.rdAssociation.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
             this.rdAssociation.UseVisualStyleBackColor = true;
+            this.rdAssociation.CheckedChanged += new System.EventHandler(this.rdJoinTypeChanged);
             // 
             // rdInner
             // 
-            this.rdInner.AutoSize = true;
             this.rdInner.Image = global::Maestro.Editors.Properties.Resources.sql_join_inner;
-            this.rdInner.Location = new System.Drawing.Point(144, 122);
+            this.rdInner.Location = new System.Drawing.Point(144, 115);
             this.rdInner.Name = "rdInner";
-            this.rdInner.Size = new System.Drawing.Size(65, 17);
+            this.rdInner.Size = new System.Drawing.Size(75, 24);
             this.rdInner.TabIndex = 10;
             this.rdInner.TabStop = true;
             this.rdInner.Text = "Inner";
             this.rdInner.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
             this.rdInner.UseVisualStyleBackColor = true;
+            this.rdInner.CheckedChanged += new System.EventHandler(this.rdJoinTypeChanged);
             // 
             // rdRightOuter
             // 
-            this.rdRightOuter.AutoSize = true;
             this.rdRightOuter.Image = global::Maestro.Editors.Properties.Resources.sql_join_right;
-            this.rdRightOuter.Location = new System.Drawing.Point(243, 99);
+            this.rdRightOuter.Location = new System.Drawing.Point(243, 92);
             this.rdRightOuter.Name = "rdRightOuter";
-            this.rdRightOuter.Size = new System.Drawing.Size(95, 17);
+            this.rdRightOuter.Size = new System.Drawing.Size(105, 24);
             this.rdRightOuter.TabIndex = 9;
             this.rdRightOuter.TabStop = true;
             this.rdRightOuter.Text = "Right Outer";
             this.rdRightOuter.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
             this.rdRightOuter.UseVisualStyleBackColor = true;
+            this.rdRightOuter.CheckedChanged += new System.EventHandler(this.rdJoinTypeChanged);
             // 
             // rdLeftOuter
             // 
-            this.rdLeftOuter.AutoSize = true;
+            this.rdLeftOuter.Checked = true;
             this.rdLeftOuter.Image = global::Maestro.Editors.Properties.Resources.sql_join_left;
-            this.rdLeftOuter.Location = new System.Drawing.Point(144, 99);
+            this.rdLeftOuter.Location = new System.Drawing.Point(144, 92);
             this.rdLeftOuter.Name = "rdLeftOuter";
-            this.rdLeftOuter.Size = new System.Drawing.Size(88, 17);
+            this.rdLeftOuter.Size = new System.Drawing.Size(98, 24);
             this.rdLeftOuter.TabIndex = 8;
             this.rdLeftOuter.TabStop = true;
             this.rdLeftOuter.Text = "Left Outer";
             this.rdLeftOuter.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
             this.rdLeftOuter.UseVisualStyleBackColor = true;
+            this.rdLeftOuter.CheckedChanged += new System.EventHandler(this.rdJoinTypeChanged);
             // 
             // chkForceOneToOne
             // 
@@ -182,29 +198,129 @@
             this.chkForceOneToOne.Text = "Force 1-to-1";
             this.chkForceOneToOne.UseVisualStyleBackColor = true;
             // 
+            // grdJoinKeys
+            // 
+            this.grdJoinKeys.AllowUserToAddRows = false;
+            this.grdJoinKeys.AllowUserToDeleteRows = false;
+            this.grdJoinKeys.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.grdJoinKeys.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.grdJoinKeys.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+            this.COL_PRIMARY,
+            this.COL_SECONDARY});
+            this.grdJoinKeys.Location = new System.Drawing.Point(6, 76);
+            this.grdJoinKeys.Name = "grdJoinKeys";
+            this.grdJoinKeys.ReadOnly = true;
+            this.grdJoinKeys.Size = new System.Drawing.Size(418, 138);
+            this.grdJoinKeys.TabIndex = 14;
+            this.grdJoinKeys.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.grdJoinKeys_CellClick);
+            this.grdJoinKeys.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.grdJoinKeys_CellClick);
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox1.Controls.Add(this.lnkDelete);
+            this.groupBox1.Controls.Add(this.lnkAdd);
+            this.groupBox1.Controls.Add(this.cmbSecondary);
+            this.groupBox1.Controls.Add(this.cmbPrimary);
+            this.groupBox1.Controls.Add(this.label6);
+            this.groupBox1.Controls.Add(this.label5);
+            this.groupBox1.Controls.Add(this.grdJoinKeys);
+            this.groupBox1.Location = new System.Drawing.Point(10, 145);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(430, 220);
+            this.groupBox1.TabIndex = 15;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Join Properties (Must specify at least one)";
+            // 
+            // lnkDelete
+            // 
+            this.lnkDelete.BackColor = System.Drawing.Color.Transparent;
+            this.lnkDelete.Enabled = false;
+            this.lnkDelete.Location = new System.Drawing.Point(61, 49);
+            this.lnkDelete.Name = "lnkDelete";
+            this.lnkDelete.Size = new System.Drawing.Size(60, 13);
+            this.lnkDelete.TabIndex = 20;
+            this.lnkDelete.TabStop = true;
+            this.lnkDelete.Text = "Delete Pair";
+            this.lnkDelete.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkDelete_LinkClicked);
+            // 
+            // lnkAdd
+            // 
+            this.lnkAdd.BackColor = System.Drawing.Color.Transparent;
+            this.lnkAdd.Enabled = false;
+            this.lnkAdd.Location = new System.Drawing.Point(7, 49);
+            this.lnkAdd.Name = "lnkAdd";
+            this.lnkAdd.Size = new System.Drawing.Size(48, 13);
+            this.lnkAdd.TabIndex = 19;
+            this.lnkAdd.TabStop = true;
+            this.lnkAdd.Text = "Add Pair";
+            this.lnkAdd.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lnkAdd_LinkClicked);
+            // 
+            // cmbSecondary
+            // 
+            this.cmbSecondary.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbSecondary.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbSecondary.FormattingEnabled = true;
+            this.cmbSecondary.Location = new System.Drawing.Point(311, 17);
+            this.cmbSecondary.Name = "cmbSecondary";
+            this.cmbSecondary.Size = new System.Drawing.Size(113, 21);
+            this.cmbSecondary.TabIndex = 18;
+            this.cmbSecondary.SelectedIndexChanged += new System.EventHandler(this.CheckAddStatus);
+            // 
+            // cmbPrimary
+            // 
+            this.cmbPrimary.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbPrimary.FormattingEnabled = true;
+            this.cmbPrimary.Location = new System.Drawing.Point(95, 17);
+            this.cmbPrimary.Name = "cmbPrimary";
+            this.cmbPrimary.Size = new System.Drawing.Size(104, 21);
+            this.cmbPrimary.TabIndex = 17;
+            this.cmbPrimary.SelectedIndexChanged += new System.EventHandler(this.CheckAddStatus);
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(205, 20);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(100, 13);
+            this.label6.TabIndex = 16;
+            this.label6.Text = "Secondary Property";
+            // 
             // label5
             // 
             this.label5.AutoSize = true;
-            this.label5.Location = new System.Drawing.Point(10, 146);
+            this.label5.Location = new System.Drawing.Point(6, 20);
             this.label5.Name = "label5";
-            this.label5.Size = new System.Drawing.Size(202, 13);
-            this.label5.TabIndex = 13;
-            this.label5.Text = "Join Properties (Must specify at least one)";
+            this.label5.Size = new System.Drawing.Size(83, 13);
+            this.label5.TabIndex = 15;
+            this.label5.Text = "Primary Property";
             // 
-            // grdJoinKeys
+            // COL_PRIMARY
             // 
-            this.grdJoinKeys.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
-            this.grdJoinKeys.Location = new System.Drawing.Point(13, 163);
-            this.grdJoinKeys.Name = "grdJoinKeys";
-            this.grdJoinKeys.Size = new System.Drawing.Size(325, 68);
-            this.grdJoinKeys.TabIndex = 14;
+            this.COL_PRIMARY.DataPropertyName = "FeatureClassProperty";
+            this.COL_PRIMARY.HeaderText = "Primary";
+            this.COL_PRIMARY.Name = "COL_PRIMARY";
+            this.COL_PRIMARY.ReadOnly = true;
+            this.COL_PRIMARY.Width = 130;
             // 
+            // COL_SECONDARY
+            // 
+            this.COL_SECONDARY.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+            this.COL_SECONDARY.DataPropertyName = "AttributeClassProperty";
+            this.COL_SECONDARY.HeaderText = "Secondary";
+            this.COL_SECONDARY.Name = "COL_SECONDARY";
+            this.COL_SECONDARY.ReadOnly = true;
+            // 
             // JoinSettings
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.Controls.Add(this.grdJoinKeys);
-            this.Controls.Add(this.label5);
+            this.Controls.Add(this.groupBox1);
             this.Controls.Add(this.chkForceOneToOne);
             this.Controls.Add(this.rdAssociation);
             this.Controls.Add(this.rdInner);
@@ -219,8 +335,10 @@
             this.Controls.Add(this.label2);
             this.Controls.Add(this.label1);
             this.Name = "JoinSettings";
-            this.Size = new System.Drawing.Size(354, 246);
+            this.Size = new System.Drawing.Size(455, 368);
             ((System.ComponentModel.ISupportInitialize)(this.grdJoinKeys)).EndInit();
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
             this.ResumeLayout(false);
             this.PerformLayout();
 
@@ -241,7 +359,15 @@
         private System.Windows.Forms.RadioButton rdInner;
         private System.Windows.Forms.RadioButton rdAssociation;
         private System.Windows.Forms.CheckBox chkForceOneToOne;
+        private System.Windows.Forms.DataGridView grdJoinKeys;
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.LinkLabel lnkDelete;
+        private System.Windows.Forms.LinkLabel lnkAdd;
+        private System.Windows.Forms.ComboBox cmbSecondary;
+        private System.Windows.Forms.ComboBox cmbPrimary;
+        private System.Windows.Forms.Label label6;
         private System.Windows.Forms.Label label5;
-        private System.Windows.Forms.DataGridView grdJoinKeys;
+        private System.Windows.Forms.DataGridViewTextBoxColumn COL_PRIMARY;
+        private System.Windows.Forms.DataGridViewTextBoxColumn COL_SECONDARY;
     }
 }

Modified: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -24,14 +24,190 @@
 using System.Data;
 using System.Text;
 using System.Windows.Forms;
+using OSGeo.MapGuide.ObjectModels.FeatureSource;
+using Maestro.Shared.UI;
+using OSGeo.MapGuide.MaestroAPI.Resource;
+using OSGeo.MapGuide.MaestroAPI;
 
 namespace Maestro.Editors.FeatureSource.Extensions
 {
-    public partial class JoinSettings : UserControl
+    public partial class JoinSettings : UserControl, IEditorBindable
     {
-        public JoinSettings()
+        private JoinSettings()
         {
             InitializeComponent();
         }
+
+        private bool _init = false;
+
+        private AttributeRelateType _rel;
+
+        public JoinSettings(FeatureSetColumn [] primaryColumns, AttributeRelateType rel)
+            : this()
+        {
+            //FIXME: Initial load will set the correct secondary class, but not the correct
+            //secondary property list!!!
+
+            _init = true;
+            grdJoinKeys.AutoGenerateColumns = false;
+            _rel = rel;
+
+            TextBoxBinder.BindText(txtJoinName, _rel, "Name");
+            TextBoxBinder.BindText(txtFeatureSource, _rel, "ResourceId");
+            txtFeatureSource.TextChanged += new EventHandler(txtFeatureSource_TextChanged);
+            //rb.ReadValue();
+            UpdateJoinClass();
+
+            CheckBoxBinder.BindChecked(chkForceOneToOne, _rel, "ForceOneToOne");
+            var bin = cmbFeatureClass.DataBindings.Add("SelectedValue", _rel, "AttributeClass");
+            bin.ReadValue();
+
+            //UpdateSecondary();
+
+            _rel.PropertyChanged += (sender, e) => { OnResourceChanged(); };
+
+            cmbPrimary.DisplayMember = "Name";
+            cmbPrimary.ValueMember = "Name";
+            cmbPrimary.DataSource = primaryColumns;
+
+            grdJoinKeys.DataSource = rel.RelateProperty;
+        }
+
+        void txtFeatureSource_TextChanged(object sender, EventArgs e)
+        {
+            UpdateJoinClass();
+        }
+
+        private void UpdateJoinClass()
+        {
+            try
+            {
+                var rt = ResourceIdentifier.GetResourceType(txtFeatureSource.Text);
+                if (rt == ResourceTypes.FeatureSource)
+                {
+                    var fs = _edSvc.FeatureService.DescribeFeatureSource(txtFeatureSource.Text);
+                    cmbFeatureClass.DataSource = fs.Schemas;
+
+                    if (fs.Schemas.Length > 0)
+                    {
+                        cmbFeatureClass.SelectedIndex = 0;
+                        UpdateSecondary();
+                    }
+                }
+            }
+            catch
+            {
+
+            }
+        }
+
+        private void btnBrowse_Click(object sender, EventArgs e)
+        {
+            string resId = _edSvc.SelectResource(OSGeo.MapGuide.MaestroAPI.ResourceTypes.FeatureSource);
+            if (!string.IsNullOrEmpty(resId))
+            {
+                txtFeatureSource.Text = resId;
+            }
+        }
+
+        private IEditorService _edSvc;
+
+        public void Bind(IEditorService service)
+        {
+            _edSvc = service;
+            _edSvc.RegisterCustomNotifier(this);
+        }
+
+        private void OnResourceChanged()
+        {
+            var handler = this.ResourceChanged;
+            if (handler != null)
+                handler(this, EventArgs.Empty);
+        }
+
+        public event EventHandler ResourceChanged;
+
+        public RelateTypeEnum GetJoinType()
+        {
+            if (rdLeftOuter.Checked)
+                return RelateTypeEnum.LeftOuter;
+            else if (rdInner.Checked)
+                return RelateTypeEnum.Inner;
+            else if (rdRightOuter.Checked)
+                return RelateTypeEnum.RightOuter;
+            else if (rdAssociation.Checked)
+                return RelateTypeEnum.Association;
+
+            throw new InvalidOperationException();
+        }
+
+        protected override void OnLoad(EventArgs e)
+        {
+            _init = false;
+            base.OnLoad(e);
+        }
+
+        private void rdJoinTypeChanged(object sender, EventArgs e)
+        {
+            _rel.RelateType = GetJoinType();
+        }
+
+        private void cmbFeatureClass_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            UpdateSecondary();
+        }
+
+        private void UpdateSecondary()
+        {
+            //Invalidate
+            if (!_init)
+                _rel.RelateProperty.Clear();
+
+            var item = cmbFeatureClass.SelectedItem as FeatureSourceDescription.FeatureSourceSchema;
+            if (item != null)
+            {
+                cmbSecondary.DisplayMember = "Name";
+                cmbSecondary.ValueMember = "Name";
+                cmbSecondary.DataSource = item.Columns;
+            }
+        }
+
+        private void lnkClear_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            _rel.RelateProperty.Clear();
+        }
+
+        private void CheckAddStatus(object sender, EventArgs e)
+        {
+            lnkAdd.Enabled = cmbPrimary.SelectedIndex >= 0 && cmbSecondary.SelectedIndex >= 0;
+        }
+
+        private void grdJoinKeys_CellClick(object sender, DataGridViewCellEventArgs e)
+        {
+            if (e.RowIndex >= 0)
+            {
+                grdJoinKeys.Rows[e.RowIndex].Selected = true;
+                lnkDelete.Enabled = true;
+            }
+        }
+
+        private void lnkAdd_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            if (cmbSecondary.SelectedIndex >= 0 && cmbSecondary.SelectedIndex >= 0)
+            {
+                string primary = ((FeatureSetColumn)cmbPrimary.SelectedItem).Name;
+                string secondary = ((FeatureSetColumn)cmbSecondary.SelectedItem).Name;
+
+                _rel.RelateProperty.Add(new RelatePropertyType() { FeatureClassProperty = primary, AttributeClassProperty = secondary });
+            }
+        }
+
+        private void lnkDelete_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            if (grdJoinKeys.SelectedRows.Count == 1)
+            {
+                _rel.RelateProperty.Remove((RelatePropertyType)grdJoinKeys.SelectedRows[0].DataBoundItem);
+            }
+        }
     }
 }

Modified: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.resx
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.resx	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/Extensions/JoinSettings.resx	2010-07-19 16:58:26 UTC (rev 5039)
@@ -117,4 +117,10 @@
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
+  <metadata name="COL_PRIMARY.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="COL_SECONDARY.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
 </root>
\ No newline at end of file

Modified: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.Designer.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.Designer.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.Designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -71,8 +71,10 @@
             this.trvExtensions.Location = new System.Drawing.Point(0, 25);
             this.trvExtensions.Name = "trvExtensions";
             this.trvExtensions.SelectedImageIndex = 0;
+            this.trvExtensions.ShowNodeToolTips = true;
             this.trvExtensions.Size = new System.Drawing.Size(169, 267);
             this.trvExtensions.TabIndex = 1;
+            this.trvExtensions.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.trvExtensions_AfterSelect);
             // 
             // trvImages
             // 
@@ -104,6 +106,7 @@
             this.btnNewExtension.Name = "btnNewExtension";
             this.btnNewExtension.Size = new System.Drawing.Size(23, 22);
             this.btnNewExtension.Text = "Add New Extension";
+            this.btnNewExtension.Click += new System.EventHandler(this.btnNewExtension_Click);
             // 
             // btnNewCalculation
             // 
@@ -114,6 +117,7 @@
             this.btnNewCalculation.Name = "btnNewCalculation";
             this.btnNewCalculation.Size = new System.Drawing.Size(23, 22);
             this.btnNewCalculation.Text = "Add New Calculated Property";
+            this.btnNewCalculation.Click += new System.EventHandler(this.btnNewCalculation_Click);
             // 
             // btnNewJoin
             // 
@@ -124,6 +128,7 @@
             this.btnNewJoin.Name = "btnNewJoin";
             this.btnNewJoin.Size = new System.Drawing.Size(23, 22);
             this.btnNewJoin.Text = "New Join";
+            this.btnNewJoin.Click += new System.EventHandler(this.btnNewJoin_Click);
             // 
             // toolStripSeparator1
             // 
@@ -139,6 +144,7 @@
             this.btnDelete.Name = "btnDelete";
             this.btnDelete.Size = new System.Drawing.Size(23, 22);
             this.btnDelete.Text = "Delete";
+            this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
             // 
             // ExtensionsCtrl
             // 

Modified: sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/FeatureSource/ExtensionsCtrl.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -25,6 +25,10 @@
 using System.Text;
 using System.Windows.Forms;
 using Maestro.Shared.UI;
+using OSGeo.MapGuide.ObjectModels.FeatureSource;
+using Maestro.Editors.FeatureSource.Extensions;
+using OSGeo.MapGuide.MaestroAPI;
+using OSGeo.MapGuide.MaestroAPI.ObjectModels;
 
 namespace Maestro.Editors.FeatureSource
 {
@@ -35,11 +39,332 @@
             InitializeComponent();
         }
 
+        const int IDX_EXTENSION = 0;
+        const int IDX_CALC = 1;
+        const int IDX_JOIN = 2;
+
+        private FeatureSourceType _fs;
+        private FeatureSourceDescription _cachedSchema;
+
+        private IEditorService _edSvc;
+
         public void Bind(IEditorService service)
         {
-            
+            _edSvc = service;
+            _fs = (FeatureSourceType)_edSvc.GetEditedResource();
+            _cachedSchema = _fs.Describe();
+
+            //Build tree
+            if (_fs.Extension != null)
+            {
+                foreach (var ext in _fs.Extension)
+                {
+                    TreeNode node = new TreeNode();
+                    node.Tag = ext;
+                    node.ImageIndex = node.SelectedImageIndex = IDX_EXTENSION;
+                    
+                    node.Text = ext.Name;
+                    node.ToolTipText = string.Format(Properties.Resources.ExtendedClassTooltip, ext.FeatureClass);
+
+                    ext.PropertyChanged += (s, evt) =>
+                    {
+                        if (evt.PropertyName == "Name")
+                        {
+                            node.Text = ext.Name;
+                        }
+                        else if (evt.PropertyName == "FeatureClass")
+                        {
+                            node.ToolTipText = string.Format(Properties.Resources.ExtendedClassTooltip, ext.FeatureClass);
+                        }
+                    };
+
+                    trvExtensions.Nodes.Add(node);
+
+                    if (ext.CalculatedProperty != null)
+                    {
+                        foreach (var calc in ext.CalculatedProperty)
+                        {
+                            var cNode = new TreeNode();
+                            cNode.ImageIndex = cNode.SelectedImageIndex = IDX_CALC;
+                            cNode.Tag = calc;
+
+                            cNode.Text = calc.Name;
+                            cNode.ToolTipText = calc.Expression;
+
+                            calc.PropertyChanged += (s, evt) =>
+                            {
+                                if (evt.PropertyName == "Name")
+                                {
+                                    cNode.Text = calc.Name;
+                                }
+                                else if (evt.PropertyName == "Expression")
+                                {
+                                    cNode.ToolTipText = calc.Expression;
+                                }
+                            };
+
+                            node.Nodes.Add(cNode);
+                        }
+                    }
+                    if (ext.AttributeRelate != null)
+                    {
+                        foreach (var join in ext.AttributeRelate)
+                        {
+                            var jNode = new TreeNode();
+                            jNode.Tag = join;
+                            jNode.ImageIndex = jNode.SelectedImageIndex = IDX_JOIN;
+
+                            jNode.Text = join.Name;
+
+                            join.PropertyChanged += (s, evt) =>
+                            {
+                                if (evt.PropertyName == "Name")
+                                {
+                                    jNode.Text = join.Name;
+                                }
+                            };
+
+                            node.Nodes.Add(jNode);
+                        }
+                    }
+                    node.ExpandAll();
+                }
+            }
         }
 
+        private void OnResourceChanged()
+        {
+            var handler = this.ResourceChanged;
+            if (handler != null)
+                handler(this, EventArgs.Empty);
+        }
+
         public event EventHandler ResourceChanged;
+
+        private void btnNewExtension_Click(object sender, EventArgs e)
+        {
+            if (_fs.Extension == null)
+            {
+                _fs.Extension = new BindingList<FeatureSourceTypeExtension>();
+            }
+
+            var ext = new FeatureSourceTypeExtension();
+            TreeNode node = new TreeNode();
+            node.Tag = ext;
+            node.ImageIndex = node.SelectedImageIndex = IDX_EXTENSION;
+            ext.PropertyChanged += (s, evt) =>
+            {
+                if (evt.PropertyName == "Name")
+                {
+                    node.Text = ext.Name;
+                }
+                else if (evt.PropertyName == "FeatureClass")
+                {
+                    node.ToolTipText = string.Format(Properties.Resources.ExtendedClassTooltip, ext.FeatureClass);
+                }
+            };
+
+            _fs.Extension.Add(ext);
+
+            trvExtensions.Nodes.Add(node);
+            trvExtensions.SelectedNode = node;
+        }
+
+        private void btnNewCalculation_Click(object sender, EventArgs e)
+        {
+            var node = trvExtensions.SelectedNode;
+            if (node != null)
+            {
+                var ext = node.Tag as FeatureSourceTypeExtension;
+                if (ext != null)
+                {
+                    var calc = new CalculatedPropertyType();
+                    var cNode = new TreeNode();
+                    cNode.ImageIndex = cNode.SelectedImageIndex = IDX_CALC;
+                    cNode.Tag = calc;
+                    calc.PropertyChanged += (s, evt) =>
+                    {
+                        if (evt.PropertyName == "Name")
+                        {
+                            cNode.Text = calc.Name;
+                        }
+                        else if (evt.PropertyName == "Expression")
+                        {
+                            cNode.ToolTipText = calc.Expression;
+                        }
+                    };
+
+                    node.Nodes.Add(cNode);
+                    node.Expand();
+
+                    if (ext.CalculatedProperty == null)
+                        ext.CalculatedProperty = new BindingList<CalculatedPropertyType>();
+
+                    ext.CalculatedProperty.Add(calc);
+
+                    trvExtensions.SelectedNode = cNode;
+                }
+            }
+        }
+
+        private void btnNewJoin_Click(object sender, EventArgs e)
+        {
+            var node = trvExtensions.SelectedNode;
+            if (node != null)
+            {
+                var ext = node.Tag as FeatureSourceTypeExtension;
+                if (ext != null)
+                {
+                    var join = new AttributeRelateType();
+                    join.RelateProperty = new BindingList<RelatePropertyType>();
+                    var jNode = new TreeNode();
+                    jNode.Tag = join;
+                    jNode.ImageIndex = jNode.SelectedImageIndex = IDX_JOIN;
+                    join.PropertyChanged += (s, evt) =>
+                    {
+                        if (evt.PropertyName == "Name")
+                        {
+                            jNode.Text = join.Name;
+                        }
+                    };
+
+                    node.Nodes.Add(jNode);
+                    node.Expand();
+                    if (ext.AttributeRelate == null)
+                        ext.AttributeRelate = new BindingList<AttributeRelateType>();
+
+                    ext.AttributeRelate.Add(join);
+
+                    trvExtensions.SelectedNode = jNode;
+                }
+            }
+        }
+
+        private void btnDelete_Click(object sender, EventArgs e)
+        {
+            var node = trvExtensions.SelectedNode;
+            if (node != null)
+            {
+                var ext = node.Tag as FeatureSourceTypeExtension;
+                var join = node.Tag as AttributeRelateType;
+                var calc = node.Tag as CalculatedPropertyType;
+                if (ext != null)
+                {
+                    _fs.Extension.Remove(ext);
+
+                    if (_fs.Extension.Count == 0)
+                        _fs.Extension = null; //To prevent empty element when saving
+                }
+                else if (join != null)
+                {
+                    //Disassociate from parent
+                    ext = node.Parent.Tag as FeatureSourceTypeExtension;
+                    if (ext != null)
+                    {
+                        ext.AttributeRelate.Remove(join);
+                        node.Parent.Nodes.Remove(node);
+
+                        //To prevent writing empty elements when saving
+                        if (ext.AttributeRelate.Count == 0)
+                            ext.AttributeRelate = null;
+                    }
+                }
+                else if (calc != null)
+                {
+                    //Disassociate from parent
+                    ext = node.Parent.Tag as FeatureSourceTypeExtension;
+                    if (ext != null)
+                    {
+                        ext.CalculatedProperty.Remove(calc);
+                        node.Parent.Nodes.Remove(node);
+
+                        //To prevent writing empty elements when saving
+                        if (ext.CalculatedProperty.Count == 0)
+                            ext.CalculatedProperty = null;
+                    }
+                }
+            }
+        }
+
+        private bool IsValidExtension(FeatureSourceTypeExtension ext)
+        {
+            //TODO: Check class name and extended class name for validity
+            return !string.IsNullOrEmpty(ext.FeatureClass) && !string.IsNullOrEmpty(ext.Name);
+        }
+
+        private void trvExtensions_AfterSelect(object sender, TreeViewEventArgs e)
+        {
+            var ext = e.Node.Tag as FeatureSourceTypeExtension;
+            var join = e.Node.Tag as AttributeRelateType;
+            var calc = e.Node.Tag as CalculatedPropertyType;
+            if (ext != null)
+            {
+                var ctl = new ExtendedClassSettings(_cachedSchema.Schemas, ext);
+                ctl.Dock = DockStyle.Fill;
+                //If editing to something valid, update the toolbar
+                ctl.ResourceChanged += (s, evt) =>
+                {
+                    btnNewJoin.Enabled = btnNewCalculation.Enabled = IsValidExtension(ext);
+                };
+
+                splitContainer1.Panel2.Controls.Clear();
+                splitContainer1.Panel2.Controls.Add(ctl);
+
+                btnNewCalculation.Enabled = btnNewJoin.Enabled = IsValidExtension(ext);
+            }
+            else if (join != null)
+            {
+                ext = e.Node.Parent.Tag as FeatureSourceTypeExtension;
+                if (ext != null)
+                {
+                    FeatureSourceDescription.FeatureSourceSchema cls = null;
+                    foreach (var c in _cachedSchema.Schemas)
+                    {
+                        if (c.Fullname == ext.FeatureClass)
+                        {
+                            cls = c;
+                            break;
+                        }
+                    }
+
+                    if (cls != null)
+                    {
+                        var ctl = new JoinSettings(cls.Columns, join);
+                        ctl.Bind(_edSvc);
+                        ctl.Dock = DockStyle.Fill;
+                        splitContainer1.Panel2.Controls.Clear();
+                        splitContainer1.Panel2.Controls.Add(ctl);
+                    }
+                }
+            }
+            else if (calc != null)
+            {
+                ext = e.Node.Parent.Tag as FeatureSourceTypeExtension;
+                if (ext != null)
+                {
+                    FeatureSourceDescription.FeatureSourceSchema cls = null;
+                    foreach (var c in _cachedSchema.Schemas)
+                    {
+                        if (c.Fullname == ext.FeatureClass)
+                        {
+                            cls = c;
+                            break;
+                        }
+                    }
+
+                    if (cls != null)
+                    {
+                        var ctl = new CalculationSettings(_edSvc, cls, _fs, calc);
+                        ctl.Dock = DockStyle.Fill;
+                        splitContainer1.Panel2.Controls.Clear();
+                        splitContainer1.Panel2.Controls.Add(ctl);
+                    }
+                }
+            }
+            else 
+            {
+                splitContainer1.Panel2.Controls.Clear();
+            }
+        }
     }
 }

Modified: sandbox/maestro-3.0/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/LayerDefinition/Vector/VectorLayerSettingsSectionCtrl.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -52,12 +52,17 @@
             var vl = res.Item as OSGeo.MapGuide.ObjectModels.LayerDefinition.VectorLayerDefinitionType;
             Debug.Assert(vl != null);
 
-            txtFeatureSource.DataBindings.Add("Text", vl, "ResourceId");
+            //txtFeatureSource.DataBindings.Add("Text", vl, "ResourceId");
+            TextBoxBinder.BindText(txtFeatureSource, vl, "ResourceId");
+
             cmbSchema.DataBindings.Add("Text", vl, "FeatureName");
             cmbGeometry.DataBindings.Add("Text", vl, "Geometry");
-            txtFilter.DataBindings.Add("Text", vl, "Filter");
-            txtHyperlink.DataBindings.Add("Text", vl, "Url");
-            txtTooltip.DataBindings.Add("Text", vl, "ToolTip");
+            //txtFilter.DataBindings.Add("Text", vl, "Filter");
+            //txtHyperlink.DataBindings.Add("Text", vl, "Url");
+            //txtTooltip.DataBindings.Add("Text", vl, "ToolTip");
+            TextBoxBinder.BindText(txtFilter, vl, "Filter");
+            TextBoxBinder.BindText(txtHyperlink, vl, "Url");
+            TextBoxBinder.BindText(txtTooltip, vl, "ToolTip");
 
             //This is not the root object so no change listeners have been subscribed
             vl.PropertyChanged += (sender, e) => { OnResourceChanged(); };
@@ -154,7 +159,7 @@
                 {
                     txtFilter.Text = expr;
                     //HACK: Force databinding update
-                    txtFilter.DataBindings[0].WriteValue();
+                    //txtFilter.DataBindings[0].WriteValue();
                 }
             }
         }
@@ -170,7 +175,7 @@
                 {
                     txtHyperlink.Text = expr;
                     //HACK: Force databinding update
-                    txtHyperlink.DataBindings[0].WriteValue();
+                    //txtHyperlink.DataBindings[0].WriteValue();
                 }
             }
         }
@@ -186,7 +191,7 @@
                 {
                     txtTooltip.Text = expr;
                     //HACK: Force databinding update
-                    txtTooltip.DataBindings[0].WriteValue();
+                    //txtTooltip.DataBindings[0].WriteValue();
                 }
             }
         }

Modified: sandbox/maestro-3.0/Maestro.Editors/Maestro.Editors.csproj
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/Maestro.Editors.csproj	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/Maestro.Editors.csproj	2010-07-19 16:58:26 UTC (rev 5039)
@@ -142,6 +142,18 @@
     <Compile Include="FeatureSource\ExtensionsCtrl.Designer.cs">
       <DependentUpon>ExtensionsCtrl.cs</DependentUpon>
     </Compile>
+    <Compile Include="FeatureSource\Extensions\CalculationSettings.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="FeatureSource\Extensions\CalculationSettings.Designer.cs">
+      <DependentUpon>CalculationSettings.cs</DependentUpon>
+    </Compile>
+    <Compile Include="FeatureSource\Extensions\ExtendedClassSettings.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="FeatureSource\Extensions\ExtendedClassSettings.Designer.cs">
+      <DependentUpon>ExtendedClassSettings.cs</DependentUpon>
+    </Compile>
     <Compile Include="FeatureSource\Extensions\JoinSettings.cs">
       <SubType>UserControl</SubType>
     </Compile>
@@ -497,6 +509,14 @@
       <DependentUpon>ExtensionsCtrl.cs</DependentUpon>
       <SubType>Designer</SubType>
     </EmbeddedResource>
+    <EmbeddedResource Include="FeatureSource\Extensions\CalculationSettings.resx">
+      <DependentUpon>CalculationSettings.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="FeatureSource\Extensions\ExtendedClassSettings.resx">
+      <DependentUpon>ExtendedClassSettings.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
     <EmbeddedResource Include="FeatureSource\Extensions\JoinSettings.resx">
       <DependentUpon>JoinSettings.cs</DependentUpon>
       <SubType>Designer</SubType>

Modified: sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.Designer.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.Designer.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.Designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -67,7 +67,6 @@
             this.chkSelectable.TabIndex = 15;
             this.chkSelectable.Text = "Features on the layer are selectable (if visible)";
             this.chkSelectable.UseVisualStyleBackColor = true;
-            this.chkSelectable.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // chkExpanded
             // 
@@ -78,7 +77,6 @@
             this.chkExpanded.TabIndex = 14;
             this.chkExpanded.Text = "Layer is expanded in the legend (if themed)";
             this.chkExpanded.UseVisualStyleBackColor = true;
-            this.chkExpanded.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // chkLegendVisible
             // 
@@ -89,7 +87,6 @@
             this.chkLegendVisible.TabIndex = 13;
             this.chkLegendVisible.Text = "Layer is shown in the map legend";
             this.chkLegendVisible.UseVisualStyleBackColor = true;
-            this.chkLegendVisible.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // chkVisible
             // 
@@ -100,7 +97,6 @@
             this.chkVisible.TabIndex = 12;
             this.chkVisible.Text = "Layer is visible at startup";
             this.chkVisible.UseVisualStyleBackColor = true;
-            this.chkVisible.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // txtLegendLabel
             // 
@@ -110,7 +106,6 @@
             this.txtLegendLabel.Name = "txtLegendLabel";
             this.txtLegendLabel.Size = new System.Drawing.Size(277, 20);
             this.txtLegendLabel.TabIndex = 11;
-            this.txtLegendLabel.TextChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // txtName
             // 
@@ -120,7 +115,6 @@
             this.txtName.Name = "txtName";
             this.txtName.Size = new System.Drawing.Size(277, 20);
             this.txtName.TabIndex = 10;
-            this.txtName.TextChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // label2
             // 

Modified: sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/MapDefinition/GroupPropertiesCtrl.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -6,6 +6,7 @@
 using System.Text;
 using System.Windows.Forms;
 using OSGeo.MapGuide.ObjectModels.MapDefinition;
+using Maestro.Shared.UI;
 
 namespace Maestro.Editors.MapDefinition
 {
@@ -23,12 +24,17 @@
         {
             group.PropertyChanged += new PropertyChangedEventHandler(OnGroupChanged);
 
-            txtName.DataBindings.Add("Text", group, "Name");
-            txtLegendLabel.DataBindings.Add("Text", group, "LegendLabel");
+            //txtName.DataBindings.Add("Text", group, "Name");
+            //txtLegendLabel.DataBindings.Add("Text", group, "LegendLabel");
+            TextBoxBinder.BindText(txtName, group, "Name");
+            TextBoxBinder.BindText(txtLegendLabel, group, "LegendLabel");
 
-            chkExpanded.DataBindings.Add("Checked", group, "ExpandInLegend");
-            chkLegendVisible.DataBindings.Add("Checked", group, "ShowInLegend");
-            chkVisible.DataBindings.Add("Checked", group, "Visible");
+            //chkExpanded.DataBindings.Add("Checked", group, "ExpandInLegend");
+            //chkLegendVisible.DataBindings.Add("Checked", group, "ShowInLegend");
+            //chkVisible.DataBindings.Add("Checked", group, "Visible");
+            CheckBoxBinder.BindChecked(chkExpanded, group, "ExpandInLegend");
+            CheckBoxBinder.BindChecked(chkLegendVisible, group, "ShowInLegend");
+            CheckBoxBinder.BindChecked(chkVisible, group, "Visible");
         }
 
         void OnGroupChanged(object sender, PropertyChangedEventArgs e)
@@ -38,9 +44,9 @@
                 handler(this, EventArgs.Empty);
         }
 
-        void ForceUpdate(object sender, EventArgs e)
-        {
-            ((Control)sender).DataBindings[0].WriteValue();
-        }
+        //void ForceUpdate(object sender, EventArgs e)
+        //{
+        //    ((Control)sender).DataBindings[0].WriteValue();
+        //}
     }
 }

Modified: sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.Designer.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.Designer.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.Designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -67,7 +67,6 @@
             this.chkSelectable.TabIndex = 7;
             this.chkSelectable.Text = "Features on the layer are selectable (if visible)";
             this.chkSelectable.UseVisualStyleBackColor = true;
-            this.chkSelectable.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // chkExpanded
             // 
@@ -78,7 +77,6 @@
             this.chkExpanded.TabIndex = 6;
             this.chkExpanded.Text = "Layer is expanded in the legend (if themed)";
             this.chkExpanded.UseVisualStyleBackColor = true;
-            this.chkExpanded.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // chkLegendVisible
             // 
@@ -89,7 +87,6 @@
             this.chkLegendVisible.TabIndex = 5;
             this.chkLegendVisible.Text = "Layer is shown in the map legend";
             this.chkLegendVisible.UseVisualStyleBackColor = true;
-            this.chkLegendVisible.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // chkVisible
             // 
@@ -100,7 +97,6 @@
             this.chkVisible.TabIndex = 4;
             this.chkVisible.Text = "Layer is visible at startup";
             this.chkVisible.UseVisualStyleBackColor = true;
-            this.chkVisible.CheckedChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // txtLegendLabel
             // 
@@ -110,7 +106,6 @@
             this.txtLegendLabel.Name = "txtLegendLabel";
             this.txtLegendLabel.Size = new System.Drawing.Size(285, 20);
             this.txtLegendLabel.TabIndex = 3;
-            this.txtLegendLabel.TextChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // txtName
             // 
@@ -120,7 +115,6 @@
             this.txtName.Name = "txtName";
             this.txtName.Size = new System.Drawing.Size(285, 20);
             this.txtName.TabIndex = 2;
-            this.txtName.TextChanged += new System.EventHandler(this.ForceUpdate);
             // 
             // label2
             // 

Modified: sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/MapDefinition/LayerPropertiesCtrl.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -6,6 +6,7 @@
 using System.Text;
 using System.Windows.Forms;
 using OSGeo.MapGuide.ObjectModels.MapDefinition;
+using Maestro.Shared.UI;
 
 namespace Maestro.Editors.MapDefinition
 {
@@ -21,13 +22,21 @@
         public LayerPropertiesCtrl(MapLayerType layer) : this()
         {
             layer.PropertyChanged += new PropertyChangedEventHandler(OnLayerChanged); 
-            txtName.DataBindings.Add("Text", layer, "Name");
-            txtLegendLabel.DataBindings.Add("Text", layer, "LegendLabel");
+            //txtName.DataBindings.Add("Text", layer, "Name");
+            //txtLegendLabel.DataBindings.Add("Text", layer, "LegendLabel");
 
-            chkExpanded.DataBindings.Add("Checked", layer, "ExpandInLegend");
-            chkLegendVisible.DataBindings.Add("Checked", layer, "ShowInLegend");
-            chkVisible.DataBindings.Add("Checked", layer, "Visible");
-            chkSelectable.DataBindings.Add("Checked", layer, "Selectable");
+            //chkExpanded.DataBindings.Add("Checked", layer, "ExpandInLegend");
+            //chkLegendVisible.DataBindings.Add("Checked", layer, "ShowInLegend");
+            //chkVisible.DataBindings.Add("Checked", layer, "Visible");
+            //chkSelectable.DataBindings.Add("Checked", layer, "Selectable");
+
+            TextBoxBinder.BindText(txtName, layer, "Name");
+            TextBoxBinder.BindText(txtLegendLabel, layer, "LegendLabel");
+
+            CheckBoxBinder.BindChecked(chkExpanded, layer, "ExpandInLegend");
+            CheckBoxBinder.BindChecked(chkLegendVisible, layer, "ShowInLegend");
+            CheckBoxBinder.BindChecked(chkVisible, layer, "Visible");
+            CheckBoxBinder.BindChecked(chkSelectable, layer, "Selectable");
         }
 
         void OnLayerChanged(object sender, PropertyChangedEventArgs e)
@@ -37,9 +46,9 @@
                 handler(this, EventArgs.Empty);
         }
 
-        void ForceUpdate(object sender, EventArgs e)
-        {
-            ((Control)sender).DataBindings[0].WriteValue();
-        }
+        //void ForceUpdate(object sender, EventArgs e)
+        //{
+        //    ((Control)sender).DataBindings[0].WriteValue();
+        //}
     }
 }

Modified: sandbox/maestro-3.0/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/MapDefinition/MapSettingsSectionCtrl.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -68,8 +68,10 @@
                     }
                 }
             };
-            txtDescription.DataBindings.Add(bmeta);
-            txtCoordinateSystem.DataBindings.Add("Text", _map, "CoordinateSystem");
+            //txtDescription.DataBindings.Add(bmeta);
+            TextBoxBinder.BindText(txtDescription, bmeta);
+            //txtCoordinateSystem.DataBindings.Add("Text", _map, "CoordinateSystem");
+            TextBoxBinder.BindText(txtCoordinateSystem, _map, "CoordinateSystem");
 
             //ColorComboBox requires custom databinding
             cmbBackgroundColor.CurrentColor = _map.BackgroundColor;
@@ -111,7 +113,7 @@
 
                 //HACK: Force the binding to update
                 //http://stackoverflow.com/questions/1060080/databound-winforms-control-does-not-recognize-change-until-losing-focus
-                txtCoordinateSystem.DataBindings[0].WriteValue();
+                //txtCoordinateSystem.DataBindings[0].WriteValue();
             }
         }
 

Modified: sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.Designer.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.Designer.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.Designer.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -273,6 +273,15 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Extended class based on: {0}.
+        /// </summary>
+        internal static string ExtendedClassTooltip {
+            get {
+                return ResourceManager.GetString("ExtendedClassTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to File Downloaded.
         /// </summary>
         internal static string FileDownloaded {

Modified: sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.resx
===================================================================
--- sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.resx	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Editors/Properties/Resources.resx	2010-07-19 16:58:26 UTC (rev 5039)
@@ -382,4 +382,7 @@
   <data name="ruler" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\ruler.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="ExtendedClassTooltip" xml:space="preserve">
+    <value>Extended class based on: {0}</value>
+  </data>
 </root>
\ No newline at end of file

Added: sandbox/maestro-3.0/Maestro.Shared.UI/CheckBoxBinder.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Shared.UI/CheckBoxBinder.cs	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Shared.UI/CheckBoxBinder.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,54 @@
+#region Disclaimer / License
+// Copyright (C) 2010, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Maestro.Shared.UI
+{
+    /// <summary>
+    /// Helper class to bind object properties to <see cref="CheckBox"/> derived classes for 
+    /// immediate updates as opposed to updates on loss of focus.
+    /// </summary>
+    public static class CheckBoxBinder
+    {
+        // We need to force WriteValue() on CheckedChanged otherwise it will only call WriteValue()
+        // on loss of focus.
+        // http://stackoverflow.com/questions/1060080/databound-winforms-control-does-not-recognize-change-until-losing-focus
+
+
+        public static Binding BindChecked(CheckBox chk, Binding b)
+        {
+            chk.DataBindings.Add(b);
+            chk.CheckedChanged += (sender, e) => { b.WriteValue(); };
+
+            return b;
+        }
+
+        public static Binding BindChecked(CheckBox chk, object dataSource, string dataMember)
+        {
+            var binding = chk.DataBindings.Add("Checked", dataSource, dataMember);
+            chk.CheckedChanged += (sender, e) => { binding.WriteValue(); };
+
+            return binding;
+        }
+    }
+}

Modified: sandbox/maestro-3.0/Maestro.Shared.UI/Maestro.Shared.UI.csproj
===================================================================
--- sandbox/maestro-3.0/Maestro.Shared.UI/Maestro.Shared.UI.csproj	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/Maestro.Shared.UI/Maestro.Shared.UI.csproj	2010-07-19 16:58:26 UTC (rev 5039)
@@ -38,6 +38,7 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="CheckBoxBinder.cs" />
     <Compile Include="CollapsiblePanel.cs">
       <SubType>UserControl</SubType>
     </Compile>
@@ -51,6 +52,7 @@
       <DesignTime>True</DesignTime>
       <DependentUpon>Resources.resx</DependentUpon>
     </Compile>
+    <Compile Include="TextBoxBinder.cs" />
     <Compile Include="WaitCursor.cs" />
     <Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
   </ItemGroup>

Added: sandbox/maestro-3.0/Maestro.Shared.UI/TextBoxBinder.cs
===================================================================
--- sandbox/maestro-3.0/Maestro.Shared.UI/TextBoxBinder.cs	                        (rev 0)
+++ sandbox/maestro-3.0/Maestro.Shared.UI/TextBoxBinder.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -0,0 +1,53 @@
+#region Disclaimer / License
+// Copyright (C) 2010, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Maestro.Shared.UI
+{
+    /// <summary>
+    /// Helper class to bind object properties to <see cref="TextBoxBase"/> derived classes for 
+    /// immediate updates as opposed to updates on loss of focus.
+    /// </summary>
+    public static class TextBoxBinder
+    {
+        // We need to force WriteValue() on TextChanged otherwise it will only call WriteValue()
+        // on loss of focus.
+        // http://stackoverflow.com/questions/1060080/databound-winforms-control-does-not-recognize-change-until-losing-focus
+
+        public static Binding BindText(TextBoxBase txt, Binding b)
+        {
+            txt.DataBindings.Add(b);
+            txt.TextChanged += (sender, e) => { b.WriteValue(); };
+
+            return b;
+        }
+
+        public static Binding BindText(TextBoxBase txt, object dataSource, string dataMember)
+        {
+            var binding = txt.DataBindings.Add("Text", dataSource, dataMember);
+            txt.TextChanged += (sender, e) => { binding.WriteValue(); };
+
+            return binding;
+        }
+    }
+}

Modified: sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Feature/FeatureSourceDescription.cs
===================================================================
--- sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Feature/FeatureSourceDescription.cs	2010-07-19 16:28:44 UTC (rev 5038)
+++ sandbox/maestro-3.0/OSGeo.MapGuide.MaestroAPI/Feature/FeatureSourceDescription.cs	2010-07-19 16:58:26 UTC (rev 5039)
@@ -135,6 +135,11 @@
 			public string Fullname { get { return m_schema == null ? m_name : m_schema + ":" + m_name; } }
             public string FullnameDecoded { get { return Utility.DecodeFDOName(this.Fullname); } }
 			public FeatureSetColumn[] Columns { get { return m_columns; } }
+
+            public override string ToString()
+            {
+                return this.FullnameDecoded;
+            }
 		}
 	}
 



More information about the mapguide-commits mailing list