[mapguide-commits] r6734 - in trunk/Tools/Maestro: Install Maestro.Editors Maestro.Editors/MapDefinition Maestro.Editors/MapDefinition/Live Maestro.MapViewer OSGeo.MapGuide.MaestroAPI/Mapping

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Jun 5 07:52:06 PDT 2012


Author: jng
Date: 2012-06-05 07:52:05 -0700 (Tue, 05 Jun 2012)
New Revision: 6734

Added:
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.Designer.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.resx
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.Designer.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.resx
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.Designer.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.resx
Modified:
   trunk/Tools/Maestro/Install/Maestro.nsi
   trunk/Tools/Maestro/Maestro.Editors/Maestro.Editors.csproj
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.cs
   trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.resx
   trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs
Log:
#2018: More Live Map Definition editor work:
 - Add context menus and buttons to add new layer groups and layers
 - Implement "Draw Order" view for layers and implement layer re-ordering
 - Add a new CollectionChanged event for layer and group collection classes
 - Add new files to NSIS installer

Modified: trunk/Tools/Maestro/Install/Maestro.nsi
===================================================================
--- trunk/Tools/Maestro/Install/Maestro.nsi	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/Install/Maestro.nsi	2012-06-05 14:52:05 UTC (rev 6734)
@@ -38,11 +38,11 @@
 
 # Globals
 !ifndef SLN_CONFIG
-	!define SLN_CONFIG "Release" #"Debug"
+    !define SLN_CONFIG "Release" #"Debug"
 !endif
 
 !ifndef CPU
-	!define CPU "x86"
+    !define CPU "x86"
 !endif
 
 !echo "Building installer in configuration: ${SLN_CONFIG} (${CPU})"
@@ -50,7 +50,7 @@
 !define SLN_DIR ".."
 !define SLN_THIRDPARTY "${SLN_DIR}\Thirdparty"
 !ifndef RELEASE_VERSION
-	!define RELEASE_VERSION "Trunk"
+    !define RELEASE_VERSION "Trunk"
 !endif
 
 # Installer vars
@@ -162,65 +162,65 @@
 # default section
 Section 
 
-	; Windows > Vista
-	SetShellVarContext all
+    ; Windows > Vista
+    SetShellVarContext all
 
-	; Registry
-	!if ${CPU} == "x64"
-	SetRegView 64
-	!else
-	SetRegView 32
-	!endif
+    ; Registry
+    !if ${CPU} == "x64"
+    SetRegView 64
+    !else
+    SetRegView 32
+    !endif
 
-	# set installation dir
-	SetOutPath $INSTDIR
-	
-	# directories / core addins
-	File /r "${INST_OUTPUT_MAESTRO}\AddIns"
+    # set installation dir
+    SetOutPath $INSTDIR
+    
+    # directories / core addins
+    File /r "${INST_OUTPUT_MAESTRO}\AddIns"
     File /r "${INST_OUTPUT_MAESTRO}\Data"
     File /r "${INST_OUTPUT_MAESTRO}\Schemas"
     File /r "${INST_OUTPUT_MAESTRO}\UserDoc"
-	
-	# docs
-	#File "${INST_OUTPUT_MAESTRO}\${HELP_USER}"
-	#File "${INST_OUTPUT_MAESTRO}\${HELP_API}"
-	File "${INST_OUTPUT_MAESTRO}\changelog.txt"
-	File "${INST_OUTPUT_MAESTRO}\license.txt"
-	
-	# data/config files
+    
+    # docs
+    #File "${INST_OUTPUT_MAESTRO}\${HELP_USER}"
+    #File "${INST_OUTPUT_MAESTRO}\${HELP_API}"
+    File "${INST_OUTPUT_MAESTRO}\changelog.txt"
+    File "${INST_OUTPUT_MAESTRO}\license.txt"
+    
+    # data/config files
     File "${INST_OUTPUT_MAESTRO}\LocalConfigure.exe.config"
     File "${INST_OUTPUT_MAESTRO}\Maestro.exe.config"
     File "${INST_OUTPUT_MAESTRO}\MaestroFsPreview.exe.config"
     File "${INST_OUTPUT_MAESTRO}\MgCooker.exe.config"
     File "${INST_OUTPUT_MAESTRO}\MgCookerCmd.exe.config"
     File "${INST_OUTPUT_MAESTRO}\RtMapInspector.exe.config"
-	File "${INST_OUTPUT_MAESTRO}\ConnectionProviders.xml"
+    File "${INST_OUTPUT_MAESTRO}\ConnectionProviders.xml"
     File "${INST_OUTPUT_MAESTRO}\FsEditorMap.xml"
     File "${INST_OUTPUT_MAESTRO}\OdbcDriverMap.xml"
-	
-	# libraries
-	File "${INST_OUTPUT_MAESTRO}\Aga.Controls.dll"
+    
+    # libraries
+    File "${INST_OUTPUT_MAESTRO}\Aga.Controls.dll"
     File "${INST_OUTPUT_MAESTRO}\Ciloci.Flee.dll"
-	File "${INST_OUTPUT_MAESTRO}\ICSharpCode.Core.dll"
-	File "${INST_OUTPUT_MAESTRO}\ICSharpCode.Core.WinForms.dll"
+    File "${INST_OUTPUT_MAESTRO}\ICSharpCode.Core.dll"
+    File "${INST_OUTPUT_MAESTRO}\ICSharpCode.Core.WinForms.dll"
     File "${INST_OUTPUT_MAESTRO}\ICSharpCode.SharpZipLib.dll"
     File "${INST_OUTPUT_MAESTRO}\ICSharpCode.TextEditor.dll"
     File "${INST_OUTPUT_MAESTRO}\IronPython.dll"
     File "${INST_OUTPUT_MAESTRO}\IronPython.Modules.dll"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Base.dll"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Editors.dll"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Base.dll"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Editors.dll"
     File "${INST_OUTPUT_MAESTRO}\Maestro.LiveMapEditor.exe"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Login.dll"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Login.dll"
     File "${INST_OUTPUT_MAESTRO}\Maestro.MapViewer.dll"
     File "${INST_OUTPUT_MAESTRO}\Maestro.Packaging.dll"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Shared.UI.dll"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Shared.UI.dll"
     File "${INST_OUTPUT_MAESTRO}\Microsoft.Dynamic.dll"
     File "${INST_OUTPUT_MAESTRO}\Microsoft.Scripting.dll"
     File "${INST_OUTPUT_MAESTRO}\Microsoft.Scripting.Metadata.dll"
     File "${INST_OUTPUT_MAESTRO}\NetTopologySuite.Merged.dll"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.ExtendedObjectModels.dll"
-	File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.dll"
-	File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.Http.dll"
+    File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.dll"
+    File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.Http.dll"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.Native32-2.2.0.dll"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.ObjectModels.LayerDefinition-1.1.0.dll"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.ObjectModels.LayerDefinition-1.2.0.dll"
@@ -245,15 +245,15 @@
     File "${INST_OUTPUT_MAESTRO}\MaestroFsPreview.pdb"
     File "${INST_OUTPUT_MAESTRO}\MgCooker.pdb"
     File "${INST_OUTPUT_MAESTRO}\MgCookerCmd.pdb"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Base.pdb"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Editors.pdb"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Base.pdb"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Editors.pdb"
     File "${INST_OUTPUT_MAESTRO}\Maestro.LiveMapEditor.pdb"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Login.pdb"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Login.pdb"
     File "${INST_OUTPUT_MAESTRO}\Maestro.MapViewer.pdb"
     File "${INST_OUTPUT_MAESTRO}\Maestro.Packaging.pdb"
-	File "${INST_OUTPUT_MAESTRO}\Maestro.Shared.UI.pdb"
-	File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.pdb"
-	File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.Http.pdb"
+    File "${INST_OUTPUT_MAESTRO}\Maestro.Shared.UI.pdb"
+    File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.pdb"
+    File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.Http.pdb"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.MaestroAPI.Native32-2.2.0.pdb"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.ObjectModels.LayerDefinition-1.1.0.pdb"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.ObjectModels.LayerDefinition-1.2.0.pdb"
@@ -271,85 +271,86 @@
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.ObjectModels.WebLayout-1.1.0.pdb"
     File "${INST_OUTPUT_MAESTRO}\OSGeo.MapGuide.ObjectModels.WebLayout-2.4.0.pdb"
     File "${INST_OUTPUT_MAESTRO}\RtMapInspector.pdb"
-	
-	# main executables
-	File "${INST_OUTPUT_MAESTRO}\${EXE_MAESTRO}"
+
+    # main executables
+    File "${INST_OUTPUT_MAESTRO}\${EXE_MAESTRO}"
     File "${INST_OUTPUT_MAESTRO}\LocalConfigure.exe"
-	File "${INST_OUTPUT_MAESTRO}\MgCooker.exe"
+    File "${INST_OUTPUT_MAESTRO}\MgCooker.exe"
     File "${INST_OUTPUT_MAESTRO}\MgCookerCmd.exe"
     File "${INST_OUTPUT_MAESTRO}\MaestroFsPreview.exe"
     File "${INST_OUTPUT_MAESTRO}\RtMapInspector.exe"
-	
-	# create uninstaller
-	WriteUninstaller "$INSTDIR\uninstall.exe"
-	
-	# create Add/Remove Programs entry
-	WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
-					 "DisplayName" "${INST_PRODUCT_NAME}"
 
-	WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
-					 "UninstallString" "$INSTDIR\uninstall.exe"
-	
-	WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
-					 "URLInfoAbout" "${PROJECT_URL}"
-	
-	WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
-					 "DisplayVersion" "${RELEASE_VERSION}"
-	
-	# TODO: Add more useful information to Add/Remove programs
-	# See: http://nsis.sourceforge.net/Add_uninstall_information_to_Add/Remove_Programs
-	
-	# create Maestro shortcuts. Use INST_PRODUCT_QUALIFIED so we can have x86 and x64 entries that don't clash
-	CreateDirectory "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}"
-	
-	CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\${LNK_MAESTRO}.lnk" "$INSTDIR\${EXE_MAESTRO}"
-	CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\MgCooker.lnk" "$INSTDIR\MgCooker.exe"
+    # create uninstaller
+    WriteUninstaller "$INSTDIR\uninstall.exe"
+
+    # create Add/Remove Programs entry
+    WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
+                      "DisplayName" "${INST_PRODUCT_NAME}"
+
+    WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
+                      "UninstallString" "$INSTDIR\uninstall.exe"
+
+    WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
+                      "URLInfoAbout" "${PROJECT_URL}"
+
+    WriteRegStr HKLM "${REG_KEY_UNINSTALL}" \
+                      "DisplayVersion" "${RELEASE_VERSION}"
+
+    # TODO: Add more useful information to Add/Remove programs
+    # See: http://nsis.sourceforge.net/Add_uninstall_information_to_Add/Remove_Programs
+    
+    # create Maestro shortcuts. Use INST_PRODUCT_QUALIFIED so we can have x86 and x64 entries that don't clash
+    CreateDirectory "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}"
+    
+    CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\${LNK_MAESTRO}.lnk" "$INSTDIR\${EXE_MAESTRO}"
+    CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\MgCooker.lnk" "$INSTDIR\MgCooker.exe"
     CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\Maestro Feature Source Preview.lnk" "$INSTDIR\MaestroFsPreview.exe"
-	#CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\User Documentation.lnk" "$INSTDIR\${HELP_USER}"
-	#CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\Core API Documentation.lnk" "$INSTDIR\${HELP_API}"
-	CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\Uninstall.lnk" "$INSTDIR\uninstall.exe"
-	
-	CreateShortCut "$DESKTOP\${LNK_MAESTRO}.lnk" "$INSTDIR\${EXE_MAESTRO}"
-	
+    CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\Live Map Definition Editor.lnk" "$INSTDIR\Maestro.LiveMapEditor.exe"
+    #CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\User Documentation.lnk" "$INSTDIR\${HELP_USER}"
+    #CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\Core API Documentation.lnk" "$INSTDIR\${HELP_API}"
+    CreateShortCut "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}\Uninstall.lnk" "$INSTDIR\uninstall.exe"
+    
+    CreateShortCut "$DESKTOP\${LNK_MAESTRO}.lnk" "$INSTDIR\${EXE_MAESTRO}"
+    
 SectionEnd
 
 # uninstall section
 Section "uninstall"
-	; Windows > Vista
-	SetShellVarContext all
+    ; Windows > Vista
+    SetShellVarContext all
 
-	; Registry
-	!if ${CPU} == "x64"
-	SetRegView 64
-	!else
-	SetRegView 32
-	!endif
+    ; Registry
+    !if ${CPU} == "x64"
+    SetRegView 64
+    !else
+    SetRegView 32
+    !endif
 
     # remove uninstaller
-	Delete "$INSTDIR\uninstall.exe"
-	
-	# remove desktop shortcut
-	Delete "$DESKTOP\${LNK_MAESTRO}.lnk"
-	
-	# remove Add/Remove programs registry entry
-	DeleteRegKey HKLM "${REG_KEY_UNINSTALL}"
-	
-	# remove installation directory
-	RMDir /r "$INSTDIR"
-	
-	# remove shortcuts
-	RMDir /r "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}"
+    Delete "$INSTDIR\uninstall.exe"
+    
+    # remove desktop shortcut
+    Delete "$DESKTOP\${LNK_MAESTRO}.lnk"
+    
+    # remove Add/Remove programs registry entry
+    DeleteRegKey HKLM "${REG_KEY_UNINSTALL}"
+    
+    # remove installation directory
+    RMDir /r "$INSTDIR"
+    
+    # remove shortcuts
+    RMDir /r "$SMPROGRAMS\${INST_PRODUCT_QUALIFIED}"
 SectionEnd
 
 Function .onInit
-	; Registry
-	!if ${CPU} == "x64"
-	SetRegView 64
-	!else
-	SetRegView 32
-	!endif
-	
-	!insertmacro MUI_LANGDLL_DISPLAY
+    ; Registry
+    !if ${CPU} == "x64"
+    SetRegView 64
+    !else
+    SetRegView 32
+    !endif
+    
+    !insertmacro MUI_LANGDLL_DISPLAY
 
     ; Check for .NET Framework 4.0
     ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" Install
@@ -363,7 +364,7 @@
 FunctionEnd
 
 Function LaunchLink
-	; TODO: Needs to launch under standard user. If installer was run under UAC elevated privileges, it will run under the
-	; user who elevated these privileges.
-	ExecShell "" "$INSTDIR\${EXE_MAESTRO}"
+    ; TODO: Needs to launch under standard user. If installer was run under UAC elevated privileges, it will run under the
+    ; user who elevated these privileges.
+    ExecShell "" "$INSTDIR\${EXE_MAESTRO}"
 FunctionEnd

Modified: trunk/Tools/Maestro/Maestro.Editors/Maestro.Editors.csproj
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/Maestro.Editors.csproj	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/Maestro.Editors/Maestro.Editors.csproj	2012-06-05 14:52:05 UTC (rev 6734)
@@ -886,6 +886,24 @@
     <Compile Include="MapDefinition\LiveMapDefinitionEditorCtrl.Designer.cs">
       <DependentUpon>LiveMapDefinitionEditorCtrl.cs</DependentUpon>
     </Compile>
+    <Compile Include="MapDefinition\LiveMapEditorDrawOrder.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="MapDefinition\LiveMapEditorDrawOrder.Designer.cs">
+      <DependentUpon>LiveMapEditorDrawOrder.cs</DependentUpon>
+    </Compile>
+    <Compile Include="MapDefinition\LiveMapEditorLegend.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="MapDefinition\LiveMapEditorLegend.Designer.cs">
+      <DependentUpon>LiveMapEditorLegend.cs</DependentUpon>
+    </Compile>
+    <Compile Include="MapDefinition\Live\NewGroupDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="MapDefinition\Live\NewGroupDialog.Designer.cs">
+      <DependentUpon>NewGroupDialog.cs</DependentUpon>
+    </Compile>
     <Compile Include="MapDefinition\ManualScaleEditor.cs">
       <SubType>Form</SubType>
     </Compile>
@@ -1638,6 +1656,15 @@
     <EmbeddedResource Include="MapDefinition\LiveMapDefinitionEditorCtrl.resx">
       <DependentUpon>LiveMapDefinitionEditorCtrl.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="MapDefinition\LiveMapEditorDrawOrder.resx">
+      <DependentUpon>LiveMapEditorDrawOrder.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="MapDefinition\LiveMapEditorLegend.resx">
+      <DependentUpon>LiveMapEditorLegend.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="MapDefinition\Live\NewGroupDialog.resx">
+      <DependentUpon>NewGroupDialog.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="MapDefinition\ManualScaleEditor.resx">
       <DependentUpon>ManualScaleEditor.cs</DependentUpon>
     </EmbeddedResource>

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.Designer.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,136 @@
+namespace Maestro.Editors.MapDefinition.Live
+{
+    partial class NewGroupDialog
+    {
+        /// <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 Windows Form 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.txtLegendLabel = new System.Windows.Forms.TextBox();
+            this.btnOK = new System.Windows.Forms.Button();
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.lblDuplicateName = new System.Windows.Forms.Label();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(9, 13);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(35, 13);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Name";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(9, 58);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(72, 13);
+            this.label2.TabIndex = 1;
+            this.label2.Text = "Legend Label";
+            // 
+            // txtName
+            // 
+            this.txtName.Location = new System.Drawing.Point(12, 29);
+            this.txtName.Name = "txtName";
+            this.txtName.Size = new System.Drawing.Size(325, 20);
+            this.txtName.TabIndex = 2;
+            this.txtName.TextChanged += new System.EventHandler(this.txtName_TextChanged);
+            // 
+            // txtLegendLabel
+            // 
+            this.txtLegendLabel.Location = new System.Drawing.Point(12, 74);
+            this.txtLegendLabel.Name = "txtLegendLabel";
+            this.txtLegendLabel.Size = new System.Drawing.Size(325, 20);
+            this.txtLegendLabel.TabIndex = 3;
+            this.txtLegendLabel.TextChanged += new System.EventHandler(this.txtLegendLabel_TextChanged);
+            // 
+            // btnOK
+            // 
+            this.btnOK.Enabled = false;
+            this.btnOK.Location = new System.Drawing.Point(181, 115);
+            this.btnOK.Name = "btnOK";
+            this.btnOK.Size = new System.Drawing.Size(75, 23);
+            this.btnOK.TabIndex = 4;
+            this.btnOK.Text = "OK";
+            this.btnOK.UseVisualStyleBackColor = true;
+            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Location = new System.Drawing.Point(262, 115);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(75, 23);
+            this.btnCancel.TabIndex = 5;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // lblDuplicateName
+            // 
+            this.lblDuplicateName.AutoSize = true;
+            this.lblDuplicateName.ForeColor = System.Drawing.Color.Red;
+            this.lblDuplicateName.Location = new System.Drawing.Point(12, 120);
+            this.lblDuplicateName.Name = "lblDuplicateName";
+            this.lblDuplicateName.Size = new System.Drawing.Size(104, 13);
+            this.lblDuplicateName.TabIndex = 6;
+            this.lblDuplicateName.Text = "Name already exists!";
+            this.lblDuplicateName.Visible = false;
+            // 
+            // NewGroupDialog
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(349, 150);
+            this.ControlBox = false;
+            this.Controls.Add(this.lblDuplicateName);
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnOK);
+            this.Controls.Add(this.txtLegendLabel);
+            this.Controls.Add(this.txtName);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.label1);
+            this.Name = "NewGroupDialog";
+            this.Text = "New Group";
+            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 txtLegendLabel;
+        private System.Windows.Forms.Button btnOK;
+        private System.Windows.Forms.Button btnCancel;
+        private System.Windows.Forms.Label lblDuplicateName;
+    }
+}
\ No newline at end of file

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,73 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using OSGeo.MapGuide.MaestroAPI.Mapping;
+
+namespace Maestro.Editors.MapDefinition.Live
+{
+    public partial class NewGroupDialog : Form
+    {
+        private RuntimeMap _map;
+
+        public NewGroupDialog(RuntimeMap map)
+        {
+            InitializeComponent();
+            _map = map;
+        }
+
+        public string GroupName { get { return txtName.Text; } }
+
+        public string GroupLabel { get { return txtLegendLabel.Text; } }
+
+        private void btnCancel_Click(object sender, EventArgs e)
+        {
+            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+        }
+
+        private void btnOK_Click(object sender, EventArgs e)
+        {
+            this.DialogResult = System.Windows.Forms.DialogResult.OK;
+        }
+
+        private void txtName_TextChanged(object sender, EventArgs e)
+        {
+            string name = txtName.Text.Trim();
+            string label = txtLegendLabel.Text.Trim();
+
+            btnOK.Enabled = !string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(label) && _map.Groups[name] == null;
+            lblDuplicateName.Visible = (_map.Groups[name] != null);
+        }
+
+        private void txtLegendLabel_TextChanged(object sender, EventArgs e)
+        {
+            string name = txtName.Text.Trim();
+            string label = txtLegendLabel.Text.Trim();
+
+            btnOK.Enabled = !string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(label);
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.resx	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/Live/NewGroupDialog.resx	2012-06-05 14:52:05 UTC (rev 6734)
@@ -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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.Designer.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -28,22 +28,14 @@
         /// </summary>
         private void InitializeComponent()
         {
-            this.components = new System.ComponentModel.Container();
             this.splitContainer1 = new System.Windows.Forms.SplitContainer();
             this.splitContainer2 = new System.Windows.Forms.SplitContainer();
             this.tabLayersAndGroups = new System.Windows.Forms.TabControl();
             this.TAB_LEGEND = new System.Windows.Forms.TabPage();
-            this.legendCtrl = new Maestro.MapViewer.Legend();
-            this.ctxLegend = new System.Windows.Forms.ContextMenuStrip(this.components);
-            this.addNewGroupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.addNewLayerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.grpContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
-            this.addLayerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.removeThisGroupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.layerContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
-            this.removeThisLayerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.legendCtrl = new Maestro.Editors.MapDefinition.LiveMapEditorLegend();
             this.viewer = new Maestro.MapViewer.MapViewer();
             this.TAB_DRAW_ORDER = new System.Windows.Forms.TabPage();
+            this.drawOrderCtrl = new Maestro.Editors.MapDefinition.LiveMapEditorDrawOrder();
             this.tabProperties = new System.Windows.Forms.TabControl();
             this.TAB_PROPERTIES = new System.Windows.Forms.TabPage();
             this.propGrid = new System.Windows.Forms.PropertyGrid();
@@ -63,9 +55,7 @@
             this.splitContainer2.SuspendLayout();
             this.tabLayersAndGroups.SuspendLayout();
             this.TAB_LEGEND.SuspendLayout();
-            this.ctxLegend.SuspendLayout();
-            this.grpContextMenu.SuspendLayout();
-            this.layerContextMenu.SuspendLayout();
+            this.TAB_DRAW_ORDER.SuspendLayout();
             this.tabProperties.SuspendLayout();
             this.TAB_PROPERTIES.SuspendLayout();
             this.statusStrip.SuspendLayout();
@@ -132,77 +122,15 @@
             // 
             // legendCtrl
             // 
-            this.legendCtrl.ContextMenuStrip = this.ctxLegend;
             this.legendCtrl.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.legendCtrl.GroupContextMenu = this.grpContextMenu;
-            this.legendCtrl.LayerContextMenu = this.layerContextMenu;
             this.legendCtrl.Location = new System.Drawing.Point(3, 3);
             this.legendCtrl.Name = "legendCtrl";
-            this.legendCtrl.ShowTooltips = true;
             this.legendCtrl.Size = new System.Drawing.Size(275, 135);
             this.legendCtrl.TabIndex = 0;
-            this.legendCtrl.ThemeCompressionLimit = 25;
             this.legendCtrl.Viewer = this.viewer;
-            this.legendCtrl.NodeSelected += new Maestro.MapViewer.NodeSelectionEventHandler(this.legendCtrl_NodeSelected);
+            this.legendCtrl.NodeDeleted += new Maestro.MapViewer.NodeEventHandler(this.legendCtrl_NodeDeleted);
+            this.legendCtrl.NodeSelected += new Maestro.MapViewer.NodeEventHandler(this.legendCtrl_NodeSelected);
             // 
-            // ctxLegend
-            // 
-            this.ctxLegend.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.addNewGroupToolStripMenuItem,
-            this.addNewLayerToolStripMenuItem});
-            this.ctxLegend.Name = "ctxLegend";
-            this.ctxLegend.Size = new System.Drawing.Size(160, 48);
-            // 
-            // addNewGroupToolStripMenuItem
-            // 
-            this.addNewGroupToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.folder__plus;
-            this.addNewGroupToolStripMenuItem.Name = "addNewGroupToolStripMenuItem";
-            this.addNewGroupToolStripMenuItem.Size = new System.Drawing.Size(159, 22);
-            this.addNewGroupToolStripMenuItem.Text = "Add New Group";
-            // 
-            // addNewLayerToolStripMenuItem
-            // 
-            this.addNewLayerToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.layer__plus;
-            this.addNewLayerToolStripMenuItem.Name = "addNewLayerToolStripMenuItem";
-            this.addNewLayerToolStripMenuItem.Size = new System.Drawing.Size(159, 22);
-            this.addNewLayerToolStripMenuItem.Text = "Add New Layer";
-            // 
-            // grpContextMenu
-            // 
-            this.grpContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.addLayerToolStripMenuItem,
-            this.removeThisGroupToolStripMenuItem});
-            this.grpContextMenu.Name = "grpContextMenu";
-            this.grpContextMenu.Size = new System.Drawing.Size(179, 48);
-            // 
-            // addLayerToolStripMenuItem
-            // 
-            this.addLayerToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.layer__plus;
-            this.addLayerToolStripMenuItem.Name = "addLayerToolStripMenuItem";
-            this.addLayerToolStripMenuItem.Size = new System.Drawing.Size(178, 22);
-            this.addLayerToolStripMenuItem.Text = "Add Layer";
-            // 
-            // removeThisGroupToolStripMenuItem
-            // 
-            this.removeThisGroupToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.folder__minus;
-            this.removeThisGroupToolStripMenuItem.Name = "removeThisGroupToolStripMenuItem";
-            this.removeThisGroupToolStripMenuItem.Size = new System.Drawing.Size(178, 22);
-            this.removeThisGroupToolStripMenuItem.Text = "Remove This Group";
-            // 
-            // layerContextMenu
-            // 
-            this.layerContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.removeThisLayerToolStripMenuItem});
-            this.layerContextMenu.Name = "layerContextMenu";
-            this.layerContextMenu.Size = new System.Drawing.Size(174, 26);
-            // 
-            // removeThisLayerToolStripMenuItem
-            // 
-            this.removeThisLayerToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.layer__minus;
-            this.removeThisLayerToolStripMenuItem.Name = "removeThisLayerToolStripMenuItem";
-            this.removeThisLayerToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
-            this.removeThisLayerToolStripMenuItem.Text = "Remove This Layer";
-            // 
             // viewer
             // 
             this.viewer.Cursor = System.Windows.Forms.Cursors.Default;
@@ -219,14 +147,26 @@
             // 
             // TAB_DRAW_ORDER
             // 
+            this.TAB_DRAW_ORDER.Controls.Add(this.drawOrderCtrl);
             this.TAB_DRAW_ORDER.Location = new System.Drawing.Point(4, 22);
             this.TAB_DRAW_ORDER.Name = "TAB_DRAW_ORDER";
             this.TAB_DRAW_ORDER.Padding = new System.Windows.Forms.Padding(3);
-            this.TAB_DRAW_ORDER.Size = new System.Drawing.Size(197, 141);
+            this.TAB_DRAW_ORDER.Size = new System.Drawing.Size(281, 141);
             this.TAB_DRAW_ORDER.TabIndex = 1;
             this.TAB_DRAW_ORDER.Text = "Draw Order";
             this.TAB_DRAW_ORDER.UseVisualStyleBackColor = true;
             // 
+            // drawOrderCtrl
+            // 
+            this.drawOrderCtrl.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.drawOrderCtrl.Location = new System.Drawing.Point(3, 3);
+            this.drawOrderCtrl.Name = "drawOrderCtrl";
+            this.drawOrderCtrl.Size = new System.Drawing.Size(275, 135);
+            this.drawOrderCtrl.TabIndex = 0;
+            this.drawOrderCtrl.Viewer = this.viewer;
+            this.drawOrderCtrl.LayerChanged += new Maestro.Editors.MapDefinition.LayerEventHandler(this.drawOrderCtrl_LayerChanged);
+            this.drawOrderCtrl.LayerDeleted += new Maestro.Editors.MapDefinition.LayerEventHandler(this.drawOrderCtrl_LayerDeleted);
+            // 
             // tabProperties
             // 
             this.tabProperties.Controls.Add(this.TAB_PROPERTIES);
@@ -320,9 +260,7 @@
             this.splitContainer2.ResumeLayout(false);
             this.tabLayersAndGroups.ResumeLayout(false);
             this.TAB_LEGEND.ResumeLayout(false);
-            this.ctxLegend.ResumeLayout(false);
-            this.grpContextMenu.ResumeLayout(false);
-            this.layerContextMenu.ResumeLayout(false);
+            this.TAB_DRAW_ORDER.ResumeLayout(false);
             this.tabProperties.ResumeLayout(false);
             this.TAB_PROPERTIES.ResumeLayout(false);
             this.statusStrip.ResumeLayout(false);
@@ -331,6 +269,8 @@
             this.PerformLayout();
 
         }
+        private Maestro.Editors.MapDefinition.LiveMapEditorDrawOrder drawOrderCtrl;
+        private Maestro.Editors.MapDefinition.LiveMapEditorLegend legendCtrl;
 
         #endregion
 
@@ -340,20 +280,11 @@
         private System.Windows.Forms.TabPage TAB_DRAW_ORDER;
         private MapViewer.MapViewer viewer;
         private MapViewer.DefaultToolbar toolbar;
-        private MapViewer.Legend legendCtrl;
         private System.Windows.Forms.StatusStrip statusStrip;
         private System.Windows.Forms.ToolStripStatusLabel lblCoordinates;
         private System.Windows.Forms.ToolStripStatusLabel lblSelected;
         private System.Windows.Forms.ToolStripStatusLabel lblScale;
         private MapViewer.MapStatusTracker mapStatusTracker;
-        private System.Windows.Forms.ContextMenuStrip grpContextMenu;
-        private System.Windows.Forms.ContextMenuStrip layerContextMenu;
-        private System.Windows.Forms.ToolStripMenuItem addLayerToolStripMenuItem;
-        private System.Windows.Forms.ToolStripMenuItem removeThisLayerToolStripMenuItem;
-        private System.Windows.Forms.ToolStripMenuItem removeThisGroupToolStripMenuItem;
-        private System.Windows.Forms.ContextMenuStrip ctxLegend;
-        private System.Windows.Forms.ToolStripMenuItem addNewGroupToolStripMenuItem;
-        private System.Windows.Forms.ToolStripMenuItem addNewLayerToolStripMenuItem;
         private System.Windows.Forms.SplitContainer splitContainer2;
         private System.Windows.Forms.TabControl tabProperties;
         private System.Windows.Forms.TabPage TAB_PROPERTIES;

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.cs	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -95,5 +95,24 @@
                 return;
             propGrid.SelectedObject = node.Tag;
         }
+
+        private void drawOrderCtrl_LayerChanged(object sender, RuntimeMapLayer layer)
+        {
+            propGrid.SelectedObject = layer;
+        }
+
+        private void drawOrderCtrl_LayerDeleted(object sender, RuntimeMapLayer layer)
+        {
+            if (layer == propGrid.SelectedObject)
+                propGrid.SelectedObject = null;
+        }
+
+        private void legendCtrl_NodeDeleted(object sender, TreeNode node)
+        {
+            var layer = node.Tag as Maestro.MapViewer.Legend.LayerNodeMetadata;
+            //Nothing to edit for theme rule nodes
+            if (layer != null && layer == propGrid.SelectedObject)
+                propGrid.SelectedObject = null;
+        }
     }
 }

Modified: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.resx	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapDefinitionEditorCtrl.resx	2012-06-05 14:52:05 UTC (rev 6734)
@@ -117,15 +117,6 @@
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
-  <metadata name="ctxLegend.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>672, 17</value>
-  </metadata>
-  <metadata name="grpContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>366, 17</value>
-  </metadata>
-  <metadata name="layerContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>521, 17</value>
-  </metadata>
   <metadata name="toolbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>17, 17</value>
   </metadata>

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.Designer.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,124 @@
+
+namespace Maestro.Editors.MapDefinition
+{
+    partial class LiveMapEditorDrawOrder
+    {
+        /// <summary>
+        /// Designer variable used to keep track of non-visual components.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+        
+        /// <summary>
+        /// Disposes resources used by the control.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing) {
+                if (components != null) {
+                    components.Dispose();
+                }
+            }
+            base.Dispose(disposing);
+        }
+        
+        /// <summary>
+        /// This method is required for Windows Forms designer support.
+        /// Do not change the method contents inside the source code editor. The Forms designer might
+        /// not be able to load this method if it was changed manually.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+            this.btnUp = new System.Windows.Forms.ToolStripButton();
+            this.btnDown = new System.Windows.Forms.ToolStripButton();
+            this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+            this.btnDelete = new System.Windows.Forms.ToolStripButton();
+            this.lstDrawOrder = new System.Windows.Forms.ListBox();
+            this.toolStrip1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // toolStrip1
+            // 
+            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.btnUp,
+            this.btnDown,
+            this.toolStripSeparator1,
+            this.btnDelete});
+            this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+            this.toolStrip1.Name = "toolStrip1";
+            this.toolStrip1.Size = new System.Drawing.Size(241, 25);
+            this.toolStrip1.TabIndex = 0;
+            this.toolStrip1.Text = "toolStrip1";
+            // 
+            // btnUp
+            // 
+            this.btnUp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnUp.Enabled = false;
+            this.btnUp.Image = global::Maestro.Editors.Properties.Resources.arrow_090;
+            this.btnUp.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnUp.Name = "btnUp";
+            this.btnUp.Size = new System.Drawing.Size(23, 22);
+            this.btnUp.Text = "Move Up";
+            this.btnUp.Click += new System.EventHandler(this.btnUp_Click);
+            // 
+            // btnDown
+            // 
+            this.btnDown.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnDown.Enabled = false;
+            this.btnDown.Image = global::Maestro.Editors.Properties.Resources.arrow_270;
+            this.btnDown.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnDown.Name = "btnDown";
+            this.btnDown.Size = new System.Drawing.Size(23, 22);
+            this.btnDown.Text = "Move Down";
+            this.btnDown.Click += new System.EventHandler(this.btnDown_Click);
+            // 
+            // toolStripSeparator1
+            // 
+            this.toolStripSeparator1.Name = "toolStripSeparator1";
+            this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
+            // 
+            // btnDelete
+            // 
+            this.btnDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnDelete.Enabled = false;
+            this.btnDelete.Image = global::Maestro.Editors.Properties.Resources.cross_script;
+            this.btnDelete.ImageTransparentColor = System.Drawing.Color.Magenta;
+            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);
+            // 
+            // lstDrawOrder
+            // 
+            this.lstDrawOrder.DisplayMember = "LegendLabel";
+            this.lstDrawOrder.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.lstDrawOrder.FormattingEnabled = true;
+            this.lstDrawOrder.Location = new System.Drawing.Point(0, 25);
+            this.lstDrawOrder.Name = "lstDrawOrder";
+            this.lstDrawOrder.Size = new System.Drawing.Size(241, 380);
+            this.lstDrawOrder.TabIndex = 1;
+            this.lstDrawOrder.SelectedIndexChanged += new System.EventHandler(this.lstDrawOrder_SelectedIndexChanged);
+            // 
+            // LiveMapEditorDrawOrder
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.lstDrawOrder);
+            this.Controls.Add(this.toolStrip1);
+            this.Name = "LiveMapEditorDrawOrder";
+            this.Size = new System.Drawing.Size(241, 405);
+            this.toolStrip1.ResumeLayout(false);
+            this.toolStrip1.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+        private System.Windows.Forms.ToolStripButton btnDelete;
+        private System.Windows.Forms.ToolStripButton btnDown;
+        private System.Windows.Forms.ToolStripButton btnUp;
+        private System.Windows.Forms.ListBox lstDrawOrder;
+        private System.Windows.Forms.ToolStrip toolStrip1;
+    }
+}

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,182 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+using Maestro.MapViewer;
+using OSGeo.MapGuide.MaestroAPI.Mapping;
+
+namespace Maestro.Editors.MapDefinition
+{
+    /// <summary>
+    /// Description of LiveMapEditorDrawOrder.
+    /// </summary>
+    public partial class LiveMapEditorDrawOrder : UserControl
+    {
+        public LiveMapEditorDrawOrder()
+        {
+            InitializeComponent();
+        }
+        
+        private RuntimeMap _map;
+        private IMapViewer _viewer;
+        
+        public IMapViewer Viewer
+        {
+            get { return _viewer; }
+            set 
+            {
+                if (_viewer != value) 
+                {
+                    if (_viewer != null)
+                        _viewer.MapLoaded -= OnMapLoaded;
+                    UnbindMap();
+                    _viewer = value;
+                    if (_viewer != null)
+                    {
+                        _map = _viewer.GetMap();
+                        BindMap();
+                        _viewer.MapLoaded += OnMapLoaded;
+                    }
+                }
+            }
+        }
+
+        void OnMapLoaded(object sender, EventArgs e)
+        {
+            _map = _viewer.GetMap();
+            BindMap();
+        }
+        
+        private void OnMapLayersChanged(object sender, EventArgs e)
+        {
+            RefreshLayerList();
+        }
+        
+        private void UnbindMap() 
+        {
+            if (_map == null)
+                return;
+
+            _map.Layers.CollectionChanged -= OnMapLayersChanged;
+        }
+        
+        private void BindMap()
+        {
+            if (_map == null)
+                return;
+
+            RefreshLayerList();
+            _map.Layers.CollectionChanged += OnMapLayersChanged;
+        }
+
+        private void RefreshLayerList()
+        {
+            try
+            {
+                bSuppressSelectedIndexChanged = true;
+                var item = lstDrawOrder.SelectedItem as RuntimeMapLayer;
+                lstDrawOrder.DataSource = _map.Layers.OrderBy(x => x.DisplayOrder).ToArray();
+                if (item != null)
+                {
+                    var idx = lstDrawOrder.FindStringExact(item.LegendLabel);
+                    if (idx >= 0)
+                        lstDrawOrder.SelectedIndex = idx;
+                }
+            }
+            finally
+            {
+                bSuppressSelectedIndexChanged = false;
+            }
+        }
+
+        private bool bSuppressSelectedIndexChanged = false;
+
+        private void lstDrawOrder_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (bSuppressSelectedIndexChanged)
+                return;
+
+            btnUp.Enabled = btnDown.Enabled = btnDelete.Enabled = false;
+            var layer = lstDrawOrder.SelectedItem as RuntimeMapLayer;
+            if (layer != null)
+            {
+                btnUp.Enabled = btnDown.Enabled = btnDelete.Enabled = true;
+                var h = this.LayerChanged;
+                if (h != null)
+                    h(this, layer);
+            }
+        }
+
+        public event LayerEventHandler LayerChanged;
+
+        public event LayerEventHandler LayerDeleted;
+
+        private void btnUp_Click(object sender, EventArgs e)
+        {
+            if (_map == null)
+                return;
+
+            var layer = lstDrawOrder.SelectedItem as RuntimeMapLayer;
+            if (layer != null)
+            {
+                int idx = _map.Layers.IndexOf(layer);
+                if (idx > 0)
+                    idx--;
+                else
+                    return;
+                _map.Layers.SetNewIndex(idx, layer);
+                this.Viewer.RefreshMap();
+            }
+        }
+
+        private void btnDown_Click(object sender, EventArgs e)
+        {
+            if (_map == null)
+                return;
+
+            var layer = lstDrawOrder.SelectedItem as RuntimeMapLayer;
+            if (layer != null)
+            {
+                int idx = _map.Layers.IndexOf(layer);
+                if (idx < _map.Layers.Count - 1)
+                    idx++;
+                else
+                    return;
+                _map.Layers.SetNewIndex(idx, layer);
+                this.Viewer.RefreshMap();
+            }
+        }
+
+        private void btnDelete_Click(object sender, EventArgs e)
+        {
+            var layer = lstDrawOrder.SelectedItem as RuntimeMapLayer;
+            if (layer != null)
+            {
+                _map.Layers.Remove(layer);
+                this.Viewer.RefreshMap();
+            }
+        }
+    }
+
+    public delegate void LayerEventHandler(object sender, RuntimeMapLayer layer);
+}

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.resx	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorDrawOrder.resx	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,123 @@
+<?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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.Designer.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,196 @@
+
+namespace Maestro.Editors.MapDefinition
+{
+    partial class LiveMapEditorLegend
+    {
+        /// <summary>
+        /// Designer variable used to keep track of non-visual components.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+        
+        /// <summary>
+        /// Disposes resources used by the control.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing) {
+                if (components != null) {
+                    components.Dispose();
+                }
+            }
+            base.Dispose(disposing);
+        }
+        
+        /// <summary>
+        /// This method is required for Windows Forms designer support.
+        /// Do not change the method contents inside the source code editor. The Forms designer might
+        /// not be able to load this method if it was changed manually.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+            this.btnAddLayer = new System.Windows.Forms.ToolStripButton();
+            this.btnAddGroup = new System.Windows.Forms.ToolStripButton();
+            this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+            this.ctxLegend = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.addNewGroupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.addNewLayerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.grpContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.addLayerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.removeThisGroupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.layerContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.removeThisLayerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.legendCtrl = new Maestro.MapViewer.Legend();
+            this.toolStrip1.SuspendLayout();
+            this.ctxLegend.SuspendLayout();
+            this.grpContextMenu.SuspendLayout();
+            this.layerContextMenu.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // toolStrip1
+            // 
+            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.btnAddLayer,
+            this.btnAddGroup,
+            this.toolStripSeparator1});
+            this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+            this.toolStrip1.Name = "toolStrip1";
+            this.toolStrip1.Size = new System.Drawing.Size(275, 25);
+            this.toolStrip1.TabIndex = 0;
+            this.toolStrip1.Text = "toolStrip1";
+            // 
+            // btnAddLayer
+            // 
+            this.btnAddLayer.Image = global::Maestro.Editors.Properties.Resources.layer__plus;
+            this.btnAddLayer.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnAddLayer.Name = "btnAddLayer";
+            this.btnAddLayer.Size = new System.Drawing.Size(80, 22);
+            this.btnAddLayer.Text = "Add Layer";
+            this.btnAddLayer.Click += new System.EventHandler(this.btnAddLayer_Click);
+            // 
+            // btnAddGroup
+            // 
+            this.btnAddGroup.Image = global::Maestro.Editors.Properties.Resources.folder__plus;
+            this.btnAddGroup.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnAddGroup.Name = "btnAddGroup";
+            this.btnAddGroup.Size = new System.Drawing.Size(85, 22);
+            this.btnAddGroup.Text = "Add Group";
+            this.btnAddGroup.Click += new System.EventHandler(this.btnAddGroup_Click);
+            // 
+            // toolStripSeparator1
+            // 
+            this.toolStripSeparator1.Name = "toolStripSeparator1";
+            this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
+            // 
+            // ctxLegend
+            // 
+            this.ctxLegend.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.addNewGroupToolStripMenuItem,
+            this.addNewLayerToolStripMenuItem});
+            this.ctxLegend.Name = "ctxLegend";
+            this.ctxLegend.Size = new System.Drawing.Size(160, 48);
+            this.ctxLegend.Click += new System.EventHandler(this.btnAddLayer_Click);
+            // 
+            // addNewGroupToolStripMenuItem
+            // 
+            this.addNewGroupToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.folder__plus;
+            this.addNewGroupToolStripMenuItem.Name = "addNewGroupToolStripMenuItem";
+            this.addNewGroupToolStripMenuItem.Size = new System.Drawing.Size(159, 22);
+            this.addNewGroupToolStripMenuItem.Text = "Add New Group";
+            this.addNewGroupToolStripMenuItem.Click += new System.EventHandler(this.btnAddGroup_Click);
+            // 
+            // addNewLayerToolStripMenuItem
+            // 
+            this.addNewLayerToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.layer__plus;
+            this.addNewLayerToolStripMenuItem.Name = "addNewLayerToolStripMenuItem";
+            this.addNewLayerToolStripMenuItem.Size = new System.Drawing.Size(159, 22);
+            this.addNewLayerToolStripMenuItem.Text = "Add New Layer";
+            // 
+            // grpContextMenu
+            // 
+            this.grpContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.addLayerToolStripMenuItem,
+            this.removeThisGroupToolStripMenuItem});
+            this.grpContextMenu.Name = "grpContextMenu";
+            this.grpContextMenu.Size = new System.Drawing.Size(179, 48);
+            // 
+            // addLayerToolStripMenuItem
+            // 
+            this.addLayerToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.layer__plus;
+            this.addLayerToolStripMenuItem.Name = "addLayerToolStripMenuItem";
+            this.addLayerToolStripMenuItem.Size = new System.Drawing.Size(178, 22);
+            this.addLayerToolStripMenuItem.Text = "Add Layer";
+            this.addLayerToolStripMenuItem.Click += new System.EventHandler(this.addLayerToolStripMenuItem_Click);
+            // 
+            // removeThisGroupToolStripMenuItem
+            // 
+            this.removeThisGroupToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.folder__minus;
+            this.removeThisGroupToolStripMenuItem.Name = "removeThisGroupToolStripMenuItem";
+            this.removeThisGroupToolStripMenuItem.Size = new System.Drawing.Size(178, 22);
+            this.removeThisGroupToolStripMenuItem.Text = "Remove This Group";
+            this.removeThisGroupToolStripMenuItem.Click += new System.EventHandler(this.removeThisGroupToolStripMenuItem_Click);
+            // 
+            // layerContextMenu
+            // 
+            this.layerContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.removeThisLayerToolStripMenuItem});
+            this.layerContextMenu.Name = "layerContextMenu";
+            this.layerContextMenu.Size = new System.Drawing.Size(174, 26);
+            // 
+            // removeThisLayerToolStripMenuItem
+            // 
+            this.removeThisLayerToolStripMenuItem.Image = global::Maestro.Editors.Properties.Resources.layer__minus;
+            this.removeThisLayerToolStripMenuItem.Name = "removeThisLayerToolStripMenuItem";
+            this.removeThisLayerToolStripMenuItem.Size = new System.Drawing.Size(173, 22);
+            this.removeThisLayerToolStripMenuItem.Text = "Remove This Layer";
+            this.removeThisLayerToolStripMenuItem.Click += new System.EventHandler(this.removeThisLayerToolStripMenuItem_Click);
+            // 
+            // legendCtrl
+            // 
+            this.legendCtrl.ContextMenuStrip = this.ctxLegend;
+            this.legendCtrl.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.legendCtrl.GroupContextMenu = this.grpContextMenu;
+            this.legendCtrl.LayerContextMenu = this.layerContextMenu;
+            this.legendCtrl.Location = new System.Drawing.Point(0, 25);
+            this.legendCtrl.Name = "legendCtrl";
+            this.legendCtrl.SelectOnRightClick = true;
+            this.legendCtrl.ShowTooltips = true;
+            this.legendCtrl.Size = new System.Drawing.Size(275, 356);
+            this.legendCtrl.TabIndex = 1;
+            this.legendCtrl.ThemeCompressionLimit = 25;
+            this.legendCtrl.Viewer = null;
+            // 
+            // LiveMapEditorLegend
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.legendCtrl);
+            this.Controls.Add(this.toolStrip1);
+            this.Name = "LiveMapEditorLegend";
+            this.Size = new System.Drawing.Size(275, 381);
+            this.toolStrip1.ResumeLayout(false);
+            this.toolStrip1.PerformLayout();
+            this.ctxLegend.ResumeLayout(false);
+            this.grpContextMenu.ResumeLayout(false);
+            this.layerContextMenu.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+        private System.Windows.Forms.ToolStripButton btnAddGroup;
+        private System.Windows.Forms.ToolStripButton btnAddLayer;
+        private Maestro.MapViewer.Legend legendCtrl;
+        private System.Windows.Forms.ToolStrip toolStrip1;
+        private System.Windows.Forms.ContextMenuStrip ctxLegend;
+        private System.Windows.Forms.ToolStripMenuItem addNewGroupToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem addNewLayerToolStripMenuItem;
+        private System.Windows.Forms.ContextMenuStrip grpContextMenu;
+        private System.Windows.Forms.ToolStripMenuItem addLayerToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem removeThisGroupToolStripMenuItem;
+        private System.Windows.Forms.ContextMenuStrip layerContextMenu;
+        private System.Windows.Forms.ToolStripMenuItem removeThisLayerToolStripMenuItem;
+    }
+}

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,191 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+
+using Maestro.MapViewer;
+using OSGeo.MapGuide.MaestroAPI.Services;
+using Maestro.Editors.Generic;
+using OSGeo.MapGuide.MaestroAPI;
+using OSGeo.MapGuide.MaestroAPI.Mapping;
+using OSGeo.MapGuide.MaestroAPI.Resource;
+using OSGeo.MapGuide.ObjectModels.LayerDefinition;
+
+namespace Maestro.Editors.MapDefinition
+{
+    /// <summary>
+    /// Description of LiveMapEditorLegend.
+    /// </summary>
+    public partial class LiveMapEditorLegend : UserControl
+    {
+        public LiveMapEditorLegend()
+        {
+            InitializeComponent();
+            legendCtrl.NodeSelected += new NodeEventHandler(OnInnerNodeSelected);
+        }
+        
+        private void OnInnerNodeSelected(object sender, TreeNode e)
+        {
+            var h = this.NodeSelected;
+            if (h != null)
+                h(this, e);
+        }
+
+        public event NodeEventHandler NodeDeleted;
+
+        public event NodeEventHandler NodeSelected;
+        
+        public IMapViewer Viewer
+        {
+            get { return legendCtrl.Viewer; }
+            set { legendCtrl.Viewer = value; }
+        }
+
+        private void btnAddGroup_Click(object sender, EventArgs e)
+        {
+            var map = this.Viewer.GetMap();
+            if (map != null)
+            {
+                var diag = new Live.NewGroupDialog(map);
+                if (diag.ShowDialog() == DialogResult.OK)
+                {
+                    var mapSvc = (IMappingService)map.CurrentConnection.GetService((int)ServiceType.Mapping);
+                    var group = mapSvc.CreateMapGroup(map, diag.GroupName);
+                    group.LegendLabel = diag.GroupLabel;
+                    group.Visible = true;
+                    group.ShowInLegend = true;
+                    map.Groups.Add(group);
+                    legendCtrl.Viewer.RefreshMap();
+                }
+            }
+        }
+
+        private static string GenerateUniqueName(string prefix, RuntimeMapLayerCollection layers)
+        {
+            int counter = 0;
+            string name = prefix;
+            while (layers[name] != null)
+            {
+                counter++;
+                name = prefix + counter;
+            }
+            return name;
+        }
+
+        private void btnAddLayer_Click(object sender, EventArgs e)
+        {
+            var map = this.Viewer.GetMap();
+            if (map != null)
+            {
+                using (var picker = new ResourcePicker(map.CurrentConnection.ResourceService, ResourceTypes.LayerDefinition, ResourcePickerMode.OpenResource))
+                {
+                    if (picker.ShowDialog() == DialogResult.OK)
+                    {
+                        var mapSvc = (IMappingService)map.CurrentConnection.GetService((int)ServiceType.Mapping);
+                        var layer = mapSvc.CreateMapLayer(map, ((ILayerDefinition)map.CurrentConnection.ResourceService.GetResource(picker.ResourceID)));
+                        layer.Name = GenerateUniqueName(ResourceIdentifier.GetName(picker.ResourceID), map.Layers);
+                        layer.LegendLabel = ResourceIdentifier.GetName(picker.ResourceID);
+                        layer.Visible = true;
+                        layer.ShowInLegend = true;
+                        map.Layers.Insert(0, layer);
+                        legendCtrl.Viewer.RefreshMap();
+                    }
+                }
+            }
+        }
+
+        private void addLayerToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            var map = this.Viewer.GetMap();
+            if (map != null)
+            {
+                var node = legendCtrl.SelectedNode;
+                if (node != null)
+                {
+                    var grp = node.Tag as Legend.GroupNodeMetadata;
+                    if (grp != null)
+                    {
+                        using (var picker = new ResourcePicker(map.CurrentConnection.ResourceService, ResourceTypes.LayerDefinition, ResourcePickerMode.OpenResource))
+                        {
+                            if (picker.ShowDialog() == DialogResult.OK)
+                            {
+                                var mapSvc = (IMappingService)map.CurrentConnection.GetService((int)ServiceType.Mapping);
+                                var layer = mapSvc.CreateMapLayer(map, ((ILayerDefinition)map.CurrentConnection.ResourceService.GetResource(picker.ResourceID)));
+                                layer.Name = GenerateUniqueName(ResourceIdentifier.GetName(picker.ResourceID), map.Layers);
+                                layer.LegendLabel = ResourceIdentifier.GetName(picker.ResourceID);
+                                layer.Group = grp.Name;
+                                layer.Visible = true;
+                                layer.ShowInLegend = true;
+                                map.Layers.Insert(0, layer);
+                                legendCtrl.Viewer.RefreshMap();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        private void removeThisGroupToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            var map = this.Viewer.GetMap();
+            if (map != null)
+            {
+                var node = legendCtrl.SelectedNode;
+                if (node != null)
+                {
+                    var grp = node.Tag as Legend.GroupNodeMetadata;
+                    if (grp != null)
+                    {
+                        var group = map.Groups[grp.Group];
+                        if (group != null)
+                        {
+                            map.Groups.Remove(group);
+                            legendCtrl.Viewer.RefreshMap();
+                        }
+                    }
+                }
+            }
+        }
+
+        private void removeThisLayerToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            var map = this.Viewer.GetMap();
+            if (map != null)
+            {
+                var node = legendCtrl.SelectedNode;
+                if (node != null)
+                {
+                    var lyr = node.Tag as Legend.LayerNodeMetadata;
+                    if (lyr != null && !lyr.IsThemeRule)
+                    {
+                        var layer = map.Layers[lyr.Name];
+                        if (layer != null)
+                        {
+                            map.Layers.Remove(layer);
+                            legendCtrl.Viewer.RefreshMap();
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.resx	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.Editors/MapDefinition/LiveMapEditorLegend.resx	2012-06-05 14:52:05 UTC (rev 6734)
@@ -0,0 +1,132 @@
+<?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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="ctxLegend.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>122, 17</value>
+  </metadata>
+  <metadata name="grpContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>229, 17</value>
+  </metadata>
+  <metadata name="layerContextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>373, 17</value>
+  </metadata>
+</root>
\ No newline at end of file

Modified: trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -53,6 +53,7 @@
             this.trvLegend.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.trvLegend_DrawNode);
             this.trvLegend.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.trvLegend_AfterSelect);
             this.trvLegend.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.trvLegend_NodeMouseClick);
+            this.trvLegend.MouseDown += new System.Windows.Forms.MouseEventHandler(this.trvLegend_MouseDown);
             // 
             // imgLegend
             // 

Modified: trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -34,7 +34,7 @@
 
 namespace Maestro.MapViewer
 {
-    public delegate void NodeSelectionEventHandler(object sender, TreeNode node);
+    public delegate void NodeEventHandler(object sender, TreeNode node);
 
     public partial class Legend : UserControl
     {
@@ -272,6 +272,8 @@
             }
         }
 
+        public TreeNode SelectedNode { get { return trvLegend.SelectedNode; } }
+
         private static void ClearNodes(TreeNodeCollection nodes)
         {
             foreach (TreeNode node in nodes)
@@ -1010,7 +1012,7 @@
             set { trvLegend.ShowNodeToolTips = value; }
         }
 
-        public event NodeSelectionEventHandler NodeSelected;
+        public event NodeEventHandler NodeSelected;
 
         private void trvLegend_AfterSelect(object sender, TreeViewEventArgs e)
         {
@@ -1018,5 +1020,15 @@
             if (h != null)
                 h(this, e.Node);
         }
+
+        public bool SelectOnRightClick { get; set; }
+
+        private void trvLegend_MouseDown(object sender, MouseEventArgs e)
+        {
+            if (e.Button == MouseButtons.Right && this.SelectOnRightClick)
+            {
+                trvLegend.SelectedNode = trvLegend.GetNodeAt(e.X, e.Y);
+            }
+        }
     }
 }

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs	2012-06-05 12:12:43 UTC (rev 6733)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs	2012-06-05 14:52:05 UTC (rev 6734)
@@ -19,8 +19,11 @@
 #endregion
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Text;
+
 using OSGeo.MapGuide.MaestroAPI.Exceptions;
+using System.Collections;
 
 namespace OSGeo.MapGuide.MaestroAPI.Mapping
 {
@@ -29,7 +32,7 @@
     /// </summary>
     /// <typeparam name="TKey">The type of the key.</typeparam>
     /// <typeparam name="TVal">The type of the value.</typeparam>
-    public abstract class KeyValueCollection<TKey, TVal> : IList<TVal> where TVal : class
+    public abstract class KeyValueCollection<TKey, TVal> : IList<TVal>, IList where TVal : class
     {
         /// <summary>
         /// The internal list of value
@@ -96,6 +99,7 @@
             _values.Insert(index, item);
             _valuesByKey.Add(key, item);
             OnItemAdded(item);
+            OnCollectionChanged();
         }
 
         /// <summary>
@@ -121,6 +125,7 @@
                 _valuesByKey.Remove(key);
 
                 OnItemRemoved(item);
+                OnCollectionChanged();
             }
         }
 
@@ -149,10 +154,38 @@
                 if (_values[index] != null)
                     RemoveAt(index);
                 _values[index] = value;
+                OnCollectionChanged();
             }
         }
 
         /// <summary>
+        /// Sets the new index of the specified object. This object must already be present inside the collection
+        /// </summary>
+        /// <param name="newIndex"></param>
+        /// <param name="item"></param>
+        public void SetNewIndex(int newIndex, TVal item)
+        {
+            int idx = this.IndexOf(item);
+            if (idx >= 0)
+            {
+                bool bSuccess = false;
+                try
+                {
+                    bSuppressCollectionChanged = true;
+                    this.RemoveAt(idx);
+                    this.Insert(newIndex, item);
+                    bSuccess = true;
+                }
+                finally
+                {
+                    bSuppressCollectionChanged = false;
+                    if (bSuccess)
+                        OnCollectionChanged();
+                }
+            }
+        }
+
+        /// <summary>
         /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
         /// </summary>
         /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
@@ -169,6 +202,7 @@
             _values.Add(item);
             _valuesByKey.Add(key, item);
             OnItemAdded(item);
+            OnCollectionChanged();
         }
 
         /// <summary>
@@ -179,24 +213,35 @@
         ///   </exception>
         public virtual void Clear()
         {
-            //We don't call Clear() directly because we need to propagate removal of each
-            //item back to the map
-            var items = new List<TVal>(this);
-            foreach (var item in items)
+            bool hasRemovedAnItem = false;
+            try 
             {
-                Remove(item);
+                bSuppressCollectionChanged = true;
+                //We don't call Clear() directly because we need to propagate removal of each
+                //item back to the map
+                var items = new List<TVal>(this);
+                foreach (var item in items)
+                {
+                    Remove(item);
+                    hasRemovedAnItem = true;
+                }
+                //This shouldn't happen
+                if (_values.Count > 0)
+                {
+                    System.Diagnostics.Trace.TraceWarning("Expected empty values collection!");
+                    _values.Clear();
+                }
+                if (_valuesByKey.Count > 0)
+                {
+                    System.Diagnostics.Trace.TraceWarning("Expected empty values collection!");
+                    _valuesByKey.Clear();
+                }
             }
-            //This shouldn't happen
-            if (_values.Count > 0)
-            {
-                System.Diagnostics.Trace.TraceWarning("Expected empty values collection!");
-                _values.Clear();
+            finally {
+                bSuppressCollectionChanged = false;
+                if (hasRemovedAnItem)
+                    OnCollectionChanged();
             }
-            if (_valuesByKey.Count > 0)
-            {
-                System.Diagnostics.Trace.TraceWarning("Expected empty values collection!");
-                _valuesByKey.Clear();
-            }
         }
 
         /// <summary>
@@ -279,6 +324,7 @@
                 _valuesByKey.Remove(key);
 
                 OnItemRemoved(item);
+                OnCollectionChanged();
                 return ret;
             }
             return ret;
@@ -323,8 +369,32 @@
         public TVal this[TKey key]
         {
             get { return _valuesByKey.ContainsKey(key) ? _valuesByKey[key] : null; }
-            set { _valuesByKey[key] = value; }
+            set 
+            { 
+                _valuesByKey[key] = value;
+                OnCollectionChanged();
+            }
         }
+        
+        /// <summary>
+        /// Raised when the collection has been modified
+        /// </summary>
+        public event EventHandler CollectionChanged;
+        
+        private bool bSuppressCollectionChanged = false;
+        
+        /// <summary>
+        /// Raises the <see cref="CollectionChanged" /> event
+        /// </summary>
+        protected virtual void OnCollectionChanged()
+        {
+            if (bSuppressCollectionChanged)
+                return;
+        
+            var h = this.CollectionChanged;
+            if (h != null)
+                h(this, EventArgs.Empty);
+        }
 
         /// <summary>
         /// Called before an item is added
@@ -357,6 +427,86 @@
         /// <param name="value">The value.</param>
         /// <returns></returns>
         protected abstract TKey SelectKey(TVal value);
+
+        int IList.Add(object value)
+        {
+            this.Add((TVal)value);
+            return this.Count - 1;
+        }
+
+        void IList.Clear()
+        {
+            this.Clear();
+        }
+
+        bool IList.Contains(object value)
+        {
+            return this.Contains((TVal)value);
+        }
+
+        int IList.IndexOf(object value)
+        {
+            return this.IndexOf((TVal)value);
+        }
+
+        void IList.Insert(int index, object value)
+        {
+            this.Insert(index, (TVal)value);
+        }
+
+        bool IList.IsFixedSize
+        {
+            get { return false; }
+        }
+
+        bool IList.IsReadOnly
+        {
+            get { return false; }
+        }
+
+        void IList.Remove(object value)
+        {
+            this.Remove((TVal)value);
+        }
+
+        void IList.RemoveAt(int index)
+        {
+            this.RemoveAt(index);
+        }
+
+        object IList.this[int index]
+        {
+            get
+            {
+                return this[index];
+            }
+            set
+            {
+                this[index] = (TVal)value;
+            }
+        }
+
+        void ICollection.CopyTo(Array array, int index)
+        {
+            this.CopyTo((TVal[])array, index);
+        }
+
+        int ICollection.Count
+        {
+            get { return this.Count; }
+        }
+
+        bool ICollection.IsSynchronized
+        {
+            get { return false; }
+        }
+
+        private readonly object _syncRoot = new object();
+
+        object ICollection.SyncRoot
+        {
+            get { return _syncRoot; }
+        }
     }
 
     /// <summary>



More information about the mapguide-commits mailing list