[mapguide-commits] r6607 - in branches/2.4/MgDev/Desktop: MapViewer MapViewer/Properties MapViewerTest

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Thu May 3 10:23:12 EDT 2012


Author: jng
Date: 2012-05-03 07:23:12 -0700 (Thu, 03 May 2012)
New Revision: 6607

Added:
   branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.resx
   branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgControlImpl.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgInvokeComponent.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.resx
   branches/2.4/MgDev/Desktop/MapViewer/MgMeasureControl.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.resx
Removed:
   branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.resx
   branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.resx
   branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.resx
Modified:
   branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj
   branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.cs
   branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.cs
   branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.resx
   branches/2.4/MgDev/Desktop/MapViewerTest/Form1.Designer.cs
   branches/2.4/MgDev/Desktop/MapViewerTest/Form1.cs
   branches/2.4/MgDev/Desktop/MapViewerTest/Form1.resx
   branches/2.4/MgDev/Desktop/MapViewerTest/Program.cs
Log:
Refactor the new mg-desktop controls to be component based. The purpose of this change is to allow for a drag and drop design paradigm that WinForms is conductive to and to allow for mostly declarative assembly of the map viewer user interface (instead of having to write code to do it). 

This has conceptual similarities to commands in the AJAX viewer and widgets in the Fusion viewer and provides a UI design experience that is very similar to the editors of Web Layouts and Flexible Layouts in Studio and Maestro.

With this change, the mg-desktop viewer conceptually lines up with the AJAX/Fusion viewer like so:

 * MgComponent -> AJAX Viewer Command -> Fusion Widget
 * MgInvokeComponentButton/MgInvokeComponentMenuStripItem -> AJAX Viewer menu/toolbar item -> Fusion menu/toolbar item
 * Visual Studio Form Designer -> WebLayout/Fusion editor



Modified: branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MapViewer.csproj	2012-05-03 14:23:12 UTC (rev 6607)
@@ -69,20 +69,32 @@
     <Compile Include="IMapViewerComponent.cs" />
     <Compile Include="IMapStatusBar.cs" />
     <Compile Include="IPropertyPane.cs" />
+    <Compile Include="MgComponent.cs">
+      <SubType>Component</SubType>
+    </Compile>
     <Compile Include="MgBufferControl.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="MgBufferControlImpl.cs">
       <SubType>UserControl</SubType>
     </Compile>
-    <Compile Include="MgBufferControl.Designer.cs">
-      <DependentUpon>MgBufferControl.cs</DependentUpon>
+    <Compile Include="MgBufferControlImpl.Designer.cs">
+      <DependentUpon>MgBufferControlImpl.cs</DependentUpon>
     </Compile>
+    <Compile Include="MgControlImpl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
     <Compile Include="MgDefaultToolbar.cs">
       <SubType>Component</SubType>
     </Compile>
-    <Compile Include="MgLineMeasureControl.cs">
+    <Compile Include="MgInvokeComponent.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="MgLineMeasureControlImpl.cs">
       <SubType>UserControl</SubType>
     </Compile>
-    <Compile Include="MgLineMeasureControl.Designer.cs">
-      <DependentUpon>MgLineMeasureControl.cs</DependentUpon>
+    <Compile Include="MgLineMeasureControlImpl.Designer.cs">
+      <DependentUpon>MgLineMeasureControlImpl.cs</DependentUpon>
     </Compile>
     <Compile Include="MgMapViewer.cs">
       <SubType>Component</SubType>
@@ -95,6 +107,9 @@
       <DependentUpon>MgLegend.cs</DependentUpon>
     </Compile>
     <Compile Include="MgMapViewerProvider.cs" />
+    <Compile Include="MgMeasureControl.cs">
+      <SubType>Component</SubType>
+    </Compile>
     <Compile Include="MgPropertyPane.cs">
       <SubType>UserControl</SubType>
     </Compile>
@@ -102,10 +117,13 @@
       <DependentUpon>MgPropertyPane.cs</DependentUpon>
     </Compile>
     <Compile Include="MgQueryControl.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="MgQueryControlImpl.cs">
       <SubType>UserControl</SubType>
     </Compile>
-    <Compile Include="MgQueryControl.Designer.cs">
-      <DependentUpon>MgQueryControl.cs</DependentUpon>
+    <Compile Include="MgQueryControlImpl.Designer.cs">
+      <DependentUpon>MgQueryControlImpl.cs</DependentUpon>
     </Compile>
     <Compile Include="MgQueryResultsDialog.cs">
       <SubType>Form</SubType>
@@ -127,20 +145,20 @@
       <Generator>ResXFileCodeGenerator</Generator>
       <LastGenOutput>Debug.Designer.cs</LastGenOutput>
     </EmbeddedResource>
-    <EmbeddedResource Include="MgBufferControl.resx">
-      <DependentUpon>MgBufferControl.cs</DependentUpon>
+    <EmbeddedResource Include="MgBufferControlImpl.resx">
+      <DependentUpon>MgBufferControlImpl.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="MgLegend.resx">
       <DependentUpon>MgLegend.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="MgLineMeasureControl.resx">
-      <DependentUpon>MgLineMeasureControl.cs</DependentUpon>
+    <EmbeddedResource Include="MgLineMeasureControlImpl.resx">
+      <DependentUpon>MgLineMeasureControlImpl.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="MgPropertyPane.resx">
       <DependentUpon>MgPropertyPane.cs</DependentUpon>
     </EmbeddedResource>
-    <EmbeddedResource Include="MgQueryControl.resx">
-      <DependentUpon>MgQueryControl.cs</DependentUpon>
+    <EmbeddedResource Include="MgQueryControlImpl.resx">
+      <DependentUpon>MgQueryControlImpl.cs</DependentUpon>
     </EmbeddedResource>
     <EmbeddedResource Include="MgQueryResultsDialog.resx">
       <DependentUpon>MgQueryResultsDialog.cs</DependentUpon>

Deleted: branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.Designer.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,457 +0,0 @@
-namespace OSGeo.MapGuide.Viewer
-{
-    partial class MgBufferControl
-    {
-        /// <summary> 
-        /// Required designer variable.
-        /// </summary>
-        private System.ComponentModel.IContainer components = null;
-
-        /// <summary> 
-        /// Clean up any resources being used.
-        /// </summary>
-        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Component Designer generated code
-
-        /// <summary> 
-        /// Required method for Designer support - do not modify 
-        /// the contents of this method with the code editor.
-        /// </summary>
-        private void InitializeComponent()
-        {
-            this.groupBox1 = new System.Windows.Forms.GroupBox();
-            this.lstLayers = new System.Windows.Forms.ListBox();
-            this.label2 = new System.Windows.Forms.Label();
-            this.cmbUnits = new System.Windows.Forms.ComboBox();
-            this.numBufferDistance = new System.Windows.Forms.NumericUpDown();
-            this.label1 = new System.Windows.Forms.Label();
-            this.lblSelectFeatures = new System.Windows.Forms.Label();
-            this.groupBox2 = new System.Windows.Forms.GroupBox();
-            this.btnFillBackColor = new System.Windows.Forms.Button();
-            this.pnlFillBackColor = new System.Windows.Forms.Panel();
-            this.label10 = new System.Windows.Forms.Label();
-            this.numFillTransparency = new System.Windows.Forms.NumericUpDown();
-            this.label5 = new System.Windows.Forms.Label();
-            this.btnFillColor = new System.Windows.Forms.Button();
-            this.pnlFillColor = new System.Windows.Forms.Panel();
-            this.label4 = new System.Windows.Forms.Label();
-            this.cmbFillPattern = new System.Windows.Forms.ComboBox();
-            this.label3 = new System.Windows.Forms.Label();
-            this.groupBox3 = new System.Windows.Forms.GroupBox();
-            this.numLineThickness = new System.Windows.Forms.NumericUpDown();
-            this.cmbBorderPattern = new System.Windows.Forms.ComboBox();
-            this.label6 = new System.Windows.Forms.Label();
-            this.label8 = new System.Windows.Forms.Label();
-            this.btnBorderColor = new System.Windows.Forms.Button();
-            this.label7 = new System.Windows.Forms.Label();
-            this.pnlBorderColor = new System.Windows.Forms.Panel();
-            this.btnCreate = new System.Windows.Forms.Button();
-            this.groupBox4 = new System.Windows.Forms.GroupBox();
-            this.chkMergeBuffers = new System.Windows.Forms.CheckBox();
-            this.txtBufferLayer = new System.Windows.Forms.TextBox();
-            this.label9 = new System.Windows.Forms.Label();
-            this.colorPicker = new System.Windows.Forms.ColorDialog();
-            this.groupBox1.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numBufferDistance)).BeginInit();
-            this.groupBox2.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numFillTransparency)).BeginInit();
-            this.groupBox3.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numLineThickness)).BeginInit();
-            this.groupBox4.SuspendLayout();
-            this.SuspendLayout();
-            // 
-            // groupBox1
-            // 
-            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.groupBox1.Controls.Add(this.lstLayers);
-            this.groupBox1.Controls.Add(this.label2);
-            this.groupBox1.Controls.Add(this.cmbUnits);
-            this.groupBox1.Controls.Add(this.numBufferDistance);
-            this.groupBox1.Controls.Add(this.label1);
-            this.groupBox1.Controls.Add(this.lblSelectFeatures);
-            this.groupBox1.Location = new System.Drawing.Point(0, 0);
-            this.groupBox1.Name = "groupBox1";
-            this.groupBox1.Size = new System.Drawing.Size(232, 220);
-            this.groupBox1.TabIndex = 0;
-            this.groupBox1.TabStop = false;
-            this.groupBox1.Text = "Buffer Settings";
-            // 
-            // lstLayers
-            // 
-            this.lstLayers.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.lstLayers.FormattingEnabled = true;
-            this.lstLayers.Location = new System.Drawing.Point(9, 126);
-            this.lstLayers.Name = "lstLayers";
-            this.lstLayers.Size = new System.Drawing.Size(206, 82);
-            this.lstLayers.TabIndex = 5;
-            // 
-            // label2
-            // 
-            this.label2.AutoSize = true;
-            this.label2.Location = new System.Drawing.Point(6, 101);
-            this.label2.Name = "label2";
-            this.label2.Size = new System.Drawing.Size(180, 13);
-            this.label2.TabIndex = 4;
-            this.label2.Text = "Includes the following layers in buffer";
-            // 
-            // cmbUnits
-            // 
-            this.cmbUnits.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.cmbUnits.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cmbUnits.FormattingEnabled = true;
-            this.cmbUnits.Location = new System.Drawing.Point(105, 66);
-            this.cmbUnits.Name = "cmbUnits";
-            this.cmbUnits.Size = new System.Drawing.Size(110, 21);
-            this.cmbUnits.TabIndex = 3;
-            // 
-            // numBufferDistance
-            // 
-            this.numBufferDistance.Location = new System.Drawing.Point(9, 67);
-            this.numBufferDistance.Maximum = new decimal(new int[] {
-            100000,
-            0,
-            0,
-            0});
-            this.numBufferDistance.Minimum = new decimal(new int[] {
-            100000,
-            0,
-            0,
-            -2147483648});
-            this.numBufferDistance.Name = "numBufferDistance";
-            this.numBufferDistance.Size = new System.Drawing.Size(92, 20);
-            this.numBufferDistance.TabIndex = 2;
-            // 
-            // label1
-            // 
-            this.label1.AutoSize = true;
-            this.label1.Location = new System.Drawing.Point(6, 50);
-            this.label1.Name = "label1";
-            this.label1.Size = new System.Drawing.Size(126, 13);
-            this.label1.TabIndex = 1;
-            this.label1.Text = "Distance around features";
-            // 
-            // lblSelectFeatures
-            // 
-            this.lblSelectFeatures.BackColor = System.Drawing.Color.White;
-            this.lblSelectFeatures.ForeColor = System.Drawing.Color.Blue;
-            this.lblSelectFeatures.Location = new System.Drawing.Point(6, 16);
-            this.lblSelectFeatures.Name = "lblSelectFeatures";
-            this.lblSelectFeatures.Size = new System.Drawing.Size(209, 23);
-            this.lblSelectFeatures.TabIndex = 0;
-            this.lblSelectFeatures.Text = "Select Features on the Map first";
-            this.lblSelectFeatures.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            // 
-            // groupBox2
-            // 
-            this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.groupBox2.Controls.Add(this.btnFillBackColor);
-            this.groupBox2.Controls.Add(this.pnlFillBackColor);
-            this.groupBox2.Controls.Add(this.label10);
-            this.groupBox2.Controls.Add(this.numFillTransparency);
-            this.groupBox2.Controls.Add(this.label5);
-            this.groupBox2.Controls.Add(this.btnFillColor);
-            this.groupBox2.Controls.Add(this.pnlFillColor);
-            this.groupBox2.Controls.Add(this.label4);
-            this.groupBox2.Controls.Add(this.cmbFillPattern);
-            this.groupBox2.Controls.Add(this.label3);
-            this.groupBox2.Location = new System.Drawing.Point(0, 220);
-            this.groupBox2.Name = "groupBox2";
-            this.groupBox2.Size = new System.Drawing.Size(232, 144);
-            this.groupBox2.TabIndex = 1;
-            this.groupBox2.TabStop = false;
-            this.groupBox2.Text = "Fill Style";
-            // 
-            // btnFillBackColor
-            // 
-            this.btnFillBackColor.Location = new System.Drawing.Point(183, 102);
-            this.btnFillBackColor.Name = "btnFillBackColor";
-            this.btnFillBackColor.Size = new System.Drawing.Size(32, 23);
-            this.btnFillBackColor.TabIndex = 9;
-            this.btnFillBackColor.Text = "...";
-            this.btnFillBackColor.UseVisualStyleBackColor = true;
-            this.btnFillBackColor.Click += new System.EventHandler(this.btnFillBackColor_Click);
-            // 
-            // pnlFillBackColor
-            // 
-            this.pnlFillBackColor.Location = new System.Drawing.Point(95, 103);
-            this.pnlFillBackColor.Name = "pnlFillBackColor";
-            this.pnlFillBackColor.Size = new System.Drawing.Size(82, 22);
-            this.pnlFillBackColor.TabIndex = 8;
-            // 
-            // label10
-            // 
-            this.label10.AutoSize = true;
-            this.label10.Location = new System.Drawing.Point(30, 107);
-            this.label10.Name = "label10";
-            this.label10.Size = new System.Drawing.Size(59, 13);
-            this.label10.TabIndex = 7;
-            this.label10.Text = "Back Color";
-            // 
-            // numFillTransparency
-            // 
-            this.numFillTransparency.Location = new System.Drawing.Point(95, 77);
-            this.numFillTransparency.Name = "numFillTransparency";
-            this.numFillTransparency.Size = new System.Drawing.Size(120, 20);
-            this.numFillTransparency.TabIndex = 6;
-            // 
-            // label5
-            // 
-            this.label5.AutoSize = true;
-            this.label5.Location = new System.Drawing.Point(17, 79);
-            this.label5.Name = "label5";
-            this.label5.Size = new System.Drawing.Size(72, 13);
-            this.label5.TabIndex = 5;
-            this.label5.Text = "Transparency";
-            // 
-            // btnFillColor
-            // 
-            this.btnFillColor.Location = new System.Drawing.Point(183, 48);
-            this.btnFillColor.Name = "btnFillColor";
-            this.btnFillColor.Size = new System.Drawing.Size(32, 23);
-            this.btnFillColor.TabIndex = 4;
-            this.btnFillColor.Text = "...";
-            this.btnFillColor.UseVisualStyleBackColor = true;
-            this.btnFillColor.Click += new System.EventHandler(this.btnFillColor_Click);
-            // 
-            // pnlFillColor
-            // 
-            this.pnlFillColor.Location = new System.Drawing.Point(95, 49);
-            this.pnlFillColor.Name = "pnlFillColor";
-            this.pnlFillColor.Size = new System.Drawing.Size(82, 22);
-            this.pnlFillColor.TabIndex = 3;
-            // 
-            // label4
-            // 
-            this.label4.AutoSize = true;
-            this.label4.Location = new System.Drawing.Point(34, 53);
-            this.label4.Name = "label4";
-            this.label4.Size = new System.Drawing.Size(55, 13);
-            this.label4.TabIndex = 2;
-            this.label4.Text = "Fore Color";
-            // 
-            // cmbFillPattern
-            // 
-            this.cmbFillPattern.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cmbFillPattern.FormattingEnabled = true;
-            this.cmbFillPattern.Location = new System.Drawing.Point(95, 23);
-            this.cmbFillPattern.Name = "cmbFillPattern";
-            this.cmbFillPattern.Size = new System.Drawing.Size(120, 21);
-            this.cmbFillPattern.TabIndex = 1;
-            // 
-            // label3
-            // 
-            this.label3.AutoSize = true;
-            this.label3.Location = new System.Drawing.Point(48, 26);
-            this.label3.Name = "label3";
-            this.label3.Size = new System.Drawing.Size(41, 13);
-            this.label3.TabIndex = 0;
-            this.label3.Text = "Pattern";
-            // 
-            // groupBox3
-            // 
-            this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.groupBox3.Controls.Add(this.numLineThickness);
-            this.groupBox3.Controls.Add(this.cmbBorderPattern);
-            this.groupBox3.Controls.Add(this.label6);
-            this.groupBox3.Controls.Add(this.label8);
-            this.groupBox3.Controls.Add(this.btnBorderColor);
-            this.groupBox3.Controls.Add(this.label7);
-            this.groupBox3.Controls.Add(this.pnlBorderColor);
-            this.groupBox3.Location = new System.Drawing.Point(0, 364);
-            this.groupBox3.Name = "groupBox3";
-            this.groupBox3.Size = new System.Drawing.Size(232, 100);
-            this.groupBox3.TabIndex = 2;
-            this.groupBox3.TabStop = false;
-            this.groupBox3.Text = "Border Style";
-            // 
-            // numLineThickness
-            // 
-            this.numLineThickness.Location = new System.Drawing.Point(95, 73);
-            this.numLineThickness.Name = "numLineThickness";
-            this.numLineThickness.Size = new System.Drawing.Size(120, 20);
-            this.numLineThickness.TabIndex = 13;
-            // 
-            // cmbBorderPattern
-            // 
-            this.cmbBorderPattern.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cmbBorderPattern.FormattingEnabled = true;
-            this.cmbBorderPattern.Location = new System.Drawing.Point(95, 19);
-            this.cmbBorderPattern.Name = "cmbBorderPattern";
-            this.cmbBorderPattern.Size = new System.Drawing.Size(120, 21);
-            this.cmbBorderPattern.TabIndex = 8;
-            // 
-            // label6
-            // 
-            this.label6.AutoSize = true;
-            this.label6.Location = new System.Drawing.Point(17, 75);
-            this.label6.Name = "label6";
-            this.label6.Size = new System.Drawing.Size(72, 13);
-            this.label6.TabIndex = 12;
-            this.label6.Text = "Transparency";
-            // 
-            // label8
-            // 
-            this.label8.AutoSize = true;
-            this.label8.Location = new System.Drawing.Point(48, 22);
-            this.label8.Name = "label8";
-            this.label8.Size = new System.Drawing.Size(41, 13);
-            this.label8.TabIndex = 7;
-            this.label8.Text = "Pattern";
-            // 
-            // btnBorderColor
-            // 
-            this.btnBorderColor.Location = new System.Drawing.Point(183, 44);
-            this.btnBorderColor.Name = "btnBorderColor";
-            this.btnBorderColor.Size = new System.Drawing.Size(32, 23);
-            this.btnBorderColor.TabIndex = 11;
-            this.btnBorderColor.Text = "...";
-            this.btnBorderColor.UseVisualStyleBackColor = true;
-            this.btnBorderColor.Click += new System.EventHandler(this.btnBorderColor_Click);
-            // 
-            // label7
-            // 
-            this.label7.AutoSize = true;
-            this.label7.Location = new System.Drawing.Point(58, 49);
-            this.label7.Name = "label7";
-            this.label7.Size = new System.Drawing.Size(31, 13);
-            this.label7.TabIndex = 9;
-            this.label7.Text = "Color";
-            // 
-            // pnlBorderColor
-            // 
-            this.pnlBorderColor.Location = new System.Drawing.Point(95, 45);
-            this.pnlBorderColor.Name = "pnlBorderColor";
-            this.pnlBorderColor.Size = new System.Drawing.Size(82, 22);
-            this.pnlBorderColor.TabIndex = 10;
-            // 
-            // btnCreate
-            // 
-            this.btnCreate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-            this.btnCreate.Location = new System.Drawing.Point(9, 567);
-            this.btnCreate.Name = "btnCreate";
-            this.btnCreate.Size = new System.Drawing.Size(98, 23);
-            this.btnCreate.TabIndex = 3;
-            this.btnCreate.Text = "Create Buffer";
-            this.btnCreate.UseVisualStyleBackColor = true;
-            this.btnCreate.Click += new System.EventHandler(this.btnCreate_Click);
-            // 
-            // groupBox4
-            // 
-            this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.groupBox4.Controls.Add(this.chkMergeBuffers);
-            this.groupBox4.Controls.Add(this.txtBufferLayer);
-            this.groupBox4.Controls.Add(this.label9);
-            this.groupBox4.Location = new System.Drawing.Point(0, 464);
-            this.groupBox4.Name = "groupBox4";
-            this.groupBox4.Size = new System.Drawing.Size(232, 97);
-            this.groupBox4.TabIndex = 4;
-            this.groupBox4.TabStop = false;
-            this.groupBox4.Text = "Other";
-            // 
-            // chkMergeBuffers
-            // 
-            this.chkMergeBuffers.AutoSize = true;
-            this.chkMergeBuffers.Checked = true;
-            this.chkMergeBuffers.CheckState = System.Windows.Forms.CheckState.Checked;
-            this.chkMergeBuffers.Location = new System.Drawing.Point(12, 69);
-            this.chkMergeBuffers.Name = "chkMergeBuffers";
-            this.chkMergeBuffers.Size = new System.Drawing.Size(117, 17);
-            this.chkMergeBuffers.TabIndex = 2;
-            this.chkMergeBuffers.Text = "Merge Buffer Areas";
-            this.chkMergeBuffers.UseVisualStyleBackColor = true;
-            // 
-            // txtBufferLayer
-            // 
-            this.txtBufferLayer.Location = new System.Drawing.Point(12, 43);
-            this.txtBufferLayer.Name = "txtBufferLayer";
-            this.txtBufferLayer.Size = new System.Drawing.Size(203, 20);
-            this.txtBufferLayer.TabIndex = 1;
-            // 
-            // label9
-            // 
-            this.label9.AutoSize = true;
-            this.label9.Location = new System.Drawing.Point(9, 26);
-            this.label9.Name = "label9";
-            this.label9.Size = new System.Drawing.Size(98, 13);
-            this.label9.TabIndex = 0;
-            this.label9.Text = "Buffer Layer Name:";
-            // 
-            // MgBufferControl
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.Controls.Add(this.groupBox4);
-            this.Controls.Add(this.btnCreate);
-            this.Controls.Add(this.groupBox3);
-            this.Controls.Add(this.groupBox2);
-            this.Controls.Add(this.groupBox1);
-            this.Name = "MgBufferControl";
-            this.Size = new System.Drawing.Size(232, 601);
-            this.groupBox1.ResumeLayout(false);
-            this.groupBox1.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numBufferDistance)).EndInit();
-            this.groupBox2.ResumeLayout(false);
-            this.groupBox2.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numFillTransparency)).EndInit();
-            this.groupBox3.ResumeLayout(false);
-            this.groupBox3.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numLineThickness)).EndInit();
-            this.groupBox4.ResumeLayout(false);
-            this.groupBox4.PerformLayout();
-            this.ResumeLayout(false);
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.GroupBox groupBox1;
-        private System.Windows.Forms.Label lblSelectFeatures;
-        private System.Windows.Forms.ListBox lstLayers;
-        private System.Windows.Forms.Label label2;
-        private System.Windows.Forms.ComboBox cmbUnits;
-        private System.Windows.Forms.NumericUpDown numBufferDistance;
-        private System.Windows.Forms.Label label1;
-        private System.Windows.Forms.GroupBox groupBox2;
-        private System.Windows.Forms.NumericUpDown numFillTransparency;
-        private System.Windows.Forms.Label label5;
-        private System.Windows.Forms.Button btnFillColor;
-        private System.Windows.Forms.Panel pnlFillColor;
-        private System.Windows.Forms.Label label4;
-        private System.Windows.Forms.ComboBox cmbFillPattern;
-        private System.Windows.Forms.Label label3;
-        private System.Windows.Forms.GroupBox groupBox3;
-        private System.Windows.Forms.NumericUpDown numLineThickness;
-        private System.Windows.Forms.ComboBox cmbBorderPattern;
-        private System.Windows.Forms.Label label6;
-        private System.Windows.Forms.Label label8;
-        private System.Windows.Forms.Button btnBorderColor;
-        private System.Windows.Forms.Label label7;
-        private System.Windows.Forms.Panel pnlBorderColor;
-        private System.Windows.Forms.Button btnCreate;
-        private System.Windows.Forms.GroupBox groupBox4;
-        private System.Windows.Forms.CheckBox chkMergeBuffers;
-        private System.Windows.Forms.TextBox txtBufferLayer;
-        private System.Windows.Forms.Label label9;
-        private System.Windows.Forms.ColorDialog colorPicker;
-        private System.Windows.Forms.Button btnFillBackColor;
-        private System.Windows.Forms.Panel pnlFillBackColor;
-        private System.Windows.Forms.Label label10;
-    }
-}

Modified: branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,491 +1,35 @@
 using System;
 using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
 using System.Text;
-using System.Windows.Forms;
-using System.Globalization;
+using System.ComponentModel;
 
 namespace OSGeo.MapGuide.Viewer
 {
-    public partial class MgBufferControl : UserControl
+    /// <summary>
+    /// A generic component that generates buffers from selected features on the map
+    /// </summary>
+    [ToolboxItem(true)]
+    public class MgBufferControl : MgViewerComponent
     {
-        private IMapViewer _viewer;
-        private MgResourceService _resSvc;
-        private MgFeatureService _featSvc;
-        private string _sessionId;
-
-        public MgBufferControl(IMapViewer viewer)
+        public MgBufferControl()
         {
-            InitializeComponent();
-            _viewer = viewer;
-            _sessionId = Guid.NewGuid().ToString();
-            var provider = viewer.GetProvider();
-            _resSvc = (MgResourceService)provider.CreateService(MgServiceType.ResourceService);
-            _featSvc = (MgFeatureService)provider.CreateService(MgServiceType.FeatureService);
-
-            cmbUnits.DataSource = Enum.GetValues(typeof(MeasurementUnit));
-            cmbUnits.SelectedItem = MeasurementUnit.Kilometers;
-            cmbBorderPattern.DataSource = Enum.GetValues(typeof(StockPattern));
-            cmbFillPattern.DataSource = Enum.GetValues(typeof(StockPattern));
-
-            cmbBorderPattern.SelectedItem = StockPattern.Solid;
-            cmbFillPattern.SelectedItem = StockPattern.Solid;
-
-            pnlFillColor.BackColor = Color.Red;
-            pnlBorderColor.BackColor = Color.Black;
-
-            numBufferDistance.Value = 1;
-            numFillTransparency.Value = 50;
-            numLineThickness.Value = 1;
-
-            _viewer.SelectionChanged += new EventHandler(OnViewerSelectedChanged);
+            this.Icon = Properties.Resources.buffer;
+            this.Label = Properties.Resources.TitleBuffer;
         }
 
-        void OnViewerSelectedChanged(object sender, EventArgs e)
+        protected override MgControlImpl CreateControlImpl()
         {
-            lstLayers.Items.Clear();
-            var sel = _viewer.GetSelection();
-            var layers = sel.GetLayers();
-            if (layers != null)
-            {
-                for (var i = 0; i < layers.GetCount(); i++)
-                {
-                    var layer = layers.GetItem(i);
-                    var name = layer.GetName();
-
-                    lstLayers.Items.Add(name);
-                }
-            }
-
-            lblSelectFeatures.Visible = (lstLayers.Items.Count == 0);
+            return new MgBufferControlImpl(this.Viewer);
         }
 
-        private void btnFillColor_Click(object sender, EventArgs e)
+        protected override void SubscribeViewerEvents(IMapViewer viewer)
         {
-            if (colorPicker.ShowDialog() == DialogResult.OK)
-            {
-                pnlFillColor.BackColor = colorPicker.Color;
-            }
+            base.SubscribeViewerEvents(viewer);
         }
 
-        private void btnBorderColor_Click(object sender, EventArgs e)
+        protected override void UnsubscribeViewerEvents(IMapViewer viewer)
         {
-            if (colorPicker.ShowDialog() == DialogResult.OK)
-            {
-                pnlBorderColor.BackColor = colorPicker.Color;
-            }
+            base.UnsubscribeViewerEvents(viewer);
         }
-
-        private void btnFillBackColor_Click(object sender, EventArgs e)
-        {
-            if (colorPicker.ShowDialog() == DialogResult.OK)
-            {
-                pnlFillBackColor.BackColor = colorPicker.Color;
-            }
-        }
-
-        private void btnCreate_Click(object sender, EventArgs e)
-        {
-            var layerName = txtBufferLayer.Text.Trim();
-            if (string.IsNullOrEmpty(layerName))
-            {
-                MessageBox.Show("Please enter a name for this layer");
-                return;
-            }
-
-            if (lstLayers.SelectedItems.Count == 0)
-            {
-                MessageBox.Show("Please include one or more layers to create a buffer from");
-                return;
-            }
-
-            var map = _viewer.GetMap();
-            var layers = map.GetLayers();
-            var provider = _viewer.GetProvider();
-
-            //From here, it's the same logic as buffer.aspx in .net MapGuide AJAX viewer
-            MgResourceIdentifier fsId = new MgResourceIdentifier("Session:" + _sessionId + "//" + txtBufferLayer.Text + "_Buffer.FeatureSource");
-            MgResourceIdentifier ldfId = new MgResourceIdentifier("Session:" + _sessionId + "//" + txtBufferLayer.Text + "_Buffer.LayerDefinition");
-
-            MgLayerBase layer = FindLayer(layers, txtBufferLayer.Text);
-            string[] layerNames = GetLayerNames();
-
-            double distance = Convert.ToDouble(numBufferDistance.Value);
-            MeasurementUnit bUnits = (MeasurementUnit)cmbUnits.SelectedItem;
-            switch (bUnits)
-            {
-                case MeasurementUnit.Feet:
-                    distance *= 0.30480;
-                    break;
-                case MeasurementUnit.Kilometers:
-                    distance *= 1000;
-                    break;
-                case MeasurementUnit.Miles:
-                    distance *= 1609.35;
-                    break;
-            }
-
-            String srsDefMap = GetMapSrs(map);
-            MgCoordinateSystem srsMap = provider.GetMapCoordinateSystem();
-            string mapSrsUnits = "";
-            bool arbitraryMapSrs = (srsMap.GetType() == MgCoordinateSystemType.Arbitrary);
-            if (arbitraryMapSrs)
-                mapSrsUnits = srsMap.GetUnits();
-
-            String xtrans = String.Format("{0:x2}", ((int)(255 * Convert.ToInt32(numFillTransparency.Value) / 100)));
-            var lineColor = ToHtmlColor(pnlBorderColor.BackColor);
-            var foreColor = ToHtmlColor(pnlFillColor.BackColor);
-            var backColor = ToHtmlColor(pnlFillBackColor.BackColor);
-            String layerTempl = string.Format(Properties.Resources.AreaLayerDef,
-                    fsId.ToString(),
-                    "BufferSchema:Buffer",
-                    "GEOM",
-                    cmbFillPattern.SelectedItem,
-                    xtrans + foreColor,
-                    ((0 != 1/*transparent*/) ? "ff" : "00") + backColor,
-                    cmbBorderPattern.SelectedItem,
-                    numLineThickness.Value.ToString(NumberFormatInfo.InvariantInfo),
-                    lineColor
-            );
-            byte[] bytes = Encoding.UTF8.GetBytes(layerTempl);
-            MgByteSource src = new MgByteSource(bytes, bytes.Length);
-            MgByteReader layerDefContent = src.GetReader();
-            _resSvc.SetResource(ldfId, layerDefContent, null);
-
-            bool newBuffer = false;
-            if (layer == null)
-            {
-                newBuffer = true;
-
-                //Targetting a new layer. create a data source for it
-                //
-                MgClassDefinition classDef = new MgClassDefinition();
-
-                classDef.SetName("Buffer");
-                classDef.SetDescription("Feature class for buffer layer");
-                classDef.SetDefaultGeometryPropertyName("GEOM");
-
-                //Set KEY property
-                MgDataPropertyDefinition prop = new MgDataPropertyDefinition("KEY");
-                prop.SetDataType(MgPropertyType.Int32);
-                prop.SetAutoGeneration(true);
-                prop.SetReadOnly(true);
-                classDef.GetIdentityProperties().Add(prop);
-                classDef.GetProperties().Add(prop);
-
-                //Set ID property. Hold this segment ID
-                prop = new MgDataPropertyDefinition("ID");
-                prop.SetDataType(MgPropertyType.Int32);
-                classDef.GetProperties().Add(prop);
-
-                //Set geometry property
-                MgGeometricPropertyDefinition geomProp = new MgGeometricPropertyDefinition("GEOM");
-                //prop.SetGeometryTypes(MgFeatureGeometricType.mfgtSurface); //TODO use the constant when exposed
-                geomProp.SetGeometryTypes(4);
-                classDef.GetProperties().Add(geomProp);
-
-                //Create the schema
-                MgFeatureSchema schema = new MgFeatureSchema("BufferSchema", "Temporary buffer schema");
-                schema.GetClasses().Add(classDef);
-
-                //finally, creation of the feature source
-                MgCreateSdfParams sdfParams = new MgCreateSdfParams("LatLong", map.GetMapSRS(), schema);
-                _featSvc.CreateFeatureSource(fsId, sdfParams);
-
-                //Add layer to map
-                layer = provider.CreateLayer(ldfId);
-                layer.SetName(txtBufferLayer.Text);
-                layer.SetLegendLabel(txtBufferLayer.Text);
-                layer.SetDisplayInLegend(true);
-                layer.SetSelectable(true);
-                layers.Insert(0, layer);
-            }
-            else
-            {
-                //data source already exist. clear its content
-                //
-                ClearDataSource(_featSvc, fsId, "BufferSchema:Buffer");
-            }
-
-            var sel = _viewer.GetSelection();
-            var selLayers = sel.GetLayers();
-
-            MgAgfReaderWriter agfRW = new MgAgfReaderWriter();
-            MgGeometryCollection bufferGeometries = new MgGeometryCollection();
-            MgGeometry geomBuffer;
-
-            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
-            int featId = 0;
-
-            MgBatchPropertyCollection propCollection = new MgBatchPropertyCollection();
-
-            int excludedLayers = 0;
-            MgCoordinateSystem srsDs = null;
-            MgGeometryCollection inputGeometries = new MgGeometryCollection();
-
-            int bufferFeatures = 0;
-            for (int li = 0; li < selLayers.GetCount(); li++)
-            {
-                MgLayerBase selLayer = selLayers.GetItem(li);
-                bool inputLayer = false;
-                String selLayerName = selLayer.GetName();
-                for (int il = 0; il < layerNames.Length; il++)
-                {
-                    if (layerNames[il].Equals(selLayerName))
-                    {
-                        inputLayer = true;
-                        break;
-                    }
-                }
-                if (inputLayer == false)
-                {
-                    continue;
-                }
-
-                // get the data source SRS
-                //
-                MgResourceIdentifier featSourceId = new MgResourceIdentifier(selLayer.GetFeatureSourceId());
-                MgSpatialContextReader ctxs = _featSvc.GetSpatialContexts(featSourceId, false);
-                String srsDefDs = "";
-                if (ctxs != null && ctxs.ReadNext())
-                    srsDefDs = ctxs.GetCoordinateSystemWkt();
-
-                if (srsDefDs == null || srsDefDs.Length == 0)
-                {
-                    excludedLayers++;
-                    continue;
-                }
-
-                var srsFactory = new MgCoordinateSystemFactory();
-                srsDs = srsFactory.Create(srsDefDs);
-                bool arbitraryDsSrs = (srsDs.GetType() == MgCoordinateSystemType.Arbitrary);
-                String dsSrsUnits = "";
-
-                if (arbitraryDsSrs)
-                    dsSrsUnits = srsDs.GetUnits();
-
-                // exclude layer if:
-                //  the map is non-arbitrary and the layer is arbitrary or vice-versa
-                //     or
-                //  layer and map are both arbitrary but have different units
-                //
-                if ((arbitraryDsSrs != arbitraryMapSrs) || (arbitraryDsSrs && (dsSrsUnits != mapSrsUnits)))
-                {
-                    excludedLayers++;
-                    continue;
-                }
-
-                // calculate distance in the data source SRS units
-                //
-                double dist = srsDs.ConvertMetersToCoordinateSystemUnits(distance);
-
-                // calculate great circle unless data source srs is arbitrary
-                MgCoordinateSystemMeasure measure;
-                if (!arbitraryDsSrs)
-                    measure = srsDs.GetMeasure();
-                else
-                    measure = null;
-
-                // create a SRS transformer if necessary
-                MgCoordinateSystemTransform srsXform;
-                if (!srsDefDs.Equals(srsDefMap))
-                    srsXform = srsFactory.GetTransform(srsDs, srsMap);
-                else
-                    srsXform = null;
-
-                String featureClassName = selLayer.GetFeatureClassName();
-                String filter = sel.GenerateFilter(selLayer, featureClassName);
-                if (filter == null || filter.Length == 0)
-                    continue;
-
-                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
-                query.SetFilter(filter);
-
-                MgResourceIdentifier featureSource = new MgResourceIdentifier(selLayer.GetFeatureSourceId());
-
-                MgFeatureReader features = _featSvc.SelectFeatures(featureSource, featureClassName, query);
-
-                if (features.ReadNext())
-                {
-                    MgClassDefinition classDef = features.GetClassDefinition();
-                    String geomPropName = classDef.GetDefaultGeometryPropertyName();
-
-                    do
-                    {
-                        MgByteReader geomReader = features.GetGeometry(geomPropName);
-                        MgGeometry geom = agfRW.Read(geomReader);
-
-                        if (!chkMergeBuffers.Checked)
-                        {
-                            geomBuffer = geom.Buffer(dist, measure);
-                            if (geomBuffer != null)
-                            {
-                                if (srsXform != null)
-                                    geomBuffer = (MgGeometry)geomBuffer.Transform(srsXform);
-                                AddFeatureToCollection(propCollection, agfRW, featId++, geomBuffer);
-                                bufferFeatures++;
-                            }
-                        }
-                        else
-                        {
-                            if (srsXform != null)
-                                geom = (MgGeometry)geom.Transform(srsXform);
-                            inputGeometries.Add(geom);
-                        }
-                    }
-                    while (features.ReadNext());
-
-                    features.Close();
-                }
-            }
-
-            if (chkMergeBuffers.Checked)
-            {
-                if (inputGeometries.GetCount() > 0)
-                {
-                    double dist = srsMap.ConvertMetersToCoordinateSystemUnits(distance);
-                    MgCoordinateSystemMeasure measure;
-                    if (!arbitraryMapSrs)
-                        measure = srsMap.GetMeasure();
-                    else
-                        measure = null;
-
-                    MgGeometryFactory geomFactory = new MgGeometryFactory();
-                    geomBuffer = geomFactory.CreateMultiGeometry(inputGeometries).Buffer(dist, measure);
-                    if (geomBuffer != null)
-                    {
-                        AddFeatureToCollection(propCollection, agfRW, featId, geomBuffer);
-                        bufferFeatures = 1;
-                    }
-                }
-            }
-
-            if (propCollection.GetCount() > 0)
-            {
-                commands.Add(new MgInsertFeatures("BufferSchema:Buffer", propCollection));
-
-                //Insert the features in the temporary data source
-                //
-                ReleaseReader(_featSvc.UpdateFeatures(fsId, commands, false), commands);
-            }
-
-            // Save the new map state
-            //
-            layer.ForceRefresh();
-            _viewer.RefreshMap();
-
-            //build report message
-            MessageBox.Show("Buffer layer (" + txtBufferLayer.Text + ") " + (newBuffer ? "created" : "updated"));
-        }
-
-        private string[] GetLayerNames()
-        {
-            var items = new List<string>();
-            foreach (var it in lstLayers.Items)
-            {
-                items.Add(it.ToString());
-            }
-            return items.ToArray();
-        }
-
-        static string ToHtmlColor(Color color)
-        {
-            return String.Format("{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);
-        }
-
-        static MgLayerBase FindLayer(MgLayerCollection layers, String layerName)
-        {
-            MgLayerBase layer = null;
-            int i = 0;
-            for (i = 0; i < layers.GetCount(); i++)
-            {
-                MgLayerBase layer1 = layers.GetItem(i);
-
-                if (layer1.GetName() == layerName)
-                {
-                    layer = layer1;
-                    break;
-                }
-            }
-            return layer;
-        }
-
-        static string GetMapSrs(MgMapBase map)
-        {
-            try
-            {
-                String srs = map.GetMapSRS();
-                if (srs != "")
-                    return srs;
-            }
-            catch (MgException e)
-            {
-            }
-
-            //No SRS, set to ArbitrayXY meters
-            //
-            return "LOCALCS[\"Non-Earth (Meter)\",LOCAL_DATUM[\"Local Datum\",0],UNIT[\"Meter\", 1],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]";
-        }
-
-        static void ClearDataSource(MgFeatureService featSvc, MgResourceIdentifier fsId, String featureName)
-        {
-            MgDeleteFeatures deleteCmd = new MgDeleteFeatures(featureName, "ID >= 0");
-            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
-            commands.Add(deleteCmd);
-            featSvc.UpdateFeatures(fsId, commands, false);
-        }
-
-        static void ReleaseReader(MgPropertyCollection res, MgFeatureCommandCollection commands)
-        {
-            if (res == null)
-                return;
-
-            for (int i = 0; i < res.GetCount(); i++)
-            {
-                MgFeatureCommand cmd = commands.GetItem(i);
-                if (cmd is MgInsertFeatures)
-                {
-                    MgFeatureProperty resProp = res.GetItem(i) as MgFeatureProperty;
-                    if (resProp != null)
-                    {
-                        MgFeatureReader reader = resProp.GetValue() as MgFeatureReader;
-                        if (reader == null)
-                            return;
-                        reader.Close();
-                    }
-                }
-            }
-        }
-
-        static void AddFeatureToCollection(MgBatchPropertyCollection propCollection, MgAgfReaderWriter agfRW, int featureId, MgGeometry featureGeom)
-        {
-            MgPropertyCollection bufferProps = new MgPropertyCollection();
-            MgInt32Property idProp = new MgInt32Property("ID", featureId);
-            bufferProps.Add(idProp);
-            MgByteReader geomReader = agfRW.Write(featureGeom);
-            MgGeometryProperty geomProp = new MgGeometryProperty("GEOM", geomReader);
-            bufferProps.Add(geomProp);
-            propCollection.Add(bufferProps);
-        }
     }
-
-    public enum StockPattern
-    {
-        Solid,
-        Net,
-        Line,
-        Line_45,
-        Line_90,
-        Line_135,
-        Square,
-        Box,
-        Cross,
-        Dash,
-        Dolmit,
-        Hex,
-        Sacncr,
-        Steel
-    }
 }

Deleted: branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.resx	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgBufferControl.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,123 +0,0 @@
-<?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="colorPicker.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: branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.Designer.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,457 @@
+namespace OSGeo.MapGuide.Viewer
+{
+    partial class MgBufferControlImpl
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.lstLayers = new System.Windows.Forms.ListBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.cmbUnits = new System.Windows.Forms.ComboBox();
+            this.numBufferDistance = new System.Windows.Forms.NumericUpDown();
+            this.label1 = new System.Windows.Forms.Label();
+            this.lblSelectFeatures = new System.Windows.Forms.Label();
+            this.groupBox2 = new System.Windows.Forms.GroupBox();
+            this.btnFillBackColor = new System.Windows.Forms.Button();
+            this.pnlFillBackColor = new System.Windows.Forms.Panel();
+            this.label10 = new System.Windows.Forms.Label();
+            this.numFillTransparency = new System.Windows.Forms.NumericUpDown();
+            this.label5 = new System.Windows.Forms.Label();
+            this.btnFillColor = new System.Windows.Forms.Button();
+            this.pnlFillColor = new System.Windows.Forms.Panel();
+            this.label4 = new System.Windows.Forms.Label();
+            this.cmbFillPattern = new System.Windows.Forms.ComboBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.groupBox3 = new System.Windows.Forms.GroupBox();
+            this.numLineThickness = new System.Windows.Forms.NumericUpDown();
+            this.cmbBorderPattern = new System.Windows.Forms.ComboBox();
+            this.label6 = new System.Windows.Forms.Label();
+            this.label8 = new System.Windows.Forms.Label();
+            this.btnBorderColor = new System.Windows.Forms.Button();
+            this.label7 = new System.Windows.Forms.Label();
+            this.pnlBorderColor = new System.Windows.Forms.Panel();
+            this.btnCreate = new System.Windows.Forms.Button();
+            this.groupBox4 = new System.Windows.Forms.GroupBox();
+            this.chkMergeBuffers = new System.Windows.Forms.CheckBox();
+            this.txtBufferLayer = new System.Windows.Forms.TextBox();
+            this.label9 = new System.Windows.Forms.Label();
+            this.colorPicker = new System.Windows.Forms.ColorDialog();
+            this.groupBox1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numBufferDistance)).BeginInit();
+            this.groupBox2.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numFillTransparency)).BeginInit();
+            this.groupBox3.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numLineThickness)).BeginInit();
+            this.groupBox4.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox1.Controls.Add(this.lstLayers);
+            this.groupBox1.Controls.Add(this.label2);
+            this.groupBox1.Controls.Add(this.cmbUnits);
+            this.groupBox1.Controls.Add(this.numBufferDistance);
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Controls.Add(this.lblSelectFeatures);
+            this.groupBox1.Location = new System.Drawing.Point(0, 0);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(232, 220);
+            this.groupBox1.TabIndex = 0;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Buffer Settings";
+            // 
+            // lstLayers
+            // 
+            this.lstLayers.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.lstLayers.FormattingEnabled = true;
+            this.lstLayers.Location = new System.Drawing.Point(9, 126);
+            this.lstLayers.Name = "lstLayers";
+            this.lstLayers.Size = new System.Drawing.Size(206, 82);
+            this.lstLayers.TabIndex = 5;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(6, 101);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(180, 13);
+            this.label2.TabIndex = 4;
+            this.label2.Text = "Includes the following layers in buffer";
+            // 
+            // cmbUnits
+            // 
+            this.cmbUnits.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbUnits.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbUnits.FormattingEnabled = true;
+            this.cmbUnits.Location = new System.Drawing.Point(105, 66);
+            this.cmbUnits.Name = "cmbUnits";
+            this.cmbUnits.Size = new System.Drawing.Size(110, 21);
+            this.cmbUnits.TabIndex = 3;
+            // 
+            // numBufferDistance
+            // 
+            this.numBufferDistance.Location = new System.Drawing.Point(9, 67);
+            this.numBufferDistance.Maximum = new decimal(new int[] {
+            100000,
+            0,
+            0,
+            0});
+            this.numBufferDistance.Minimum = new decimal(new int[] {
+            100000,
+            0,
+            0,
+            -2147483648});
+            this.numBufferDistance.Name = "numBufferDistance";
+            this.numBufferDistance.Size = new System.Drawing.Size(92, 20);
+            this.numBufferDistance.TabIndex = 2;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(6, 50);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(126, 13);
+            this.label1.TabIndex = 1;
+            this.label1.Text = "Distance around features";
+            // 
+            // lblSelectFeatures
+            // 
+            this.lblSelectFeatures.BackColor = System.Drawing.Color.White;
+            this.lblSelectFeatures.ForeColor = System.Drawing.Color.Blue;
+            this.lblSelectFeatures.Location = new System.Drawing.Point(6, 16);
+            this.lblSelectFeatures.Name = "lblSelectFeatures";
+            this.lblSelectFeatures.Size = new System.Drawing.Size(209, 23);
+            this.lblSelectFeatures.TabIndex = 0;
+            this.lblSelectFeatures.Text = "Select Features on the Map first";
+            this.lblSelectFeatures.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // groupBox2
+            // 
+            this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox2.Controls.Add(this.btnFillBackColor);
+            this.groupBox2.Controls.Add(this.pnlFillBackColor);
+            this.groupBox2.Controls.Add(this.label10);
+            this.groupBox2.Controls.Add(this.numFillTransparency);
+            this.groupBox2.Controls.Add(this.label5);
+            this.groupBox2.Controls.Add(this.btnFillColor);
+            this.groupBox2.Controls.Add(this.pnlFillColor);
+            this.groupBox2.Controls.Add(this.label4);
+            this.groupBox2.Controls.Add(this.cmbFillPattern);
+            this.groupBox2.Controls.Add(this.label3);
+            this.groupBox2.Location = new System.Drawing.Point(0, 220);
+            this.groupBox2.Name = "groupBox2";
+            this.groupBox2.Size = new System.Drawing.Size(232, 144);
+            this.groupBox2.TabIndex = 1;
+            this.groupBox2.TabStop = false;
+            this.groupBox2.Text = "Fill Style";
+            // 
+            // btnFillBackColor
+            // 
+            this.btnFillBackColor.Location = new System.Drawing.Point(183, 102);
+            this.btnFillBackColor.Name = "btnFillBackColor";
+            this.btnFillBackColor.Size = new System.Drawing.Size(32, 23);
+            this.btnFillBackColor.TabIndex = 9;
+            this.btnFillBackColor.Text = "...";
+            this.btnFillBackColor.UseVisualStyleBackColor = true;
+            this.btnFillBackColor.Click += new System.EventHandler(this.btnFillBackColor_Click);
+            // 
+            // pnlFillBackColor
+            // 
+            this.pnlFillBackColor.Location = new System.Drawing.Point(95, 103);
+            this.pnlFillBackColor.Name = "pnlFillBackColor";
+            this.pnlFillBackColor.Size = new System.Drawing.Size(82, 22);
+            this.pnlFillBackColor.TabIndex = 8;
+            // 
+            // label10
+            // 
+            this.label10.AutoSize = true;
+            this.label10.Location = new System.Drawing.Point(30, 107);
+            this.label10.Name = "label10";
+            this.label10.Size = new System.Drawing.Size(59, 13);
+            this.label10.TabIndex = 7;
+            this.label10.Text = "Back Color";
+            // 
+            // numFillTransparency
+            // 
+            this.numFillTransparency.Location = new System.Drawing.Point(95, 77);
+            this.numFillTransparency.Name = "numFillTransparency";
+            this.numFillTransparency.Size = new System.Drawing.Size(120, 20);
+            this.numFillTransparency.TabIndex = 6;
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(17, 79);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(72, 13);
+            this.label5.TabIndex = 5;
+            this.label5.Text = "Transparency";
+            // 
+            // btnFillColor
+            // 
+            this.btnFillColor.Location = new System.Drawing.Point(183, 48);
+            this.btnFillColor.Name = "btnFillColor";
+            this.btnFillColor.Size = new System.Drawing.Size(32, 23);
+            this.btnFillColor.TabIndex = 4;
+            this.btnFillColor.Text = "...";
+            this.btnFillColor.UseVisualStyleBackColor = true;
+            this.btnFillColor.Click += new System.EventHandler(this.btnFillColor_Click);
+            // 
+            // pnlFillColor
+            // 
+            this.pnlFillColor.Location = new System.Drawing.Point(95, 49);
+            this.pnlFillColor.Name = "pnlFillColor";
+            this.pnlFillColor.Size = new System.Drawing.Size(82, 22);
+            this.pnlFillColor.TabIndex = 3;
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(34, 53);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(55, 13);
+            this.label4.TabIndex = 2;
+            this.label4.Text = "Fore Color";
+            // 
+            // cmbFillPattern
+            // 
+            this.cmbFillPattern.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbFillPattern.FormattingEnabled = true;
+            this.cmbFillPattern.Location = new System.Drawing.Point(95, 23);
+            this.cmbFillPattern.Name = "cmbFillPattern";
+            this.cmbFillPattern.Size = new System.Drawing.Size(120, 21);
+            this.cmbFillPattern.TabIndex = 1;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(48, 26);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(41, 13);
+            this.label3.TabIndex = 0;
+            this.label3.Text = "Pattern";
+            // 
+            // groupBox3
+            // 
+            this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox3.Controls.Add(this.numLineThickness);
+            this.groupBox3.Controls.Add(this.cmbBorderPattern);
+            this.groupBox3.Controls.Add(this.label6);
+            this.groupBox3.Controls.Add(this.label8);
+            this.groupBox3.Controls.Add(this.btnBorderColor);
+            this.groupBox3.Controls.Add(this.label7);
+            this.groupBox3.Controls.Add(this.pnlBorderColor);
+            this.groupBox3.Location = new System.Drawing.Point(0, 364);
+            this.groupBox3.Name = "groupBox3";
+            this.groupBox3.Size = new System.Drawing.Size(232, 100);
+            this.groupBox3.TabIndex = 2;
+            this.groupBox3.TabStop = false;
+            this.groupBox3.Text = "Border Style";
+            // 
+            // numLineThickness
+            // 
+            this.numLineThickness.Location = new System.Drawing.Point(95, 73);
+            this.numLineThickness.Name = "numLineThickness";
+            this.numLineThickness.Size = new System.Drawing.Size(120, 20);
+            this.numLineThickness.TabIndex = 13;
+            // 
+            // cmbBorderPattern
+            // 
+            this.cmbBorderPattern.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbBorderPattern.FormattingEnabled = true;
+            this.cmbBorderPattern.Location = new System.Drawing.Point(95, 19);
+            this.cmbBorderPattern.Name = "cmbBorderPattern";
+            this.cmbBorderPattern.Size = new System.Drawing.Size(120, 21);
+            this.cmbBorderPattern.TabIndex = 8;
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(17, 75);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(72, 13);
+            this.label6.TabIndex = 12;
+            this.label6.Text = "Transparency";
+            // 
+            // label8
+            // 
+            this.label8.AutoSize = true;
+            this.label8.Location = new System.Drawing.Point(48, 22);
+            this.label8.Name = "label8";
+            this.label8.Size = new System.Drawing.Size(41, 13);
+            this.label8.TabIndex = 7;
+            this.label8.Text = "Pattern";
+            // 
+            // btnBorderColor
+            // 
+            this.btnBorderColor.Location = new System.Drawing.Point(183, 44);
+            this.btnBorderColor.Name = "btnBorderColor";
+            this.btnBorderColor.Size = new System.Drawing.Size(32, 23);
+            this.btnBorderColor.TabIndex = 11;
+            this.btnBorderColor.Text = "...";
+            this.btnBorderColor.UseVisualStyleBackColor = true;
+            this.btnBorderColor.Click += new System.EventHandler(this.btnBorderColor_Click);
+            // 
+            // label7
+            // 
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(58, 49);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(31, 13);
+            this.label7.TabIndex = 9;
+            this.label7.Text = "Color";
+            // 
+            // pnlBorderColor
+            // 
+            this.pnlBorderColor.Location = new System.Drawing.Point(95, 45);
+            this.pnlBorderColor.Name = "pnlBorderColor";
+            this.pnlBorderColor.Size = new System.Drawing.Size(82, 22);
+            this.pnlBorderColor.TabIndex = 10;
+            // 
+            // btnCreate
+            // 
+            this.btnCreate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.btnCreate.Location = new System.Drawing.Point(9, 567);
+            this.btnCreate.Name = "btnCreate";
+            this.btnCreate.Size = new System.Drawing.Size(98, 23);
+            this.btnCreate.TabIndex = 3;
+            this.btnCreate.Text = "Create Buffer";
+            this.btnCreate.UseVisualStyleBackColor = true;
+            this.btnCreate.Click += new System.EventHandler(this.btnCreate_Click);
+            // 
+            // groupBox4
+            // 
+            this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox4.Controls.Add(this.chkMergeBuffers);
+            this.groupBox4.Controls.Add(this.txtBufferLayer);
+            this.groupBox4.Controls.Add(this.label9);
+            this.groupBox4.Location = new System.Drawing.Point(0, 464);
+            this.groupBox4.Name = "groupBox4";
+            this.groupBox4.Size = new System.Drawing.Size(232, 97);
+            this.groupBox4.TabIndex = 4;
+            this.groupBox4.TabStop = false;
+            this.groupBox4.Text = "Other";
+            // 
+            // chkMergeBuffers
+            // 
+            this.chkMergeBuffers.AutoSize = true;
+            this.chkMergeBuffers.Checked = true;
+            this.chkMergeBuffers.CheckState = System.Windows.Forms.CheckState.Checked;
+            this.chkMergeBuffers.Location = new System.Drawing.Point(12, 69);
+            this.chkMergeBuffers.Name = "chkMergeBuffers";
+            this.chkMergeBuffers.Size = new System.Drawing.Size(117, 17);
+            this.chkMergeBuffers.TabIndex = 2;
+            this.chkMergeBuffers.Text = "Merge Buffer Areas";
+            this.chkMergeBuffers.UseVisualStyleBackColor = true;
+            // 
+            // txtBufferLayer
+            // 
+            this.txtBufferLayer.Location = new System.Drawing.Point(12, 43);
+            this.txtBufferLayer.Name = "txtBufferLayer";
+            this.txtBufferLayer.Size = new System.Drawing.Size(203, 20);
+            this.txtBufferLayer.TabIndex = 1;
+            // 
+            // label9
+            // 
+            this.label9.AutoSize = true;
+            this.label9.Location = new System.Drawing.Point(9, 26);
+            this.label9.Name = "label9";
+            this.label9.Size = new System.Drawing.Size(98, 13);
+            this.label9.TabIndex = 0;
+            this.label9.Text = "Buffer Layer Name:";
+            // 
+            // MgBufferControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.groupBox4);
+            this.Controls.Add(this.btnCreate);
+            this.Controls.Add(this.groupBox3);
+            this.Controls.Add(this.groupBox2);
+            this.Controls.Add(this.groupBox1);
+            this.Name = "MgBufferControl";
+            this.Size = new System.Drawing.Size(232, 601);
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numBufferDistance)).EndInit();
+            this.groupBox2.ResumeLayout(false);
+            this.groupBox2.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numFillTransparency)).EndInit();
+            this.groupBox3.ResumeLayout(false);
+            this.groupBox3.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numLineThickness)).EndInit();
+            this.groupBox4.ResumeLayout(false);
+            this.groupBox4.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.Label lblSelectFeatures;
+        private System.Windows.Forms.ListBox lstLayers;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.ComboBox cmbUnits;
+        private System.Windows.Forms.NumericUpDown numBufferDistance;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.GroupBox groupBox2;
+        private System.Windows.Forms.NumericUpDown numFillTransparency;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.Button btnFillColor;
+        private System.Windows.Forms.Panel pnlFillColor;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.ComboBox cmbFillPattern;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.GroupBox groupBox3;
+        private System.Windows.Forms.NumericUpDown numLineThickness;
+        private System.Windows.Forms.ComboBox cmbBorderPattern;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Label label8;
+        private System.Windows.Forms.Button btnBorderColor;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.Panel pnlBorderColor;
+        private System.Windows.Forms.Button btnCreate;
+        private System.Windows.Forms.GroupBox groupBox4;
+        private System.Windows.Forms.CheckBox chkMergeBuffers;
+        private System.Windows.Forms.TextBox txtBufferLayer;
+        private System.Windows.Forms.Label label9;
+        private System.Windows.Forms.ColorDialog colorPicker;
+        private System.Windows.Forms.Button btnFillBackColor;
+        private System.Windows.Forms.Panel pnlFillBackColor;
+        private System.Windows.Forms.Label label10;
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,493 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+using System.Globalization;
+
+namespace OSGeo.MapGuide.Viewer
+{
+    internal partial class MgBufferControlImpl : MgControlImpl
+    {
+        private IMapViewer _viewer;
+        private MgResourceService _resSvc;
+        private MgFeatureService _featSvc;
+        private string _sessionId;
+
+        public MgBufferControlImpl(IMapViewer viewer)
+        {
+            InitializeComponent();
+            this.Title = Properties.Resources.TitleBuffer;
+            _viewer = viewer;
+            _sessionId = Guid.NewGuid().ToString();
+            var provider = viewer.GetProvider();
+            _resSvc = (MgResourceService)provider.CreateService(MgServiceType.ResourceService);
+            _featSvc = (MgFeatureService)provider.CreateService(MgServiceType.FeatureService);
+
+            cmbUnits.DataSource = Enum.GetValues(typeof(MeasurementUnit));
+            cmbUnits.SelectedItem = MeasurementUnit.Kilometers;
+            cmbBorderPattern.DataSource = Enum.GetValues(typeof(StockPattern));
+            cmbFillPattern.DataSource = Enum.GetValues(typeof(StockPattern));
+
+            cmbBorderPattern.SelectedItem = StockPattern.Solid;
+            cmbFillPattern.SelectedItem = StockPattern.Solid;
+
+            pnlFillColor.BackColor = Color.Red;
+            pnlBorderColor.BackColor = Color.Black;
+
+            numBufferDistance.Value = 1;
+            numFillTransparency.Value = 50;
+            numLineThickness.Value = 1;
+
+            _viewer.SelectionChanged += new EventHandler(OnViewerSelectedChanged);
+            OnViewerSelectedChanged(this, EventArgs.Empty);
+        }
+
+        void OnViewerSelectedChanged(object sender, EventArgs e)
+        {
+            lstLayers.Items.Clear();
+            var sel = _viewer.GetSelection();
+            var layers = sel.GetLayers();
+            if (layers != null)
+            {
+                for (var i = 0; i < layers.GetCount(); i++)
+                {
+                    var layer = layers.GetItem(i);
+                    var name = layer.GetName();
+
+                    lstLayers.Items.Add(name);
+                }
+            }
+
+            lblSelectFeatures.Visible = (lstLayers.Items.Count == 0);
+        }
+
+        private void btnFillColor_Click(object sender, EventArgs e)
+        {
+            if (colorPicker.ShowDialog() == DialogResult.OK)
+            {
+                pnlFillColor.BackColor = colorPicker.Color;
+            }
+        }
+
+        private void btnBorderColor_Click(object sender, EventArgs e)
+        {
+            if (colorPicker.ShowDialog() == DialogResult.OK)
+            {
+                pnlBorderColor.BackColor = colorPicker.Color;
+            }
+        }
+
+        private void btnFillBackColor_Click(object sender, EventArgs e)
+        {
+            if (colorPicker.ShowDialog() == DialogResult.OK)
+            {
+                pnlFillBackColor.BackColor = colorPicker.Color;
+            }
+        }
+
+        private void btnCreate_Click(object sender, EventArgs e)
+        {
+            var layerName = txtBufferLayer.Text.Trim();
+            if (string.IsNullOrEmpty(layerName))
+            {
+                MessageBox.Show("Please enter a name for this layer");
+                return;
+            }
+
+            if (lstLayers.SelectedItems.Count == 0)
+            {
+                MessageBox.Show("Please include one or more layers to create a buffer from");
+                return;
+            }
+
+            var map = _viewer.GetMap();
+            var layers = map.GetLayers();
+            var provider = _viewer.GetProvider();
+
+            //From here, it's the same logic as buffer.aspx in .net MapGuide AJAX viewer
+            MgResourceIdentifier fsId = new MgResourceIdentifier("Session:" + _sessionId + "//" + txtBufferLayer.Text + "_Buffer.FeatureSource");
+            MgResourceIdentifier ldfId = new MgResourceIdentifier("Session:" + _sessionId + "//" + txtBufferLayer.Text + "_Buffer.LayerDefinition");
+
+            MgLayerBase layer = FindLayer(layers, txtBufferLayer.Text);
+            string[] layerNames = GetLayerNames();
+
+            double distance = Convert.ToDouble(numBufferDistance.Value);
+            MeasurementUnit bUnits = (MeasurementUnit)cmbUnits.SelectedItem;
+            switch (bUnits)
+            {
+                case MeasurementUnit.Feet:
+                    distance *= 0.30480;
+                    break;
+                case MeasurementUnit.Kilometers:
+                    distance *= 1000;
+                    break;
+                case MeasurementUnit.Miles:
+                    distance *= 1609.35;
+                    break;
+            }
+
+            String srsDefMap = GetMapSrs(map);
+            MgCoordinateSystem srsMap = provider.GetMapCoordinateSystem();
+            string mapSrsUnits = "";
+            bool arbitraryMapSrs = (srsMap.GetType() == MgCoordinateSystemType.Arbitrary);
+            if (arbitraryMapSrs)
+                mapSrsUnits = srsMap.GetUnits();
+
+            String xtrans = String.Format("{0:x2}", ((int)(255 * Convert.ToInt32(numFillTransparency.Value) / 100)));
+            var lineColor = ToHtmlColor(pnlBorderColor.BackColor);
+            var foreColor = ToHtmlColor(pnlFillColor.BackColor);
+            var backColor = ToHtmlColor(pnlFillBackColor.BackColor);
+            String layerTempl = string.Format(Properties.Resources.AreaLayerDef,
+                    fsId.ToString(),
+                    "BufferSchema:Buffer",
+                    "GEOM",
+                    cmbFillPattern.SelectedItem,
+                    xtrans + foreColor,
+                    ((0 != 1/*transparent*/) ? "ff" : "00") + backColor,
+                    cmbBorderPattern.SelectedItem,
+                    numLineThickness.Value.ToString(NumberFormatInfo.InvariantInfo),
+                    lineColor
+            );
+            byte[] bytes = Encoding.UTF8.GetBytes(layerTempl);
+            MgByteSource src = new MgByteSource(bytes, bytes.Length);
+            MgByteReader layerDefContent = src.GetReader();
+            _resSvc.SetResource(ldfId, layerDefContent, null);
+
+            bool newBuffer = false;
+            if (layer == null)
+            {
+                newBuffer = true;
+
+                //Targetting a new layer. create a data source for it
+                //
+                MgClassDefinition classDef = new MgClassDefinition();
+
+                classDef.SetName("Buffer");
+                classDef.SetDescription("Feature class for buffer layer");
+                classDef.SetDefaultGeometryPropertyName("GEOM");
+
+                //Set KEY property
+                MgDataPropertyDefinition prop = new MgDataPropertyDefinition("KEY");
+                prop.SetDataType(MgPropertyType.Int32);
+                prop.SetAutoGeneration(true);
+                prop.SetReadOnly(true);
+                classDef.GetIdentityProperties().Add(prop);
+                classDef.GetProperties().Add(prop);
+
+                //Set ID property. Hold this segment ID
+                prop = new MgDataPropertyDefinition("ID");
+                prop.SetDataType(MgPropertyType.Int32);
+                classDef.GetProperties().Add(prop);
+
+                //Set geometry property
+                MgGeometricPropertyDefinition geomProp = new MgGeometricPropertyDefinition("GEOM");
+                //prop.SetGeometryTypes(MgFeatureGeometricType.mfgtSurface); //TODO use the constant when exposed
+                geomProp.SetGeometryTypes(4);
+                classDef.GetProperties().Add(geomProp);
+
+                //Create the schema
+                MgFeatureSchema schema = new MgFeatureSchema("BufferSchema", "Temporary buffer schema");
+                schema.GetClasses().Add(classDef);
+
+                //finally, creation of the feature source
+                MgCreateSdfParams sdfParams = new MgCreateSdfParams("LatLong", map.GetMapSRS(), schema);
+                _featSvc.CreateFeatureSource(fsId, sdfParams);
+
+                //Add layer to map
+                layer = provider.CreateLayer(ldfId);
+                layer.SetName(txtBufferLayer.Text);
+                layer.SetLegendLabel(txtBufferLayer.Text);
+                layer.SetDisplayInLegend(true);
+                layer.SetSelectable(true);
+                layers.Insert(0, layer);
+            }
+            else
+            {
+                //data source already exist. clear its content
+                //
+                ClearDataSource(_featSvc, fsId, "BufferSchema:Buffer");
+            }
+
+            var sel = _viewer.GetSelection();
+            var selLayers = sel.GetLayers();
+
+            MgAgfReaderWriter agfRW = new MgAgfReaderWriter();
+            MgGeometryCollection bufferGeometries = new MgGeometryCollection();
+            MgGeometry geomBuffer;
+
+            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
+            int featId = 0;
+
+            MgBatchPropertyCollection propCollection = new MgBatchPropertyCollection();
+
+            int excludedLayers = 0;
+            MgCoordinateSystem srsDs = null;
+            MgGeometryCollection inputGeometries = new MgGeometryCollection();
+
+            int bufferFeatures = 0;
+            for (int li = 0; li < selLayers.GetCount(); li++)
+            {
+                MgLayerBase selLayer = selLayers.GetItem(li);
+                bool inputLayer = false;
+                String selLayerName = selLayer.GetName();
+                for (int il = 0; il < layerNames.Length; il++)
+                {
+                    if (layerNames[il].Equals(selLayerName))
+                    {
+                        inputLayer = true;
+                        break;
+                    }
+                }
+                if (inputLayer == false)
+                {
+                    continue;
+                }
+
+                // get the data source SRS
+                //
+                MgResourceIdentifier featSourceId = new MgResourceIdentifier(selLayer.GetFeatureSourceId());
+                MgSpatialContextReader ctxs = _featSvc.GetSpatialContexts(featSourceId, false);
+                String srsDefDs = "";
+                if (ctxs != null && ctxs.ReadNext())
+                    srsDefDs = ctxs.GetCoordinateSystemWkt();
+
+                if (srsDefDs == null || srsDefDs.Length == 0)
+                {
+                    excludedLayers++;
+                    continue;
+                }
+
+                var srsFactory = new MgCoordinateSystemFactory();
+                srsDs = srsFactory.Create(srsDefDs);
+                bool arbitraryDsSrs = (srsDs.GetType() == MgCoordinateSystemType.Arbitrary);
+                String dsSrsUnits = "";
+
+                if (arbitraryDsSrs)
+                    dsSrsUnits = srsDs.GetUnits();
+
+                // exclude layer if:
+                //  the map is non-arbitrary and the layer is arbitrary or vice-versa
+                //     or
+                //  layer and map are both arbitrary but have different units
+                //
+                if ((arbitraryDsSrs != arbitraryMapSrs) || (arbitraryDsSrs && (dsSrsUnits != mapSrsUnits)))
+                {
+                    excludedLayers++;
+                    continue;
+                }
+
+                // calculate distance in the data source SRS units
+                //
+                double dist = srsDs.ConvertMetersToCoordinateSystemUnits(distance);
+
+                // calculate great circle unless data source srs is arbitrary
+                MgCoordinateSystemMeasure measure;
+                if (!arbitraryDsSrs)
+                    measure = srsDs.GetMeasure();
+                else
+                    measure = null;
+
+                // create a SRS transformer if necessary
+                MgCoordinateSystemTransform srsXform;
+                if (!srsDefDs.Equals(srsDefMap))
+                    srsXform = srsFactory.GetTransform(srsDs, srsMap);
+                else
+                    srsXform = null;
+
+                String featureClassName = selLayer.GetFeatureClassName();
+                String filter = sel.GenerateFilter(selLayer, featureClassName);
+                if (filter == null || filter.Length == 0)
+                    continue;
+
+                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
+                query.SetFilter(filter);
+
+                MgResourceIdentifier featureSource = new MgResourceIdentifier(selLayer.GetFeatureSourceId());
+
+                MgFeatureReader features = _featSvc.SelectFeatures(featureSource, featureClassName, query);
+
+                if (features.ReadNext())
+                {
+                    MgClassDefinition classDef = features.GetClassDefinition();
+                    String geomPropName = classDef.GetDefaultGeometryPropertyName();
+
+                    do
+                    {
+                        MgByteReader geomReader = features.GetGeometry(geomPropName);
+                        MgGeometry geom = agfRW.Read(geomReader);
+
+                        if (!chkMergeBuffers.Checked)
+                        {
+                            geomBuffer = geom.Buffer(dist, measure);
+                            if (geomBuffer != null)
+                            {
+                                if (srsXform != null)
+                                    geomBuffer = (MgGeometry)geomBuffer.Transform(srsXform);
+                                AddFeatureToCollection(propCollection, agfRW, featId++, geomBuffer);
+                                bufferFeatures++;
+                            }
+                        }
+                        else
+                        {
+                            if (srsXform != null)
+                                geom = (MgGeometry)geom.Transform(srsXform);
+                            inputGeometries.Add(geom);
+                        }
+                    }
+                    while (features.ReadNext());
+
+                    features.Close();
+                }
+            }
+
+            if (chkMergeBuffers.Checked)
+            {
+                if (inputGeometries.GetCount() > 0)
+                {
+                    double dist = srsMap.ConvertMetersToCoordinateSystemUnits(distance);
+                    MgCoordinateSystemMeasure measure;
+                    if (!arbitraryMapSrs)
+                        measure = srsMap.GetMeasure();
+                    else
+                        measure = null;
+
+                    MgGeometryFactory geomFactory = new MgGeometryFactory();
+                    geomBuffer = geomFactory.CreateMultiGeometry(inputGeometries).Buffer(dist, measure);
+                    if (geomBuffer != null)
+                    {
+                        AddFeatureToCollection(propCollection, agfRW, featId, geomBuffer);
+                        bufferFeatures = 1;
+                    }
+                }
+            }
+
+            if (propCollection.GetCount() > 0)
+            {
+                commands.Add(new MgInsertFeatures("BufferSchema:Buffer", propCollection));
+
+                //Insert the features in the temporary data source
+                //
+                ReleaseReader(_featSvc.UpdateFeatures(fsId, commands, false), commands);
+            }
+
+            // Save the new map state
+            //
+            layer.ForceRefresh();
+            _viewer.RefreshMap();
+
+            //build report message
+            MessageBox.Show("Buffer layer (" + txtBufferLayer.Text + ") " + (newBuffer ? "created" : "updated"));
+        }
+
+        private string[] GetLayerNames()
+        {
+            var items = new List<string>();
+            foreach (var it in lstLayers.Items)
+            {
+                items.Add(it.ToString());
+            }
+            return items.ToArray();
+        }
+
+        static string ToHtmlColor(Color color)
+        {
+            return String.Format("{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);
+        }
+
+        static MgLayerBase FindLayer(MgLayerCollection layers, String layerName)
+        {
+            MgLayerBase layer = null;
+            int i = 0;
+            for (i = 0; i < layers.GetCount(); i++)
+            {
+                MgLayerBase layer1 = layers.GetItem(i);
+
+                if (layer1.GetName() == layerName)
+                {
+                    layer = layer1;
+                    break;
+                }
+            }
+            return layer;
+        }
+
+        static string GetMapSrs(MgMapBase map)
+        {
+            try
+            {
+                String srs = map.GetMapSRS();
+                if (srs != "")
+                    return srs;
+            }
+            catch (MgException e)
+            {
+            }
+
+            //No SRS, set to ArbitrayXY meters
+            //
+            return "LOCALCS[\"Non-Earth (Meter)\",LOCAL_DATUM[\"Local Datum\",0],UNIT[\"Meter\", 1],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]";
+        }
+
+        static void ClearDataSource(MgFeatureService featSvc, MgResourceIdentifier fsId, String featureName)
+        {
+            MgDeleteFeatures deleteCmd = new MgDeleteFeatures(featureName, "ID >= 0");
+            MgFeatureCommandCollection commands = new MgFeatureCommandCollection();
+            commands.Add(deleteCmd);
+            featSvc.UpdateFeatures(fsId, commands, false);
+        }
+
+        static void ReleaseReader(MgPropertyCollection res, MgFeatureCommandCollection commands)
+        {
+            if (res == null)
+                return;
+
+            for (int i = 0; i < res.GetCount(); i++)
+            {
+                MgFeatureCommand cmd = commands.GetItem(i);
+                if (cmd is MgInsertFeatures)
+                {
+                    MgFeatureProperty resProp = res.GetItem(i) as MgFeatureProperty;
+                    if (resProp != null)
+                    {
+                        MgFeatureReader reader = resProp.GetValue() as MgFeatureReader;
+                        if (reader == null)
+                            return;
+                        reader.Close();
+                    }
+                }
+            }
+        }
+
+        static void AddFeatureToCollection(MgBatchPropertyCollection propCollection, MgAgfReaderWriter agfRW, int featureId, MgGeometry featureGeom)
+        {
+            MgPropertyCollection bufferProps = new MgPropertyCollection();
+            MgInt32Property idProp = new MgInt32Property("ID", featureId);
+            bufferProps.Add(idProp);
+            MgByteReader geomReader = agfRW.Write(featureGeom);
+            MgGeometryProperty geomProp = new MgGeometryProperty("GEOM", geomReader);
+            bufferProps.Add(geomProp);
+            propCollection.Add(bufferProps);
+        }
+    }
+
+    public enum StockPattern
+    {
+        Solid,
+        Net,
+        Line,
+        Line_45,
+        Line_90,
+        Line_135,
+        Square,
+        Box,
+        Cross,
+        Dash,
+        Dolmit,
+        Hex,
+        Sacncr,
+        Steel
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.resx	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgBufferControlImpl.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -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="colorPicker.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: branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgComponent.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,216 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Drawing;
+using System.Diagnostics;
+
+namespace OSGeo.MapGuide.Viewer
+{
+    /// <summary>
+    /// The base class of all viewer components. This is analogous to a command in the MapGuide
+    /// AJAX viewer and a widget in the Fusion viewer.
+    /// </summary>
+    [ToolboxItem(false)]
+    public class MgComponent : Component
+    {
+        private IMapViewer _viewer;
+
+        /// <summary>
+        /// Gets whether to disable invocation entry points (eg. buttons, menus, etc) to this component when the
+        /// viewer is busy
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("Disables this component while the map is loading")]
+        public virtual bool DisableWhenMapIsLoading { get { return true; } }
+
+        /// <summary>
+        /// Gets or sets the description of this component
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("The description of this component")]
+        public string Label { get; set; }
+
+        /// <summary>
+        /// Gets or sets the tooltip text of this component
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("The tooltip text of this component")]
+        public string ToolTipText { get; set; }
+
+        /// <summary>
+        /// The icon for this component
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("The icon for this component")]
+        public Image Icon { get; set; }
+
+        /// <summary>
+        /// Gets or sets the view instance to subscribe events to
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("The viewer instance to subscribe events to")]
+        public IMapViewer Viewer
+        {
+            get { return _viewer; }
+            set
+            {
+                if (_viewer != null)
+                    UnsubscribeViewerEvents(_viewer);
+                _viewer = value;
+                SubscribeViewerEvents(_viewer);
+            }
+        }
+
+        /// <summary>
+        /// Subscribes to viewer events
+        /// </summary>
+        /// <param name="viewer"></param>
+        protected virtual void SubscribeViewerEvents(IMapViewer viewer)
+        {
+            if (viewer != null)
+                viewer.PropertyChanged += OnViewerPropertyChanged;
+        }
+
+        public event ViewerBusyStateEventHandler ViewerBusyStateChanged;
+
+        void OnViewerPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == "IsBusy")
+            {
+                var busy = this.Viewer.IsBusy;
+                Trace.TraceInformation("Dispatching busy state event to " + _listeners.Count + " listeners");
+                foreach (var l in _listeners)
+                    l.SetBusy(busy);
+            }
+        }
+
+        /// <summary>
+        /// Unsubscribes events from the specified viewer instance
+        /// </summary>
+        /// <param name="viewer"></param>
+        protected virtual void UnsubscribeViewerEvents(IMapViewer viewer)
+        {
+            if (viewer != null)
+                viewer.PropertyChanged -= OnViewerPropertyChanged;
+        }
+
+        private List<IMapViewerBusyStateListener> _listeners = new List<IMapViewerBusyStateListener>();
+
+        public void AddListener(IMapViewerBusyStateListener listener)
+        {
+            _listeners.Add(listener);
+        }
+
+        public void RemoveListener(IMapViewerBusyStateListener listener)
+        {
+            _listeners.Remove(listener);
+        }
+
+        /// <summary>
+        /// Invokes this component
+        /// </summary>
+        public virtual void Invoke() 
+        {
+            
+        }
+    }
+
+    public delegate void ViewerBusyStateEventHandler(bool busy);
+
+    public interface IMapViewerBusyStateListener
+    {
+        void SetBusy(bool busy);
+    }
+
+    /// <summary>
+    /// Indicates the target a UI-based component should display its UI view in
+    /// </summary>
+    public enum MgViewerTarget
+    {
+        /// <summary>
+        /// Display the UI view within the specified parent container
+        /// </summary>
+        ParentContainer,
+        /// <summary>
+        /// Display the UI view within a new window
+        /// </summary>
+        NewWindow
+    }
+
+    /// <summary>
+    /// The base class of all UI-based components
+    /// </summary>
+    [ToolboxItem(false)]
+    public class MgViewerComponent : MgComponent
+    {
+        protected MgViewerComponent()
+        {
+            this.ParentContainer = null;
+            this.Target = MgViewerTarget.NewWindow;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("The control which will house this component")]
+        public Control ParentContainer
+        {
+            get;
+            set;
+        }
+
+        private MgViewerTarget _target;
+
+        /// <summary>
+        /// Gets or sets the target that this component should display its UI view in
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [DefaultValue(MgViewerTarget.NewWindow)]
+        [Description("Target that this component should display its UI view in")]
+        public MgViewerTarget Target
+        {
+            get { return _target; }
+            set
+            {
+                if (value == MgViewerTarget.ParentContainer && this.ParentContainer == null)
+                    throw new ArgumentException("Must specify a parent container");
+                _target = value;
+            }
+        }
+
+        /// <summary>
+        /// Creates the associated view. Must be overridden by subclasses
+        /// </summary>
+        /// <returns></returns>
+        protected virtual MgControlImpl CreateControlImpl() { throw new NotImplementedException(); }
+
+        public override void Invoke()
+        {
+            var control = CreateControlImpl();
+            control.Dock = DockStyle.Fill;
+            if (this.Target == MgViewerTarget.ParentContainer)
+            {
+                this.ParentContainer.Controls.Clear();
+                this.ParentContainer.Controls.Add(control);
+            }
+            else //New Window
+            {
+                var form = new Form();
+                Rectangle screenRectangle = form.RectangleToScreen(form.ClientRectangle);
+                int titleHeight = screenRectangle.Top - form.Top;
+                form.Width = control.PreferredSize.Width;
+                form.Height = control.PreferredSize.Height + titleHeight + 10; //HACK: height calculation is imperfect, so pad out
+                form.Text = control.Title;
+                form.Controls.Add(control);
+
+                if (control.ModalWindow)
+                    form.ShowDialog();
+                else
+                    form.Show();
+            }
+        }
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgControlImpl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgControlImpl.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgControlImpl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using System.ComponentModel;
+
+namespace OSGeo.MapGuide.Viewer
+{
+    /// <summary>
+    /// Base class for views show by their associated <see cref="T:OSGeo.MapGuide.Viewer.MgViewerComponent"/> instances
+    /// </summary>
+    [ToolboxItem(false)]
+    public class MgControlImpl : UserControl
+    {
+        /// <summary>
+        /// Gets or set the title to show if this view is shown in a new window
+        /// </summary>
+        public virtual string Title { get; set; }
+
+        protected MgControlImpl() { this.ModalWindow = false; }
+
+        /// <summary>
+        /// Gets whether to show as a modal window if parent component chooses to show this component
+        /// in a new window. Only applies if parent component shows this component in a new window
+        /// </summary>
+        public virtual bool ModalWindow { get; set; }
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgInvokeComponent.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgInvokeComponent.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgInvokeComponent.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms.Design;
+using System.Diagnostics;
+
+namespace OSGeo.MapGuide.Viewer
+{
+    /// <summary>
+    /// A specialized instance of <see cref="T:System.Windows.Forms.ToolStripButton"/> that can
+    /// invoke the assigned <see cref="T:OSGeo.MapGuide.Viewer.MgComponent"/> instance.
+    /// </summary>
+    [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip)]
+    public class MgInvokeComponentButton : ToolStripButton, IMapViewerBusyStateListener
+    {
+        private MgComponent _component;
+
+        /// <summary>
+        /// Gets or sets the target component to be invoked
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("The target component to invoke when this component is clicked. All other UI properties are inherited from this compoent")]
+        public MgComponent TargetComponent
+        {
+            get { return _component; }
+            set 
+            {
+                if (_component != null)
+                    _component.RemoveListener(this);
+                _component = value;
+                if (_component != null)
+                {
+                    base.ToolTipText = _component.ToolTipText;
+                    base.Text = _component.Label;
+                    base.Image = _component.Icon;
+                    _component.AddListener(this);
+                }
+            }
+        }
+
+        protected override void OnClick(EventArgs e)
+        {
+            if (this.TargetComponent == null)
+                throw new InvalidOperationException("No target component assigned to this component");
+
+            this.TargetComponent.Invoke();
+
+            base.OnClick(e);
+        }
+
+        public void SetBusy(bool busy)
+        {
+            this.Enabled = !busy;
+        }
+    }
+
+    /// <summary>
+    /// A specialized instance of <see cref="T:System.Windows.Forms.ToolStripMenuItem"/> that can
+    /// invoke the assigned <see cref="T:OSGeo.MapGuide.Viewer.MgComponent"/> instance.
+    /// </summary>
+    [ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ContextMenuStrip | ToolStripItemDesignerAvailability.MenuStrip)]
+    public class MgInvokeComponentMenuStripItem : ToolStripMenuItem, IMapViewerBusyStateListener
+    {
+        private MgComponent _component;
+
+        /// <summary>
+        /// Gets or sets the target component to be invoked
+        /// </summary>
+        [Category("MapGuide Component Properties")]
+        [Description("The target component to invoke when this component is clicked. All other UI properties are inherited from this compoent")]
+        public MgComponent TargetComponent
+        {
+            get { return _component; }
+            set
+            {
+                if (_component != null)
+                    _component.RemoveListener(this);
+                _component = value;
+                if (_component != null)
+                {
+                    base.ToolTipText = _component.ToolTipText;
+                    base.Text = _component.Label;
+                    base.Image = _component.Icon;
+                    _component.AddListener(this);
+                }
+            }
+        }
+
+        protected override void OnClick(EventArgs e)
+        {
+            if (this.TargetComponent == null)
+                throw new InvalidOperationException("No target component assigned to this component");
+
+            this.TargetComponent.Invoke();
+
+            base.OnClick(e);
+        }
+
+        public void SetBusy(bool busy)
+        {
+            this.Enabled = !busy;
+        }
+    }
+}

Deleted: branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.Designer.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,155 +0,0 @@
-namespace OSGeo.MapGuide.Viewer
-{
-    partial class MgLineMeasureControl
-    {
-        /// <summary> 
-        /// Required designer variable.
-        /// </summary>
-        private System.ComponentModel.IContainer components = null;
-
-        /// <summary> 
-        /// Clean up any resources being used.
-        /// </summary>
-        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Component Designer generated code
-
-        /// <summary> 
-        /// Required method for Designer support - do not modify 
-        /// the contents of this method with the code editor.
-        /// </summary>
-        private void InitializeComponent()
-        {
-            this.label1 = new System.Windows.Forms.Label();
-            this.lstSegments = new System.Windows.Forms.ListBox();
-            this.label2 = new System.Windows.Forms.Label();
-            this.lblUnits = new System.Windows.Forms.Label();
-            this.label3 = new System.Windows.Forms.Label();
-            this.cmbUnits = new System.Windows.Forms.ComboBox();
-            this.btnStart = new System.Windows.Forms.Button();
-            this.groupBox1 = new System.Windows.Forms.GroupBox();
-            this.groupBox1.SuspendLayout();
-            this.SuspendLayout();
-            // 
-            // label1
-            // 
-            this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-            this.label1.AutoSize = true;
-            this.label1.Location = new System.Drawing.Point(15, 297);
-            this.label1.Name = "label1";
-            this.label1.Size = new System.Drawing.Size(157, 13);
-            this.label1.TabIndex = 0;
-            this.label1.Text = "Click \"Start\" to begin measuring";
-            // 
-            // lstSegments
-            // 
-            this.lstSegments.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.lstSegments.FormattingEnabled = true;
-            this.lstSegments.Location = new System.Drawing.Point(3, 16);
-            this.lstSegments.Name = "lstSegments";
-            this.lstSegments.Size = new System.Drawing.Size(206, 192);
-            this.lstSegments.TabIndex = 1;
-            // 
-            // label2
-            // 
-            this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-            this.label2.AutoSize = true;
-            this.label2.Location = new System.Drawing.Point(15, 270);
-            this.label2.Name = "label2";
-            this.label2.Size = new System.Drawing.Size(79, 13);
-            this.label2.TabIndex = 2;
-            this.label2.Text = "Total Distance:";
-            // 
-            // lblUnits
-            // 
-            this.lblUnits.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-            this.lblUnits.AutoSize = true;
-            this.lblUnits.Location = new System.Drawing.Point(100, 270);
-            this.lblUnits.Name = "lblUnits";
-            this.lblUnits.Size = new System.Drawing.Size(0, 13);
-            this.lblUnits.TabIndex = 3;
-            // 
-            // label3
-            // 
-            this.label3.AutoSize = true;
-            this.label3.Location = new System.Drawing.Point(15, 17);
-            this.label3.Name = "label3";
-            this.label3.Size = new System.Drawing.Size(34, 13);
-            this.label3.TabIndex = 4;
-            this.label3.Text = "Units:";
-            // 
-            // cmbUnits
-            // 
-            this.cmbUnits.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.cmbUnits.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cmbUnits.FormattingEnabled = true;
-            this.cmbUnits.Location = new System.Drawing.Point(97, 14);
-            this.cmbUnits.Name = "cmbUnits";
-            this.cmbUnits.Size = new System.Drawing.Size(127, 21);
-            this.cmbUnits.TabIndex = 5;
-            this.cmbUnits.SelectedIndexChanged += new System.EventHandler(this.cmbUnits_SelectedIndexChanged);
-            // 
-            // btnStart
-            // 
-            this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-            this.btnStart.Location = new System.Drawing.Point(18, 325);
-            this.btnStart.Name = "btnStart";
-            this.btnStart.Size = new System.Drawing.Size(82, 23);
-            this.btnStart.TabIndex = 6;
-            this.btnStart.Text = "Start";
-            this.btnStart.UseVisualStyleBackColor = true;
-            this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
-            // 
-            // groupBox1
-            // 
-            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.groupBox1.Controls.Add(this.lstSegments);
-            this.groupBox1.Location = new System.Drawing.Point(15, 41);
-            this.groupBox1.Name = "groupBox1";
-            this.groupBox1.Size = new System.Drawing.Size(212, 211);
-            this.groupBox1.TabIndex = 7;
-            this.groupBox1.TabStop = false;
-            this.groupBox1.Text = "Segments";
-            // 
-            // MgLineMeasureControl
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.Controls.Add(this.groupBox1);
-            this.Controls.Add(this.btnStart);
-            this.Controls.Add(this.cmbUnits);
-            this.Controls.Add(this.label3);
-            this.Controls.Add(this.lblUnits);
-            this.Controls.Add(this.label2);
-            this.Controls.Add(this.label1);
-            this.Name = "MgLineMeasureControl";
-            this.Size = new System.Drawing.Size(247, 360);
-            this.groupBox1.ResumeLayout(false);
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.Label label1;
-        private System.Windows.Forms.ListBox lstSegments;
-        private System.Windows.Forms.Label label2;
-        private System.Windows.Forms.Label lblUnits;
-        private System.Windows.Forms.Label label3;
-        private System.Windows.Forms.ComboBox cmbUnits;
-        private System.Windows.Forms.Button btnStart;
-        private System.Windows.Forms.GroupBox groupBox1;
-    }
-}

Deleted: branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,133 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
-using System.Text;
-using System.Windows.Forms;
-
-namespace OSGeo.MapGuide.Viewer
-{
-    public partial class MgLineMeasureControl : UserControl
-    {
-        private IMapViewer _viewer;
-        private MgCoordinateSystem _mapCs;
-        private BindingList<MeasuredLineSegment> _segments;
-
-        public MgLineMeasureControl(IMapViewer viewer, MeasurementUnit preferredUnit)
-        {
-            InitializeComponent();
-            _viewer = viewer;
-            _segments = new BindingList<MeasuredLineSegment>();
-            cmbUnits.DataSource = Enum.GetValues(typeof(MeasurementUnit));
-            cmbUnits.SelectedItem = preferredUnit;
-            lstSegments.DataSource = _segments;
-            _mapCs = _viewer.GetProvider().GetMapCoordinateSystem();
-        }
-
-        private void btnStart_Click(object sender, EventArgs e)
-        {
-            btnStart.Enabled = false;
-            _segments.Clear();
-            _viewer.DigitizeLineString((coordinates) => //Completed
-            {
-                btnStart.Enabled = true;
-            }, (x1, y1, x2, y2) => //Segment completed
-            {
-                double dist = 0.0;
-                if (_mapCs.GetType() == MgCoordinateSystemType.Geographic)
-                    dist = _mapCs.MeasureGreatCircleDistance(x1, y1, x2, y2);
-                else
-                    dist = _mapCs.MeasureEuclideanDistance(x1, y1, x2, y2);
-
-                //Convert this distance to meters
-                dist = _mapCs.ConvertCoordinateSystemUnitsToMeters(dist);
-                //Add to list of line segments
-                _segments.Add(new MeasuredLineSegment() { MapDistanceMeters = dist, Units = (MeasurementUnit)cmbUnits.SelectedItem });
-
-                lblUnits.Text = TotalUnits(_segments).ToString();
-            });
-        }
-
-        private static double TotalUnits(IEnumerable<MeasuredLineSegment> segments)
-        {
-            double total = 0.0;
-            foreach (var seg in segments)
-            {
-                total += seg.DisplayUnits;
-            }
-            return total;
-        }
-
-        private void cmbUnits_SelectedIndexChanged(object sender, EventArgs e)
-        {
-            //Update segments units, then total
-            foreach (var seg in _segments)
-            {
-                seg.Units = (MeasurementUnit)cmbUnits.SelectedItem;
-            }
-            lblUnits.Text = TotalUnits(_segments).ToString(); 
-        }
-    }
-
-    public enum MeasurementUnit
-    {
-        Feet,
-        Meters,
-        Kilometers,
-        Miles
-    }
-
-    public class MeasuredLineSegment : INotifyPropertyChanged
-    {
-        public double MapDistanceMeters { get; set; }
-
-        private MeasurementUnit _units;
-
-        public MeasurementUnit Units
-        {
-            get { return _units; }
-            set 
-            {
-                if (!value.Equals(_units))
-                {
-                    _units = value;
-                    var h = this.PropertyChanged;
-                    if (h != null) 
-                    {
-                        h(this, new PropertyChangedEventArgs("Units"));
-                        h(this, new PropertyChangedEventArgs("DisplayUnits"));
-                    }
-                }
-            }
-        }
-
-        const double M_TO_KM = 0.001;
-        const double M_TO_MI = 0.000621371192;
-
-        public double DisplayUnits
-        {
-            get
-            {
-                var dist = this.MapDistanceMeters;
-                switch (this.Units)
-                {
-                    case MeasurementUnit.Kilometers:
-                        dist *= M_TO_KM;
-                        break;
-                    case MeasurementUnit.Miles:
-                        dist *= M_TO_MI;
-                        break;
-                }
-                return dist;
-            }
-        }
-
-        public override string ToString()
-        {
-            return string.Format("{0} {1}", this.DisplayUnits, this.Units);
-        }
-
-        public event PropertyChangedEventHandler PropertyChanged;
-    }
-}

Deleted: branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.resx	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControl.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,120 +0,0 @@
-<?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

Added: branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.Designer.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,155 @@
+namespace OSGeo.MapGuide.Viewer
+{
+    partial class MgLineMeasureControlImpl
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label1 = new System.Windows.Forms.Label();
+            this.lstSegments = new System.Windows.Forms.ListBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.lblUnits = new System.Windows.Forms.Label();
+            this.label3 = new System.Windows.Forms.Label();
+            this.cmbUnits = new System.Windows.Forms.ComboBox();
+            this.btnStart = new System.Windows.Forms.Button();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.groupBox1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(15, 297);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(157, 13);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Click \"Start\" to begin measuring";
+            // 
+            // lstSegments
+            // 
+            this.lstSegments.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.lstSegments.FormattingEnabled = true;
+            this.lstSegments.Location = new System.Drawing.Point(3, 16);
+            this.lstSegments.Name = "lstSegments";
+            this.lstSegments.Size = new System.Drawing.Size(206, 192);
+            this.lstSegments.TabIndex = 1;
+            // 
+            // label2
+            // 
+            this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(15, 270);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(79, 13);
+            this.label2.TabIndex = 2;
+            this.label2.Text = "Total Distance:";
+            // 
+            // lblUnits
+            // 
+            this.lblUnits.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.lblUnits.AutoSize = true;
+            this.lblUnits.Location = new System.Drawing.Point(100, 270);
+            this.lblUnits.Name = "lblUnits";
+            this.lblUnits.Size = new System.Drawing.Size(0, 13);
+            this.lblUnits.TabIndex = 3;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(15, 17);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(34, 13);
+            this.label3.TabIndex = 4;
+            this.label3.Text = "Units:";
+            // 
+            // cmbUnits
+            // 
+            this.cmbUnits.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbUnits.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbUnits.FormattingEnabled = true;
+            this.cmbUnits.Location = new System.Drawing.Point(97, 14);
+            this.cmbUnits.Name = "cmbUnits";
+            this.cmbUnits.Size = new System.Drawing.Size(127, 21);
+            this.cmbUnits.TabIndex = 5;
+            this.cmbUnits.SelectedIndexChanged += new System.EventHandler(this.cmbUnits_SelectedIndexChanged);
+            // 
+            // btnStart
+            // 
+            this.btnStart.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.btnStart.Location = new System.Drawing.Point(18, 325);
+            this.btnStart.Name = "btnStart";
+            this.btnStart.Size = new System.Drawing.Size(82, 23);
+            this.btnStart.TabIndex = 6;
+            this.btnStart.Text = "Start";
+            this.btnStart.UseVisualStyleBackColor = true;
+            this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.groupBox1.Controls.Add(this.lstSegments);
+            this.groupBox1.Location = new System.Drawing.Point(15, 41);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(212, 211);
+            this.groupBox1.TabIndex = 7;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Segments";
+            // 
+            // MgLineMeasureControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.groupBox1);
+            this.Controls.Add(this.btnStart);
+            this.Controls.Add(this.cmbUnits);
+            this.Controls.Add(this.label3);
+            this.Controls.Add(this.lblUnits);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.label1);
+            this.Name = "MgLineMeasureControl";
+            this.Size = new System.Drawing.Size(247, 360);
+            this.groupBox1.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.ListBox lstSegments;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label lblUnits;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.ComboBox cmbUnits;
+        private System.Windows.Forms.Button btnStart;
+        private System.Windows.Forms.GroupBox groupBox1;
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OSGeo.MapGuide.Viewer
+{
+    internal partial class MgLineMeasureControlImpl : MgControlImpl
+    {
+        private IMapViewer _viewer;
+        private MgCoordinateSystem _mapCs;
+        private BindingList<MeasuredLineSegment> _segments;
+
+        public MgLineMeasureControlImpl(IMapViewer viewer, MeasurementUnit preferredUnit)
+        {
+            InitializeComponent();
+            this.Title = Properties.Resources.TitleMeasure;
+            _viewer = viewer;
+            _segments = new BindingList<MeasuredLineSegment>();
+            cmbUnits.DataSource = Enum.GetValues(typeof(MeasurementUnit));
+            cmbUnits.SelectedItem = preferredUnit;
+            lstSegments.DataSource = _segments;
+            _mapCs = _viewer.GetProvider().GetMapCoordinateSystem();
+        }
+
+        private void btnStart_Click(object sender, EventArgs e)
+        {
+            btnStart.Enabled = false;
+            _segments.Clear();
+            _viewer.DigitizeLineString((coordinates) => //Completed
+            {
+                btnStart.Enabled = true;
+            }, (x1, y1, x2, y2) => //Segment completed
+            {
+                double dist = 0.0;
+                if (_mapCs.GetType() == MgCoordinateSystemType.Geographic)
+                    dist = _mapCs.MeasureGreatCircleDistance(x1, y1, x2, y2);
+                else
+                    dist = _mapCs.MeasureEuclideanDistance(x1, y1, x2, y2);
+
+                //Convert this distance to meters
+                dist = _mapCs.ConvertCoordinateSystemUnitsToMeters(dist);
+                //Add to list of line segments
+                _segments.Add(new MeasuredLineSegment() { MapDistanceMeters = dist, Units = (MeasurementUnit)cmbUnits.SelectedItem });
+
+                lblUnits.Text = TotalUnits(_segments).ToString();
+            });
+        }
+
+        private static double TotalUnits(IEnumerable<MeasuredLineSegment> segments)
+        {
+            double total = 0.0;
+            foreach (var seg in segments)
+            {
+                total += seg.DisplayUnits;
+            }
+            return total;
+        }
+
+        private void cmbUnits_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            //Update segments units, then total
+            foreach (var seg in _segments)
+            {
+                seg.Units = (MeasurementUnit)cmbUnits.SelectedItem;
+            }
+            lblUnits.Text = TotalUnits(_segments).ToString(); 
+        }
+    }
+
+    public enum MeasurementUnit
+    {
+        Feet,
+        Meters,
+        Kilometers,
+        Miles
+    }
+
+    public class MeasuredLineSegment : INotifyPropertyChanged
+    {
+        public double MapDistanceMeters { get; set; }
+
+        private MeasurementUnit _units;
+
+        public MeasurementUnit Units
+        {
+            get { return _units; }
+            set 
+            {
+                if (!value.Equals(_units))
+                {
+                    _units = value;
+                    var h = this.PropertyChanged;
+                    if (h != null) 
+                    {
+                        h(this, new PropertyChangedEventArgs("Units"));
+                        h(this, new PropertyChangedEventArgs("DisplayUnits"));
+                    }
+                }
+            }
+        }
+
+        const double M_TO_KM = 0.001;
+        const double M_TO_MI = 0.000621371192;
+
+        public double DisplayUnits
+        {
+            get
+            {
+                var dist = this.MapDistanceMeters;
+                switch (this.Units)
+                {
+                    case MeasurementUnit.Kilometers:
+                        dist *= M_TO_KM;
+                        break;
+                    case MeasurementUnit.Miles:
+                        dist *= M_TO_MI;
+                        break;
+                }
+                return dist;
+            }
+        }
+
+        public override string ToString()
+        {
+            return string.Format("{0} {1}", this.DisplayUnits, this.Units);
+        }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.resx	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -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

Added: branches/2.4/MgDev/Desktop/MapViewer/MgMeasureControl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgMeasureControl.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgMeasureControl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.ComponentModel;
+
+namespace OSGeo.MapGuide.Viewer
+{
+    /// <summary>
+    /// A generic component for measuring
+    /// </summary>
+    [ToolboxItem(true)]
+    public class MgMeasureControl : MgViewerComponent
+    {
+        public MgMeasureControl()
+        {
+            this.Icon = Properties.Resources.measure;
+            this.Label = Properties.Resources.TitleMeasure;
+            this.MeasureMode = MeasureMode.Line;
+            this.PreferredUnits = MeasurementUnit.Meters;
+        }
+
+        protected override MgControlImpl CreateControlImpl()
+        {
+            switch (_measureMode)
+            {
+                case MeasureMode.Line:
+                    return new MgLineMeasureControlImpl(this.Viewer, this.PreferredUnits);
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        [Category("MapGuide Component Properties")]
+        [Description("The default units to measure in")]
+        [DefaultValue(MeasurementUnit.Meters)]
+        public MeasurementUnit PreferredUnits
+        {
+            get;
+            set;
+        }
+
+        private MeasureMode _measureMode;
+
+        [Category("MapGuide Component Properties")]
+        [DefaultValue(MeasureMode.Line)]
+        [Browsable(true)]
+        [Description("The mode of measurement")]
+        public MeasureMode MeasureMode
+        {
+            get { return _measureMode; }
+            set 
+            {
+                if (value == MeasureMode.Area)
+                    throw new NotImplementedException("This mode is not yet implemented");
+                _measureMode = value; 
+            }
+        }
+    }
+
+    /// <summary>
+    /// Defines the valid types of measurements that can be done by the <see cref="T:OSGeo.MapGuide.Viewer.MgMeasureControl"/> component
+    /// </summary>
+    public enum MeasureMode
+    {
+        /// <summary>
+        /// Measure distance by tracing 1 or more line segments
+        /// </summary>
+        Line,
+        /// <summary>
+        /// Measure area by tracing a polygon
+        /// </summary>
+        Area
+    }
+}

Deleted: branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.Designer.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,329 +0,0 @@
-namespace OSGeo.MapGuide.Viewer
-{
-    partial class MgQueryControl
-    {
-        /// <summary> 
-        /// Required designer variable.
-        /// </summary>
-        private System.ComponentModel.IContainer components = null;
-
-        /// <summary> 
-        /// Clean up any resources being used.
-        /// </summary>
-        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Component Designer generated code
-
-        /// <summary> 
-        /// Required method for Designer support - do not modify 
-        /// the contents of this method with the code editor.
-        /// </summary>
-        private void InitializeComponent()
-        {
-            this.groupBox1 = new System.Windows.Forms.GroupBox();
-            this.label1 = new System.Windows.Forms.Label();
-            this.cmbLayer = new System.Windows.Forms.ComboBox();
-            this.groupBox2 = new System.Windows.Forms.GroupBox();
-            this.txtValue = new System.Windows.Forms.TextBox();
-            this.label4 = new System.Windows.Forms.Label();
-            this.cmbOperator = new System.Windows.Forms.ComboBox();
-            this.label3 = new System.Windows.Forms.Label();
-            this.cmbProperty = new System.Windows.Forms.ComboBox();
-            this.label2 = new System.Windows.Forms.Label();
-            this.chkPropFilterEnabled = new System.Windows.Forms.CheckBox();
-            this.groupBox3 = new System.Windows.Forms.GroupBox();
-            this.spatialFilterButtonPanel = new System.Windows.Forms.FlowLayoutPanel();
-            this.btnRectangle = new System.Windows.Forms.Button();
-            this.btnPolygon = new System.Windows.Forms.Button();
-            this.btnClear = new System.Windows.Forms.Button();
-            this.chkSpatialFilter = new System.Windows.Forms.CheckBox();
-            this.btnExecute = new System.Windows.Forms.Button();
-            this.label5 = new System.Windows.Forms.Label();
-            this.numResults = new System.Windows.Forms.NumericUpDown();
-            this.groupBox1.SuspendLayout();
-            this.groupBox2.SuspendLayout();
-            this.groupBox3.SuspendLayout();
-            this.spatialFilterButtonPanel.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numResults)).BeginInit();
-            this.SuspendLayout();
-            // 
-            // groupBox1
-            // 
-            this.groupBox1.Controls.Add(this.label1);
-            this.groupBox1.Controls.Add(this.cmbLayer);
-            this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top;
-            this.groupBox1.Location = new System.Drawing.Point(0, 0);
-            this.groupBox1.Name = "groupBox1";
-            this.groupBox1.Size = new System.Drawing.Size(266, 82);
-            this.groupBox1.TabIndex = 0;
-            this.groupBox1.TabStop = false;
-            this.groupBox1.Text = "Layer";
-            // 
-            // label1
-            // 
-            this.label1.AutoSize = true;
-            this.label1.Location = new System.Drawing.Point(16, 20);
-            this.label1.Name = "label1";
-            this.label1.Size = new System.Drawing.Size(75, 13);
-            this.label1.TabIndex = 1;
-            this.label1.Text = "Select a Layer";
-            // 
-            // cmbLayer
-            // 
-            this.cmbLayer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.cmbLayer.DisplayMember = "Name";
-            this.cmbLayer.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cmbLayer.FormattingEnabled = true;
-            this.cmbLayer.Location = new System.Drawing.Point(16, 45);
-            this.cmbLayer.Name = "cmbLayer";
-            this.cmbLayer.Size = new System.Drawing.Size(231, 21);
-            this.cmbLayer.TabIndex = 0;
-            this.cmbLayer.SelectedIndexChanged += new System.EventHandler(this.cmbLayer_SelectedIndexChanged);
-            // 
-            // groupBox2
-            // 
-            this.groupBox2.Controls.Add(this.txtValue);
-            this.groupBox2.Controls.Add(this.label4);
-            this.groupBox2.Controls.Add(this.cmbOperator);
-            this.groupBox2.Controls.Add(this.label3);
-            this.groupBox2.Controls.Add(this.cmbProperty);
-            this.groupBox2.Controls.Add(this.label2);
-            this.groupBox2.Controls.Add(this.chkPropFilterEnabled);
-            this.groupBox2.Dock = System.Windows.Forms.DockStyle.Top;
-            this.groupBox2.Location = new System.Drawing.Point(0, 82);
-            this.groupBox2.Name = "groupBox2";
-            this.groupBox2.Size = new System.Drawing.Size(266, 187);
-            this.groupBox2.TabIndex = 1;
-            this.groupBox2.TabStop = false;
-            this.groupBox2.Text = "Property Filter";
-            // 
-            // txtValue
-            // 
-            this.txtValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.txtValue.Location = new System.Drawing.Point(16, 145);
-            this.txtValue.Name = "txtValue";
-            this.txtValue.Size = new System.Drawing.Size(231, 20);
-            this.txtValue.TabIndex = 6;
-            // 
-            // label4
-            // 
-            this.label4.AutoSize = true;
-            this.label4.Location = new System.Drawing.Point(16, 129);
-            this.label4.Name = "label4";
-            this.label4.Size = new System.Drawing.Size(34, 13);
-            this.label4.TabIndex = 5;
-            this.label4.Text = "Value";
-            // 
-            // cmbOperator
-            // 
-            this.cmbOperator.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.cmbOperator.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cmbOperator.FormattingEnabled = true;
-            this.cmbOperator.Location = new System.Drawing.Point(16, 101);
-            this.cmbOperator.Name = "cmbOperator";
-            this.cmbOperator.Size = new System.Drawing.Size(231, 21);
-            this.cmbOperator.TabIndex = 4;
-            // 
-            // label3
-            // 
-            this.label3.AutoSize = true;
-            this.label3.Location = new System.Drawing.Point(16, 85);
-            this.label3.Name = "label3";
-            this.label3.Size = new System.Drawing.Size(48, 13);
-            this.label3.TabIndex = 3;
-            this.label3.Text = "Operator";
-            // 
-            // cmbProperty
-            // 
-            this.cmbProperty.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.cmbProperty.DisplayMember = "Name";
-            this.cmbProperty.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cmbProperty.FormattingEnabled = true;
-            this.cmbProperty.Location = new System.Drawing.Point(16, 60);
-            this.cmbProperty.Name = "cmbProperty";
-            this.cmbProperty.Size = new System.Drawing.Size(231, 21);
-            this.cmbProperty.TabIndex = 2;
-            // 
-            // label2
-            // 
-            this.label2.AutoSize = true;
-            this.label2.Location = new System.Drawing.Point(16, 44);
-            this.label2.Name = "label2";
-            this.label2.Size = new System.Drawing.Size(46, 13);
-            this.label2.TabIndex = 1;
-            this.label2.Text = "Property";
-            // 
-            // chkPropFilterEnabled
-            // 
-            this.chkPropFilterEnabled.AutoSize = true;
-            this.chkPropFilterEnabled.Location = new System.Drawing.Point(19, 20);
-            this.chkPropFilterEnabled.Name = "chkPropFilterEnabled";
-            this.chkPropFilterEnabled.Size = new System.Drawing.Size(65, 17);
-            this.chkPropFilterEnabled.TabIndex = 0;
-            this.chkPropFilterEnabled.Text = "Enabled";
-            this.chkPropFilterEnabled.UseVisualStyleBackColor = true;
-            // 
-            // groupBox3
-            // 
-            this.groupBox3.Controls.Add(this.spatialFilterButtonPanel);
-            this.groupBox3.Controls.Add(this.chkSpatialFilter);
-            this.groupBox3.Dock = System.Windows.Forms.DockStyle.Top;
-            this.groupBox3.Location = new System.Drawing.Point(0, 269);
-            this.groupBox3.Name = "groupBox3";
-            this.groupBox3.Size = new System.Drawing.Size(266, 119);
-            this.groupBox3.TabIndex = 2;
-            this.groupBox3.TabStop = false;
-            this.groupBox3.Text = "Spatial Filter";
-            // 
-            // spatialFilterButtonPanel
-            // 
-            this.spatialFilterButtonPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.spatialFilterButtonPanel.Controls.Add(this.btnRectangle);
-            this.spatialFilterButtonPanel.Controls.Add(this.btnPolygon);
-            this.spatialFilterButtonPanel.Controls.Add(this.btnClear);
-            this.spatialFilterButtonPanel.Location = new System.Drawing.Point(19, 43);
-            this.spatialFilterButtonPanel.Name = "spatialFilterButtonPanel";
-            this.spatialFilterButtonPanel.Size = new System.Drawing.Size(228, 60);
-            this.spatialFilterButtonPanel.TabIndex = 2;
-            // 
-            // btnRectangle
-            // 
-            this.btnRectangle.Location = new System.Drawing.Point(3, 3);
-            this.btnRectangle.Name = "btnRectangle";
-            this.btnRectangle.Size = new System.Drawing.Size(75, 23);
-            this.btnRectangle.TabIndex = 2;
-            this.btnRectangle.Text = "Rectangle";
-            this.btnRectangle.UseVisualStyleBackColor = true;
-            this.btnRectangle.Click += new System.EventHandler(this.btnRectangle_Click);
-            // 
-            // btnPolygon
-            // 
-            this.btnPolygon.Location = new System.Drawing.Point(84, 3);
-            this.btnPolygon.Name = "btnPolygon";
-            this.btnPolygon.Size = new System.Drawing.Size(75, 23);
-            this.btnPolygon.TabIndex = 3;
-            this.btnPolygon.Text = "Polygon";
-            this.btnPolygon.UseVisualStyleBackColor = true;
-            this.btnPolygon.Click += new System.EventHandler(this.btnPolygon_Click);
-            // 
-            // btnClear
-            // 
-            this.btnClear.Location = new System.Drawing.Point(3, 32);
-            this.btnClear.Name = "btnClear";
-            this.btnClear.Size = new System.Drawing.Size(75, 23);
-            this.btnClear.TabIndex = 4;
-            this.btnClear.Text = "Clear";
-            this.btnClear.UseVisualStyleBackColor = true;
-            this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
-            // 
-            // chkSpatialFilter
-            // 
-            this.chkSpatialFilter.AutoSize = true;
-            this.chkSpatialFilter.Location = new System.Drawing.Point(19, 19);
-            this.chkSpatialFilter.Name = "chkSpatialFilter";
-            this.chkSpatialFilter.Size = new System.Drawing.Size(65, 17);
-            this.chkSpatialFilter.TabIndex = 1;
-            this.chkSpatialFilter.Text = "Enabled";
-            this.chkSpatialFilter.UseVisualStyleBackColor = true;
-            // 
-            // btnExecute
-            // 
-            this.btnExecute.Location = new System.Drawing.Point(16, 395);
-            this.btnExecute.Name = "btnExecute";
-            this.btnExecute.Size = new System.Drawing.Size(75, 23);
-            this.btnExecute.TabIndex = 3;
-            this.btnExecute.Text = "Execute";
-            this.btnExecute.UseVisualStyleBackColor = true;
-            this.btnExecute.Click += new System.EventHandler(this.btnExecute_Click);
-            // 
-            // label5
-            // 
-            this.label5.AutoSize = true;
-            this.label5.Location = new System.Drawing.Point(97, 400);
-            this.label5.Name = "label5";
-            this.label5.Size = new System.Drawing.Size(42, 13);
-            this.label5.TabIndex = 4;
-            this.label5.Text = "Results";
-            // 
-            // numResults
-            // 
-            this.numResults.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.numResults.Location = new System.Drawing.Point(143, 398);
-            this.numResults.Maximum = new decimal(new int[] {
-            10000,
-            0,
-            0,
-            0});
-            this.numResults.Name = "numResults";
-            this.numResults.Size = new System.Drawing.Size(104, 20);
-            this.numResults.TabIndex = 5;
-            this.numResults.Value = new decimal(new int[] {
-            100,
-            0,
-            0,
-            0});
-            // 
-            // MgQueryControl
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.Controls.Add(this.numResults);
-            this.Controls.Add(this.label5);
-            this.Controls.Add(this.btnExecute);
-            this.Controls.Add(this.groupBox3);
-            this.Controls.Add(this.groupBox2);
-            this.Controls.Add(this.groupBox1);
-            this.Name = "MgQueryControl";
-            this.Size = new System.Drawing.Size(266, 431);
-            this.groupBox1.ResumeLayout(false);
-            this.groupBox1.PerformLayout();
-            this.groupBox2.ResumeLayout(false);
-            this.groupBox2.PerformLayout();
-            this.groupBox3.ResumeLayout(false);
-            this.groupBox3.PerformLayout();
-            this.spatialFilterButtonPanel.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.numResults)).EndInit();
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.GroupBox groupBox1;
-        private System.Windows.Forms.Label label1;
-        private System.Windows.Forms.ComboBox cmbLayer;
-        private System.Windows.Forms.GroupBox groupBox2;
-        private System.Windows.Forms.CheckBox chkPropFilterEnabled;
-        private System.Windows.Forms.GroupBox groupBox3;
-        private System.Windows.Forms.CheckBox chkSpatialFilter;
-        private System.Windows.Forms.TextBox txtValue;
-        private System.Windows.Forms.Label label4;
-        private System.Windows.Forms.ComboBox cmbOperator;
-        private System.Windows.Forms.Label label3;
-        private System.Windows.Forms.ComboBox cmbProperty;
-        private System.Windows.Forms.Label label2;
-        private System.Windows.Forms.FlowLayoutPanel spatialFilterButtonPanel;
-        private System.Windows.Forms.Button btnRectangle;
-        private System.Windows.Forms.Button btnPolygon;
-        private System.Windows.Forms.Button btnClear;
-        private System.Windows.Forms.Button btnExecute;
-        private System.Windows.Forms.Label label5;
-        private System.Windows.Forms.NumericUpDown numResults;
-    }
-}

Modified: branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,204 +1,35 @@
 using System;
 using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
 using System.Text;
-using System.Windows.Forms;
+using System.ComponentModel;
 
 namespace OSGeo.MapGuide.Viewer
 {
-    public partial class MgQueryControl : UserControl
+    /// <summary>
+    /// A generic feature query component
+    /// </summary>
+    [ToolboxItem(true)]
+    public class MgQueryControl : MgViewerComponent
     {
-        private IMapViewer _viewer;
-        private MgWktReaderWriter _wktRw;
-        private MgGeometryFactory _geomFact;
-
-        private BindingList<MgDataPropertyDefinition> _properties;
-        private BindingList<MgLayerBase> _layers;
-
-        public MgQueryControl(IMapViewer viewer)
+        public MgQueryControl()
         {
-            InitializeComponent();
-            this.Disposed += new EventHandler(OnDisposed);
-            _viewer = viewer;
-            _properties = new BindingList<MgDataPropertyDefinition>();
-            _layers = new BindingList<MgLayerBase>();
-            _wktRw = new MgWktReaderWriter();
-            _geomFact = new MgGeometryFactory();
-
-            cmbOperator.DataSource = Enum.GetValues(typeof(QueryOperator));
-            cmbLayer.DataSource = _layers;
-            cmbProperty.DataSource = _properties;
-
-            cmbOperator.SelectedIndex = 0;
-            
-            var map = viewer.GetMap();
-            var layers = map.GetLayers();
-            for (var i = 0; i < layers.GetCount(); i++)
-            {
-                _layers.Add(layers.GetItem(i));
-            }
-            cmbLayer.SelectedIndex = 0;
+            this.Icon = Properties.Resources.search;
+            this.Label = Properties.Resources.TitleQuery;
         }
 
-        void OnDisposed(object sender, EventArgs e)
+        protected override MgControlImpl CreateControlImpl()
         {
-            _properties.Clear();
-            _layers.Clear();
-            _wktRw.Dispose();
-            _wktRw = null;
-            _geomFact.Dispose();
-            _geomFact = null;
+            return new MgQueryControlImpl(this.Viewer);
         }
 
-        private void cmbLayer_SelectedIndexChanged(object sender, EventArgs e)
+        protected override void SubscribeViewerEvents(IMapViewer viewer)
         {
-            var layer = cmbLayer.SelectedItem as MgLayerBase;
-            if (layer != null)
-            {
-                var cls = layer.GetClassDefinition();
-                var clsProps = cls.GetProperties();
-                _properties.Clear();
-                for (var i = 0; i < clsProps.GetCount(); i++)
-                {
-                    var prop = clsProps.GetItem(i);
-                    if (prop.GetPropertyType() == MgFeaturePropertyType.DataProperty)
-                    {
-                        _properties.Add((MgDataPropertyDefinition)prop);
-                    }
-                }
-                cmbProperty.SelectedIndex = 0;
-            }
+            base.SubscribeViewerEvents(viewer);
         }
 
-        static string MakeWktPolygon(double x1, double y1, double x2, double y2)
+        protected override void UnsubscribeViewerEvents(IMapViewer viewer)
         {
-            return "POLYGON((" + x1 + " " + y1 + ", " + x2 + " " + y1 + ", " + x2 + " " + y2 + ", " + x1 + " " + y2 + ", " + x1 + " " + y1 + "))";
+            base.UnsubscribeViewerEvents(viewer);
         }
-
-        private MgGeometry _filterGeometry;
-
-        private void btnRectangle_Click(object sender, EventArgs e)
-        {
-            _viewer.DigitizeRectangle((llx, lly, urx, ury) =>
-            {
-                ClearFilterGeometry();
-                _filterGeometry = _wktRw.Read(MakeWktPolygon(llx, lly, urx, ury));
-            });
-        }
-
-        private void btnPolygon_Click(object sender, EventArgs e)
-        {
-            _viewer.DigitizePolygon((coordinates) =>
-            {
-                ClearFilterGeometry();
-                MgCoordinateCollection coords = new MgCoordinateCollection();
-                for (int i = 0; i < coordinates.GetLength(0); i++)
-                {
-                    coords.Add(_geomFact.CreateCoordinateXY(coordinates[i, 0], coordinates[i, 1]));
-                }
-                coords.Add(_geomFact.CreateCoordinateXY(coordinates[0, 0], coordinates[0, 1]));
-                MgLinearRing ring = _geomFact.CreateLinearRing(coords);
-                _filterGeometry = _geomFact.CreatePolygon(ring, null);
-            });
-        }
-
-        private void ClearFilterGeometry()
-        {
-            if (_filterGeometry != null)
-                _filterGeometry.Dispose();
-        }
-
-        private void btnClear_Click(object sender, EventArgs e)
-        {
-            ClearFilterGeometry();
-        }
-
-        private void btnExecute_Click(object sender, EventArgs e)
-        {
-            var query = new MgFeatureQueryOptions();
-            var provider = _viewer.GetProvider();
-            var layer = (MgLayerBase)cmbLayer.SelectedItem;
-            var prop = (MgDataPropertyDefinition)cmbProperty.SelectedItem;
-            var op = (QueryOperator)cmbOperator.SelectedItem;
-
-            if (chkPropFilterEnabled.Checked)
-                query.SetFilter(FilterToString(prop, op, txtValue.Text));
-            if (chkSpatialFilter.Checked)
-                query.SetSpatialFilter(layer.GetFeatureGeometryName(), _filterGeometry, MgFeatureSpatialOperations.Intersects);
-
-            var reader = layer.SelectFeatures(query);
-            new MgQueryResultsDialog(_viewer, layer, reader, Convert.ToInt32(numResults.Value)).Show();
-        }
-
-        static string FilterToString(MgDataPropertyDefinition prop, QueryOperator op, string value)
-        {
-            var sb = new StringBuilder();
-
-            sb.Append(prop.Name + " ");
-
-            switch (op)
-            {
-                case QueryOperator.EqualTo:
-                    sb.Append(" = ");
-                    break;
-                case QueryOperator.GreaterThan:
-                    sb.Append(" > ");
-                    break;
-                case QueryOperator.GreaterThanOrEqualTo:
-                    sb.Append(" >= ");
-                    break;
-                case QueryOperator.In:
-                    sb.Append(" IN ");
-                    break;
-                case QueryOperator.LessThan:
-                    sb.Append(" < ");
-                    break;
-                case QueryOperator.LessThanOrEqualTo:
-                    sb.Append(" <= ");
-                    break;
-                case QueryOperator.Like:
-                    sb.Append(" LIKE ");
-                    break;
-                case QueryOperator.NotEqualTo:
-                    sb.Append(" <> ");
-                    break;
-            }
-
-            if (op == QueryOperator.In)
-            {
-                sb.Append("(");
-                sb.Append(value);
-                sb.Append(")");
-            }
-            else
-            {
-                if (prop.DataType == MgPropertyType.String)
-                {
-                    sb.Append("'");
-                    sb.Append(value);
-                    sb.Append("'");
-                }
-                else
-                {
-                    sb.Append(value);
-                }
-            }
-
-            return sb.ToString();
-        }
     }
-
-    public enum QueryOperator
-    {
-        EqualTo,
-        NotEqualTo,
-        GreaterThan,
-        GreaterThanOrEqualTo,
-        LessThan,
-        LessThanOrEqualTo,
-        Like,
-        In
-    }
 }

Deleted: branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.resx	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgQueryControl.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,120 +0,0 @@
-<?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

Added: branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.Designer.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,329 @@
+namespace OSGeo.MapGuide.Viewer
+{
+    partial class MgQueryControlImpl
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.cmbLayer = new System.Windows.Forms.ComboBox();
+            this.groupBox2 = new System.Windows.Forms.GroupBox();
+            this.txtValue = new System.Windows.Forms.TextBox();
+            this.label4 = new System.Windows.Forms.Label();
+            this.cmbOperator = new System.Windows.Forms.ComboBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.cmbProperty = new System.Windows.Forms.ComboBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.chkPropFilterEnabled = new System.Windows.Forms.CheckBox();
+            this.groupBox3 = new System.Windows.Forms.GroupBox();
+            this.spatialFilterButtonPanel = new System.Windows.Forms.FlowLayoutPanel();
+            this.btnRectangle = new System.Windows.Forms.Button();
+            this.btnPolygon = new System.Windows.Forms.Button();
+            this.btnClear = new System.Windows.Forms.Button();
+            this.chkSpatialFilter = new System.Windows.Forms.CheckBox();
+            this.btnExecute = new System.Windows.Forms.Button();
+            this.label5 = new System.Windows.Forms.Label();
+            this.numResults = new System.Windows.Forms.NumericUpDown();
+            this.groupBox1.SuspendLayout();
+            this.groupBox2.SuspendLayout();
+            this.groupBox3.SuspendLayout();
+            this.spatialFilterButtonPanel.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numResults)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Controls.Add(this.cmbLayer);
+            this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top;
+            this.groupBox1.Location = new System.Drawing.Point(0, 0);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(266, 82);
+            this.groupBox1.TabIndex = 0;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Layer";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(16, 20);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(75, 13);
+            this.label1.TabIndex = 1;
+            this.label1.Text = "Select a Layer";
+            // 
+            // cmbLayer
+            // 
+            this.cmbLayer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbLayer.DisplayMember = "Name";
+            this.cmbLayer.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbLayer.FormattingEnabled = true;
+            this.cmbLayer.Location = new System.Drawing.Point(16, 45);
+            this.cmbLayer.Name = "cmbLayer";
+            this.cmbLayer.Size = new System.Drawing.Size(231, 21);
+            this.cmbLayer.TabIndex = 0;
+            this.cmbLayer.SelectedIndexChanged += new System.EventHandler(this.cmbLayer_SelectedIndexChanged);
+            // 
+            // groupBox2
+            // 
+            this.groupBox2.Controls.Add(this.txtValue);
+            this.groupBox2.Controls.Add(this.label4);
+            this.groupBox2.Controls.Add(this.cmbOperator);
+            this.groupBox2.Controls.Add(this.label3);
+            this.groupBox2.Controls.Add(this.cmbProperty);
+            this.groupBox2.Controls.Add(this.label2);
+            this.groupBox2.Controls.Add(this.chkPropFilterEnabled);
+            this.groupBox2.Dock = System.Windows.Forms.DockStyle.Top;
+            this.groupBox2.Location = new System.Drawing.Point(0, 82);
+            this.groupBox2.Name = "groupBox2";
+            this.groupBox2.Size = new System.Drawing.Size(266, 187);
+            this.groupBox2.TabIndex = 1;
+            this.groupBox2.TabStop = false;
+            this.groupBox2.Text = "Property Filter";
+            // 
+            // txtValue
+            // 
+            this.txtValue.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtValue.Location = new System.Drawing.Point(16, 145);
+            this.txtValue.Name = "txtValue";
+            this.txtValue.Size = new System.Drawing.Size(231, 20);
+            this.txtValue.TabIndex = 6;
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(16, 129);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(34, 13);
+            this.label4.TabIndex = 5;
+            this.label4.Text = "Value";
+            // 
+            // cmbOperator
+            // 
+            this.cmbOperator.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbOperator.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbOperator.FormattingEnabled = true;
+            this.cmbOperator.Location = new System.Drawing.Point(16, 101);
+            this.cmbOperator.Name = "cmbOperator";
+            this.cmbOperator.Size = new System.Drawing.Size(231, 21);
+            this.cmbOperator.TabIndex = 4;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(16, 85);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(48, 13);
+            this.label3.TabIndex = 3;
+            this.label3.Text = "Operator";
+            // 
+            // cmbProperty
+            // 
+            this.cmbProperty.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.cmbProperty.DisplayMember = "Name";
+            this.cmbProperty.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cmbProperty.FormattingEnabled = true;
+            this.cmbProperty.Location = new System.Drawing.Point(16, 60);
+            this.cmbProperty.Name = "cmbProperty";
+            this.cmbProperty.Size = new System.Drawing.Size(231, 21);
+            this.cmbProperty.TabIndex = 2;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(16, 44);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(46, 13);
+            this.label2.TabIndex = 1;
+            this.label2.Text = "Property";
+            // 
+            // chkPropFilterEnabled
+            // 
+            this.chkPropFilterEnabled.AutoSize = true;
+            this.chkPropFilterEnabled.Location = new System.Drawing.Point(19, 20);
+            this.chkPropFilterEnabled.Name = "chkPropFilterEnabled";
+            this.chkPropFilterEnabled.Size = new System.Drawing.Size(65, 17);
+            this.chkPropFilterEnabled.TabIndex = 0;
+            this.chkPropFilterEnabled.Text = "Enabled";
+            this.chkPropFilterEnabled.UseVisualStyleBackColor = true;
+            // 
+            // groupBox3
+            // 
+            this.groupBox3.Controls.Add(this.spatialFilterButtonPanel);
+            this.groupBox3.Controls.Add(this.chkSpatialFilter);
+            this.groupBox3.Dock = System.Windows.Forms.DockStyle.Top;
+            this.groupBox3.Location = new System.Drawing.Point(0, 269);
+            this.groupBox3.Name = "groupBox3";
+            this.groupBox3.Size = new System.Drawing.Size(266, 119);
+            this.groupBox3.TabIndex = 2;
+            this.groupBox3.TabStop = false;
+            this.groupBox3.Text = "Spatial Filter";
+            // 
+            // spatialFilterButtonPanel
+            // 
+            this.spatialFilterButtonPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.spatialFilterButtonPanel.Controls.Add(this.btnRectangle);
+            this.spatialFilterButtonPanel.Controls.Add(this.btnPolygon);
+            this.spatialFilterButtonPanel.Controls.Add(this.btnClear);
+            this.spatialFilterButtonPanel.Location = new System.Drawing.Point(19, 43);
+            this.spatialFilterButtonPanel.Name = "spatialFilterButtonPanel";
+            this.spatialFilterButtonPanel.Size = new System.Drawing.Size(228, 60);
+            this.spatialFilterButtonPanel.TabIndex = 2;
+            // 
+            // btnRectangle
+            // 
+            this.btnRectangle.Location = new System.Drawing.Point(3, 3);
+            this.btnRectangle.Name = "btnRectangle";
+            this.btnRectangle.Size = new System.Drawing.Size(75, 23);
+            this.btnRectangle.TabIndex = 2;
+            this.btnRectangle.Text = "Rectangle";
+            this.btnRectangle.UseVisualStyleBackColor = true;
+            this.btnRectangle.Click += new System.EventHandler(this.btnRectangle_Click);
+            // 
+            // btnPolygon
+            // 
+            this.btnPolygon.Location = new System.Drawing.Point(84, 3);
+            this.btnPolygon.Name = "btnPolygon";
+            this.btnPolygon.Size = new System.Drawing.Size(75, 23);
+            this.btnPolygon.TabIndex = 3;
+            this.btnPolygon.Text = "Polygon";
+            this.btnPolygon.UseVisualStyleBackColor = true;
+            this.btnPolygon.Click += new System.EventHandler(this.btnPolygon_Click);
+            // 
+            // btnClear
+            // 
+            this.btnClear.Location = new System.Drawing.Point(3, 32);
+            this.btnClear.Name = "btnClear";
+            this.btnClear.Size = new System.Drawing.Size(75, 23);
+            this.btnClear.TabIndex = 4;
+            this.btnClear.Text = "Clear";
+            this.btnClear.UseVisualStyleBackColor = true;
+            this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
+            // 
+            // chkSpatialFilter
+            // 
+            this.chkSpatialFilter.AutoSize = true;
+            this.chkSpatialFilter.Location = new System.Drawing.Point(19, 19);
+            this.chkSpatialFilter.Name = "chkSpatialFilter";
+            this.chkSpatialFilter.Size = new System.Drawing.Size(65, 17);
+            this.chkSpatialFilter.TabIndex = 1;
+            this.chkSpatialFilter.Text = "Enabled";
+            this.chkSpatialFilter.UseVisualStyleBackColor = true;
+            // 
+            // btnExecute
+            // 
+            this.btnExecute.Location = new System.Drawing.Point(16, 395);
+            this.btnExecute.Name = "btnExecute";
+            this.btnExecute.Size = new System.Drawing.Size(75, 23);
+            this.btnExecute.TabIndex = 3;
+            this.btnExecute.Text = "Execute";
+            this.btnExecute.UseVisualStyleBackColor = true;
+            this.btnExecute.Click += new System.EventHandler(this.btnExecute_Click);
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(97, 400);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(42, 13);
+            this.label5.TabIndex = 4;
+            this.label5.Text = "Results";
+            // 
+            // numResults
+            // 
+            this.numResults.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.numResults.Location = new System.Drawing.Point(143, 398);
+            this.numResults.Maximum = new decimal(new int[] {
+            10000,
+            0,
+            0,
+            0});
+            this.numResults.Name = "numResults";
+            this.numResults.Size = new System.Drawing.Size(104, 20);
+            this.numResults.TabIndex = 5;
+            this.numResults.Value = new decimal(new int[] {
+            100,
+            0,
+            0,
+            0});
+            // 
+            // MgQueryControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.numResults);
+            this.Controls.Add(this.label5);
+            this.Controls.Add(this.btnExecute);
+            this.Controls.Add(this.groupBox3);
+            this.Controls.Add(this.groupBox2);
+            this.Controls.Add(this.groupBox1);
+            this.Name = "MgQueryControl";
+            this.Size = new System.Drawing.Size(266, 431);
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.groupBox2.ResumeLayout(false);
+            this.groupBox2.PerformLayout();
+            this.groupBox3.ResumeLayout(false);
+            this.groupBox3.PerformLayout();
+            this.spatialFilterButtonPanel.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.numResults)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.ComboBox cmbLayer;
+        private System.Windows.Forms.GroupBox groupBox2;
+        private System.Windows.Forms.CheckBox chkPropFilterEnabled;
+        private System.Windows.Forms.GroupBox groupBox3;
+        private System.Windows.Forms.CheckBox chkSpatialFilter;
+        private System.Windows.Forms.TextBox txtValue;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.ComboBox cmbOperator;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.ComboBox cmbProperty;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.FlowLayoutPanel spatialFilterButtonPanel;
+        private System.Windows.Forms.Button btnRectangle;
+        private System.Windows.Forms.Button btnPolygon;
+        private System.Windows.Forms.Button btnClear;
+        private System.Windows.Forms.Button btnExecute;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.NumericUpDown numResults;
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -0,0 +1,205 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OSGeo.MapGuide.Viewer
+{
+    internal partial class MgQueryControlImpl : MgControlImpl
+    {
+        private IMapViewer _viewer;
+        private MgWktReaderWriter _wktRw;
+        private MgGeometryFactory _geomFact;
+
+        private BindingList<MgDataPropertyDefinition> _properties;
+        private BindingList<MgLayerBase> _layers;
+
+        public MgQueryControlImpl(IMapViewer viewer)
+        {
+            InitializeComponent();
+            this.Title = Properties.Resources.TitleQuery;
+            this.Disposed += new EventHandler(OnDisposed);
+            _viewer = viewer;
+            _properties = new BindingList<MgDataPropertyDefinition>();
+            _layers = new BindingList<MgLayerBase>();
+            _wktRw = new MgWktReaderWriter();
+            _geomFact = new MgGeometryFactory();
+
+            cmbOperator.DataSource = Enum.GetValues(typeof(QueryOperator));
+            cmbLayer.DataSource = _layers;
+            cmbProperty.DataSource = _properties;
+
+            cmbOperator.SelectedIndex = 0;
+            
+            var map = viewer.GetMap();
+            var layers = map.GetLayers();
+            for (var i = 0; i < layers.GetCount(); i++)
+            {
+                _layers.Add(layers.GetItem(i));
+            }
+            cmbLayer.SelectedIndex = 0;
+        }
+
+        void OnDisposed(object sender, EventArgs e)
+        {
+            _properties.Clear();
+            _layers.Clear();
+            _wktRw.Dispose();
+            _wktRw = null;
+            _geomFact.Dispose();
+            _geomFact = null;
+        }
+
+        private void cmbLayer_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            var layer = cmbLayer.SelectedItem as MgLayerBase;
+            if (layer != null)
+            {
+                var cls = layer.GetClassDefinition();
+                var clsProps = cls.GetProperties();
+                _properties.Clear();
+                for (var i = 0; i < clsProps.GetCount(); i++)
+                {
+                    var prop = clsProps.GetItem(i);
+                    if (prop.GetPropertyType() == MgFeaturePropertyType.DataProperty)
+                    {
+                        _properties.Add((MgDataPropertyDefinition)prop);
+                    }
+                }
+                cmbProperty.SelectedIndex = 0;
+            }
+        }
+
+        static string MakeWktPolygon(double x1, double y1, double x2, double y2)
+        {
+            return "POLYGON((" + x1 + " " + y1 + ", " + x2 + " " + y1 + ", " + x2 + " " + y2 + ", " + x1 + " " + y2 + ", " + x1 + " " + y1 + "))";
+        }
+
+        private MgGeometry _filterGeometry;
+
+        private void btnRectangle_Click(object sender, EventArgs e)
+        {
+            _viewer.DigitizeRectangle((llx, lly, urx, ury) =>
+            {
+                ClearFilterGeometry();
+                _filterGeometry = _wktRw.Read(MakeWktPolygon(llx, lly, urx, ury));
+            });
+        }
+
+        private void btnPolygon_Click(object sender, EventArgs e)
+        {
+            _viewer.DigitizePolygon((coordinates) =>
+            {
+                ClearFilterGeometry();
+                MgCoordinateCollection coords = new MgCoordinateCollection();
+                for (int i = 0; i < coordinates.GetLength(0); i++)
+                {
+                    coords.Add(_geomFact.CreateCoordinateXY(coordinates[i, 0], coordinates[i, 1]));
+                }
+                coords.Add(_geomFact.CreateCoordinateXY(coordinates[0, 0], coordinates[0, 1]));
+                MgLinearRing ring = _geomFact.CreateLinearRing(coords);
+                _filterGeometry = _geomFact.CreatePolygon(ring, null);
+            });
+        }
+
+        private void ClearFilterGeometry()
+        {
+            if (_filterGeometry != null)
+                _filterGeometry.Dispose();
+        }
+
+        private void btnClear_Click(object sender, EventArgs e)
+        {
+            ClearFilterGeometry();
+        }
+
+        private void btnExecute_Click(object sender, EventArgs e)
+        {
+            var query = new MgFeatureQueryOptions();
+            var provider = _viewer.GetProvider();
+            var layer = (MgLayerBase)cmbLayer.SelectedItem;
+            var prop = (MgDataPropertyDefinition)cmbProperty.SelectedItem;
+            var op = (QueryOperator)cmbOperator.SelectedItem;
+
+            if (chkPropFilterEnabled.Checked)
+                query.SetFilter(FilterToString(prop, op, txtValue.Text));
+            if (chkSpatialFilter.Checked)
+                query.SetSpatialFilter(layer.GetFeatureGeometryName(), _filterGeometry, MgFeatureSpatialOperations.Intersects);
+
+            var reader = layer.SelectFeatures(query);
+            new MgQueryResultsDialog(_viewer, layer, reader, Convert.ToInt32(numResults.Value)).Show();
+        }
+
+        static string FilterToString(MgDataPropertyDefinition prop, QueryOperator op, string value)
+        {
+            var sb = new StringBuilder();
+
+            sb.Append(prop.Name + " ");
+
+            switch (op)
+            {
+                case QueryOperator.EqualTo:
+                    sb.Append(" = ");
+                    break;
+                case QueryOperator.GreaterThan:
+                    sb.Append(" > ");
+                    break;
+                case QueryOperator.GreaterThanOrEqualTo:
+                    sb.Append(" >= ");
+                    break;
+                case QueryOperator.In:
+                    sb.Append(" IN ");
+                    break;
+                case QueryOperator.LessThan:
+                    sb.Append(" < ");
+                    break;
+                case QueryOperator.LessThanOrEqualTo:
+                    sb.Append(" <= ");
+                    break;
+                case QueryOperator.Like:
+                    sb.Append(" LIKE ");
+                    break;
+                case QueryOperator.NotEqualTo:
+                    sb.Append(" <> ");
+                    break;
+            }
+
+            if (op == QueryOperator.In)
+            {
+                sb.Append("(");
+                sb.Append(value);
+                sb.Append(")");
+            }
+            else
+            {
+                if (prop.DataType == MgPropertyType.String)
+                {
+                    sb.Append("'");
+                    sb.Append(value);
+                    sb.Append("'");
+                }
+                else
+                {
+                    sb.Append(value);
+                }
+            }
+
+            return sb.ToString();
+        }
+    }
+
+    public enum QueryOperator
+    {
+        EqualTo,
+        NotEqualTo,
+        GreaterThan,
+        GreaterThanOrEqualTo,
+        LessThan,
+        LessThanOrEqualTo,
+        Like,
+        In
+    }
+}

Added: branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.resx	                        (rev 0)
+++ branches/2.4/MgDev/Desktop/MapViewer/MgQueryControlImpl.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -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: branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.Designer.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -1,7 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:4.0.30319.225
+//     Runtime Version:2.0.50727.5420
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -19,7 +19,7 @@
     // class via a tool like ResGen or Visual Studio.
     // To add or remove a member, edit your .ResX file then rerun ResGen
     // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class Resources {
@@ -604,6 +604,33 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Buffer.
+        /// </summary>
+        internal static string TitleBuffer {
+            get {
+                return ResourceManager.GetString("TitleBuffer", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Measure.
+        /// </summary>
+        internal static string TitleMeasure {
+            get {
+                return ResourceManager.GetString("TitleMeasure", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Query.
+        /// </summary>
+        internal static string TitleQuery {
+            get {
+                return ResourceManager.GetString("TitleQuery", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Tooltips are enabled. Click to disable.
         /// </summary>
         internal static string TooltipDisableTooltips {

Modified: branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.resx	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewer/Properties/Resources.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -112,15 +112,15 @@
     <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>
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <data name="TextDigitizePolygon" xml:space="preserve">
     <value>Digitize Polygon</value>
   </data>
-  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
   <data name="layer_shape_polyline" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\layer-shape-polyline.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
@@ -367,4 +367,13 @@
   <data name="AreaLayerDef" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\AreaLayerDef.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
   </data>
+  <data name="TitleBuffer" xml:space="preserve">
+    <value>Buffer</value>
+  </data>
+  <data name="TitleMeasure" xml:space="preserve">
+    <value>Measure</value>
+  </data>
+  <data name="TitleQuery" xml:space="preserve">
+    <value>Query</value>
+  </data>
 </root>
\ No newline at end of file

Modified: branches/2.4/MgDev/Desktop/MapViewerTest/Form1.Designer.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewerTest/Form1.Designer.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewerTest/Form1.Designer.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -43,9 +43,13 @@
             this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.testToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.loadCompactMapViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.showConnectionPoolStatusToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.purgePooledConnectionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.ctxViewer = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.refreshMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.initialViewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStrip1 = new System.Windows.Forms.ToolStrip();
             this.btnDigitizePoint = new System.Windows.Forms.ToolStripButton();
             this.btnDigitizeLine = new System.Windows.Forms.ToolStripButton();
@@ -56,10 +60,8 @@
             this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
             this.btnPlotToDwf = new System.Windows.Forms.ToolStripButton();
             this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
-            this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
-            this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
-            this.toolStripButton3 = new System.Windows.Forms.ToolStripButton();
             this.toolStripButton4 = new System.Windows.Forms.ToolStripButton();
+            this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
             this.splitContainer1 = new System.Windows.Forms.SplitContainer();
             this.splitContainer2 = new System.Windows.Forms.SplitContainer();
             this.legend = new OSGeo.MapGuide.Viewer.MgLegend();
@@ -69,13 +71,25 @@
             this.thisIsALayerContextMenuToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.propertyPane = new OSGeo.MapGuide.Viewer.MgPropertyPane();
             this.viewer = new OSGeo.MapGuide.Viewer.MgMapViewer();
-            this.ctxViewer = new System.Windows.Forms.ContextMenuStrip(this.components);
-            this.refreshMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.initialViewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
             this.toolbar = new OSGeo.MapGuide.Viewer.MgDefaultToolbar();
+            this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
+            this.mgInvokeComponentButton1 = new OSGeo.MapGuide.Viewer.MgInvokeComponentButton();
+            this.mgBufferControl1 = new OSGeo.MapGuide.Viewer.MgBufferControl();
+            this.mgInvokeComponentButton2 = new OSGeo.MapGuide.Viewer.MgInvokeComponentButton();
+            this.mgMeasureControl1 = new OSGeo.MapGuide.Viewer.MgMeasureControl();
+            this.mgInvokeComponentButton3 = new OSGeo.MapGuide.Viewer.MgInvokeComponentButton();
+            this.mgQueryControl1 = new OSGeo.MapGuide.Viewer.MgQueryControl();
+            this.mgInvokeComponentMenuStripItem1 = new OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem();
+            this.mgInvokeComponentMenuStripItem2 = new OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem();
+            this.mgInvokeComponentMenuStripItem3 = new OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem();
+            this.mgInvokeComponentMenuStripItem4 = new OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem();
+            this.mgInvokeComponentMenuStripItem5 = new OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem();
+            this.mgInvokeComponentMenuStripItem6 = new OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem();
+            this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
             this.statusStrip1.SuspendLayout();
             this.menuStrip1.SuspendLayout();
+            this.ctxViewer.SuspendLayout();
             this.toolStrip1.SuspendLayout();
             this.splitContainer1.Panel1.SuspendLayout();
             this.splitContainer1.Panel2.SuspendLayout();
@@ -85,10 +99,10 @@
             this.splitContainer2.SuspendLayout();
             this.ctxGroup.SuspendLayout();
             this.ctxLayer.SuspendLayout();
-            this.ctxViewer.SuspendLayout();
             this.toolStripContainer1.ContentPanel.SuspendLayout();
             this.toolStripContainer1.TopToolStripPanel.SuspendLayout();
             this.toolStripContainer1.SuspendLayout();
+            this.toolbar.SuspendLayout();
             this.SuspendLayout();
             // 
             // statusStrip1
@@ -139,6 +153,7 @@
             this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.fileToolStripMenuItem,
             this.testToolStripMenuItem,
+            this.toolsToolStripMenuItem,
             this.debugToolStripMenuItem});
             this.menuStrip1.Location = new System.Drawing.Point(0, 0);
             this.menuStrip1.Name = "menuStrip1";
@@ -192,6 +207,16 @@
             this.loadCompactMapViewerToolStripMenuItem.Text = "Load Compact Map Viewer";
             this.loadCompactMapViewerToolStripMenuItem.Click += new System.EventHandler(this.loadCompactMapViewerToolStripMenuItem_Click);
             // 
+            // toolsToolStripMenuItem
+            // 
+            this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.mgInvokeComponentMenuStripItem1,
+            this.mgInvokeComponentMenuStripItem2,
+            this.mgInvokeComponentMenuStripItem3});
+            this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
+            this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20);
+            this.toolsToolStripMenuItem.Text = "Tools";
+            // 
             // debugToolStripMenuItem
             // 
             this.debugToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -215,6 +240,32 @@
             this.purgePooledConnectionsToolStripMenuItem.Text = "Purge Pooled Connections";
             this.purgePooledConnectionsToolStripMenuItem.Click += new System.EventHandler(this.purgePooledConnectionsToolStripMenuItem_Click);
             // 
+            // ctxViewer
+            // 
+            this.ctxViewer.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.refreshMapToolStripMenuItem,
+            this.initialViewToolStripMenuItem,
+            this.toolStripSeparator5,
+            this.mgInvokeComponentMenuStripItem4,
+            this.mgInvokeComponentMenuStripItem5,
+            this.mgInvokeComponentMenuStripItem6});
+            this.ctxViewer.Name = "ctxViewer";
+            this.ctxViewer.Size = new System.Drawing.Size(153, 142);
+            // 
+            // refreshMapToolStripMenuItem
+            // 
+            this.refreshMapToolStripMenuItem.Name = "refreshMapToolStripMenuItem";
+            this.refreshMapToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.refreshMapToolStripMenuItem.Text = "Refresh Map";
+            this.refreshMapToolStripMenuItem.Click += new System.EventHandler(this.refreshMapToolStripMenuItem_Click);
+            // 
+            // initialViewToolStripMenuItem
+            // 
+            this.initialViewToolStripMenuItem.Name = "initialViewToolStripMenuItem";
+            this.initialViewToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
+            this.initialViewToolStripMenuItem.Text = "Initial View";
+            this.initialViewToolStripMenuItem.Click += new System.EventHandler(this.initialViewToolStripMenuItem_Click);
+            // 
             // toolStrip1
             // 
             this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None;
@@ -228,10 +279,8 @@
             this.toolStripSeparator1,
             this.btnPlotToDwf,
             this.toolStripSeparator2,
-            this.toolStripButton1,
-            this.toolStripButton2,
-            this.toolStripButton3,
-            this.toolStripButton4});
+            this.toolStripButton4,
+            this.toolStripSeparator3});
             this.toolStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
             this.toolStrip1.Location = new System.Drawing.Point(0, 25);
             this.toolStrip1.Name = "toolStrip1";
@@ -320,33 +369,6 @@
             this.toolStripSeparator2.Name = "toolStripSeparator2";
             this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25);
             // 
-            // toolStripButton1
-            // 
-            this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
-            this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.toolStripButton1.Name = "toolStripButton1";
-            this.toolStripButton1.Size = new System.Drawing.Size(72, 22);
-            this.toolStripButton1.Text = "Measure";
-            this.toolStripButton1.Click += new System.EventHandler(this.toolStripButton1_Click);
-            // 
-            // toolStripButton2
-            // 
-            this.toolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image")));
-            this.toolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.toolStripButton2.Name = "toolStripButton2";
-            this.toolStripButton2.Size = new System.Drawing.Size(59, 22);
-            this.toolStripButton2.Text = "Buffer";
-            this.toolStripButton2.Click += new System.EventHandler(this.toolStripButton2_Click);
-            // 
-            // toolStripButton3
-            // 
-            this.toolStripButton3.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton3.Image")));
-            this.toolStripButton3.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.toolStripButton3.Name = "toolStripButton3";
-            this.toolStripButton3.Size = new System.Drawing.Size(59, 22);
-            this.toolStripButton3.Text = "Query";
-            this.toolStripButton3.Click += new System.EventHandler(this.toolStripButton3_Click);
-            // 
             // toolStripButton4
             // 
             this.toolStripButton4.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton4.Image")));
@@ -357,6 +379,11 @@
             this.toolStripButton4.ToolTipText = "Profile current map view";
             this.toolStripButton4.Click += new System.EventHandler(this.toolStripButton4_Click);
             // 
+            // toolStripSeparator3
+            // 
+            this.toolStripSeparator3.Name = "toolStripSeparator3";
+            this.toolStripSeparator3.Size = new System.Drawing.Size(6, 25);
+            // 
             // splitContainer1
             // 
             this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -455,28 +482,6 @@
             this.viewer.ZoomInFactor = 0.75;
             this.viewer.ZoomOutFactor = 1.35;
             // 
-            // ctxViewer
-            // 
-            this.ctxViewer.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.refreshMapToolStripMenuItem,
-            this.initialViewToolStripMenuItem});
-            this.ctxViewer.Name = "ctxViewer";
-            this.ctxViewer.Size = new System.Drawing.Size(141, 48);
-            // 
-            // refreshMapToolStripMenuItem
-            // 
-            this.refreshMapToolStripMenuItem.Name = "refreshMapToolStripMenuItem";
-            this.refreshMapToolStripMenuItem.Size = new System.Drawing.Size(140, 22);
-            this.refreshMapToolStripMenuItem.Text = "Refresh Map";
-            this.refreshMapToolStripMenuItem.Click += new System.EventHandler(this.refreshMapToolStripMenuItem_Click);
-            // 
-            // initialViewToolStripMenuItem
-            // 
-            this.initialViewToolStripMenuItem.Name = "initialViewToolStripMenuItem";
-            this.initialViewToolStripMenuItem.Size = new System.Drawing.Size(140, 22);
-            this.initialViewToolStripMenuItem.Text = "Initial View";
-            this.initialViewToolStripMenuItem.Click += new System.EventHandler(this.initialViewToolStripMenuItem_Click);
-            // 
             // toolStripContainer1
             // 
             // 
@@ -499,6 +504,11 @@
             // toolbar
             // 
             this.toolbar.Dock = System.Windows.Forms.DockStyle.None;
+            this.toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.toolStripSeparator4,
+            this.mgInvokeComponentButton1,
+            this.mgInvokeComponentButton2,
+            this.mgInvokeComponentButton3});
             this.toolbar.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
             this.toolbar.Location = new System.Drawing.Point(0, 0);
             this.toolbar.Name = "toolbar";
@@ -509,6 +519,115 @@
             this.toolbar.Viewer = null;
             this.toolbar.ZoomOutMode = OSGeo.MapGuide.Viewer.ZoomOutMode.AutoZoom;
             // 
+            // toolStripSeparator4
+            // 
+            this.toolStripSeparator4.Name = "toolStripSeparator4";
+            this.toolStripSeparator4.Size = new System.Drawing.Size(6, 25);
+            // 
+            // mgInvokeComponentButton1
+            // 
+            this.mgInvokeComponentButton1.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentButton1.Image")));
+            this.mgInvokeComponentButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.mgInvokeComponentButton1.Name = "mgInvokeComponentButton1";
+            this.mgInvokeComponentButton1.Size = new System.Drawing.Size(59, 22);
+            this.mgInvokeComponentButton1.TargetComponent = this.mgBufferControl1;
+            this.mgInvokeComponentButton1.Text = "Buffer";
+            // 
+            // mgBufferControl1
+            // 
+            this.mgBufferControl1.Icon = ((System.Drawing.Image)(resources.GetObject("mgBufferControl1.Icon")));
+            this.mgBufferControl1.Label = "Buffer";
+            this.mgBufferControl1.ParentContainer = null;
+            this.mgBufferControl1.ToolTipText = null;
+            this.mgBufferControl1.Viewer = this.viewer;
+            // 
+            // mgInvokeComponentButton2
+            // 
+            this.mgInvokeComponentButton2.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentButton2.Image")));
+            this.mgInvokeComponentButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.mgInvokeComponentButton2.Name = "mgInvokeComponentButton2";
+            this.mgInvokeComponentButton2.Size = new System.Drawing.Size(72, 22);
+            this.mgInvokeComponentButton2.TargetComponent = this.mgMeasureControl1;
+            this.mgInvokeComponentButton2.Text = "Measure";
+            // 
+            // mgMeasureControl1
+            // 
+            this.mgMeasureControl1.Icon = ((System.Drawing.Image)(resources.GetObject("mgMeasureControl1.Icon")));
+            this.mgMeasureControl1.Label = "Measure";
+            this.mgMeasureControl1.ParentContainer = null;
+            this.mgMeasureControl1.ToolTipText = null;
+            this.mgMeasureControl1.Viewer = this.viewer;
+            // 
+            // mgInvokeComponentButton3
+            // 
+            this.mgInvokeComponentButton3.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentButton3.Image")));
+            this.mgInvokeComponentButton3.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.mgInvokeComponentButton3.Name = "mgInvokeComponentButton3";
+            this.mgInvokeComponentButton3.Size = new System.Drawing.Size(59, 22);
+            this.mgInvokeComponentButton3.TargetComponent = this.mgQueryControl1;
+            this.mgInvokeComponentButton3.Text = "Query";
+            // 
+            // mgQueryControl1
+            // 
+            this.mgQueryControl1.Icon = ((System.Drawing.Image)(resources.GetObject("mgQueryControl1.Icon")));
+            this.mgQueryControl1.Label = "Query";
+            this.mgQueryControl1.ParentContainer = null;
+            this.mgQueryControl1.ToolTipText = null;
+            this.mgQueryControl1.Viewer = this.viewer;
+            // 
+            // mgInvokeComponentMenuStripItem1
+            // 
+            this.mgInvokeComponentMenuStripItem1.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentMenuStripItem1.Image")));
+            this.mgInvokeComponentMenuStripItem1.Name = "mgInvokeComponentMenuStripItem1";
+            this.mgInvokeComponentMenuStripItem1.Size = new System.Drawing.Size(152, 22);
+            this.mgInvokeComponentMenuStripItem1.TargetComponent = this.mgBufferControl1;
+            this.mgInvokeComponentMenuStripItem1.Text = "Buffer";
+            // 
+            // mgInvokeComponentMenuStripItem2
+            // 
+            this.mgInvokeComponentMenuStripItem2.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentMenuStripItem2.Image")));
+            this.mgInvokeComponentMenuStripItem2.Name = "mgInvokeComponentMenuStripItem2";
+            this.mgInvokeComponentMenuStripItem2.Size = new System.Drawing.Size(152, 22);
+            this.mgInvokeComponentMenuStripItem2.TargetComponent = this.mgMeasureControl1;
+            this.mgInvokeComponentMenuStripItem2.Text = "Measure";
+            // 
+            // mgInvokeComponentMenuStripItem3
+            // 
+            this.mgInvokeComponentMenuStripItem3.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentMenuStripItem3.Image")));
+            this.mgInvokeComponentMenuStripItem3.Name = "mgInvokeComponentMenuStripItem3";
+            this.mgInvokeComponentMenuStripItem3.Size = new System.Drawing.Size(152, 22);
+            this.mgInvokeComponentMenuStripItem3.TargetComponent = this.mgQueryControl1;
+            this.mgInvokeComponentMenuStripItem3.Text = "Query";
+            // 
+            // mgInvokeComponentMenuStripItem4
+            // 
+            this.mgInvokeComponentMenuStripItem4.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentMenuStripItem4.Image")));
+            this.mgInvokeComponentMenuStripItem4.Name = "mgInvokeComponentMenuStripItem4";
+            this.mgInvokeComponentMenuStripItem4.Size = new System.Drawing.Size(152, 22);
+            this.mgInvokeComponentMenuStripItem4.TargetComponent = this.mgBufferControl1;
+            this.mgInvokeComponentMenuStripItem4.Text = "Buffer";
+            // 
+            // mgInvokeComponentMenuStripItem5
+            // 
+            this.mgInvokeComponentMenuStripItem5.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentMenuStripItem5.Image")));
+            this.mgInvokeComponentMenuStripItem5.Name = "mgInvokeComponentMenuStripItem5";
+            this.mgInvokeComponentMenuStripItem5.Size = new System.Drawing.Size(152, 22);
+            this.mgInvokeComponentMenuStripItem5.TargetComponent = this.mgMeasureControl1;
+            this.mgInvokeComponentMenuStripItem5.Text = "Measure";
+            // 
+            // mgInvokeComponentMenuStripItem6
+            // 
+            this.mgInvokeComponentMenuStripItem6.Image = ((System.Drawing.Image)(resources.GetObject("mgInvokeComponentMenuStripItem6.Image")));
+            this.mgInvokeComponentMenuStripItem6.Name = "mgInvokeComponentMenuStripItem6";
+            this.mgInvokeComponentMenuStripItem6.Size = new System.Drawing.Size(152, 22);
+            this.mgInvokeComponentMenuStripItem6.TargetComponent = this.mgQueryControl1;
+            this.mgInvokeComponentMenuStripItem6.Text = "Query";
+            // 
+            // toolStripSeparator5
+            // 
+            this.toolStripSeparator5.Name = "toolStripSeparator5";
+            this.toolStripSeparator5.Size = new System.Drawing.Size(149, 6);
+            // 
             // Form1
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -524,6 +643,7 @@
             this.statusStrip1.PerformLayout();
             this.menuStrip1.ResumeLayout(false);
             this.menuStrip1.PerformLayout();
+            this.ctxViewer.ResumeLayout(false);
             this.toolStrip1.ResumeLayout(false);
             this.toolStrip1.PerformLayout();
             this.splitContainer1.Panel1.ResumeLayout(false);
@@ -534,12 +654,13 @@
             this.splitContainer2.ResumeLayout(false);
             this.ctxGroup.ResumeLayout(false);
             this.ctxLayer.ResumeLayout(false);
-            this.ctxViewer.ResumeLayout(false);
             this.toolStripContainer1.ContentPanel.ResumeLayout(false);
             this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
             this.toolStripContainer1.TopToolStripPanel.PerformLayout();
             this.toolStripContainer1.ResumeLayout(false);
             this.toolStripContainer1.PerformLayout();
+            this.toolbar.ResumeLayout(false);
+            this.toolbar.PerformLayout();
             this.ResumeLayout(false);
             this.PerformLayout();
 
@@ -586,11 +707,24 @@
         private System.Windows.Forms.ContextMenuStrip ctxViewer;
         private System.Windows.Forms.ToolStripMenuItem refreshMapToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem initialViewToolStripMenuItem;
-        private System.Windows.Forms.ToolStripButton toolStripButton1;
-        private System.Windows.Forms.ToolStripButton toolStripButton2;
-        private System.Windows.Forms.ToolStripButton toolStripButton3;
         private System.Windows.Forms.ToolStripButton toolStripButton4;
         private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
+        private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem;
+        private OSGeo.MapGuide.Viewer.MgBufferControl mgBufferControl1;
+        private OSGeo.MapGuide.Viewer.MgQueryControl mgQueryControl1;
+        private OSGeo.MapGuide.Viewer.MgMeasureControl mgMeasureControl1;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentButton mgInvokeComponentButton1;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentButton mgInvokeComponentButton2;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentButton mgInvokeComponentButton3;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem mgInvokeComponentMenuStripItem1;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem mgInvokeComponentMenuStripItem2;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem mgInvokeComponentMenuStripItem3;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem mgInvokeComponentMenuStripItem4;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem mgInvokeComponentMenuStripItem5;
+        private OSGeo.MapGuide.Viewer.MgInvokeComponentMenuStripItem mgInvokeComponentMenuStripItem6;
     }
 }
 

Modified: branches/2.4/MgDev/Desktop/MapViewerTest/Form1.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewerTest/Form1.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewerTest/Form1.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -444,38 +444,6 @@
             viewer.InitialMapView();
         }
 
-        private void toolStripButton1_Click(object sender, EventArgs e)
-        {
-            var ctrl = new MgLineMeasureControl(viewer, MeasurementUnit.Kilometers);
-            var frm = new Form();
-            frm.Text = "Measure";
-            ctrl.Dock = DockStyle.Fill;
-            frm.Controls.Add(ctrl);
-            frm.Show();
-        }
-
-        private void toolStripButton2_Click(object sender, EventArgs e)
-        {
-            var ctrl = new MgBufferControl(viewer);
-            var frm = new Form();
-            frm.Text = "Buffer";
-            frm.Size = new System.Drawing.Size(250, 601);
-            ctrl.Dock = DockStyle.Fill;
-            frm.Controls.Add(ctrl);
-            frm.Show();
-        }
-
-        private void toolStripButton3_Click(object sender, EventArgs e)
-        {
-            var ctrl = new MgQueryControl(viewer);
-            var frm = new Form();
-            frm.Text = "Query";
-            frm.Size = new System.Drawing.Size(266, 460);
-            ctrl.Dock = DockStyle.Fill;
-            frm.Controls.Add(ctrl);
-            frm.Show();
-        }
-
         private void toolStripButton4_Click(object sender, EventArgs e)
         {
             var prof = (MgProfilingService)fact.CreateService(MgServiceType.ProfilingService);

Modified: branches/2.4/MgDev/Desktop/MapViewerTest/Form1.resx
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewerTest/Form1.resx	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewerTest/Form1.resx	2012-05-03 14:23:12 UTC (rev 6607)
@@ -123,55 +123,127 @@
   <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>133, 17</value>
   </metadata>
-  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>248, 17</value>
-  </metadata>
   <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
-  <data name="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+  <data name="mgInvokeComponentMenuStripItem1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
-        ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
-        HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
-        rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
-        TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
-        oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
-        7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
-        xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
-        LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
-        KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFoSURBVDhPpVNdKwRRGN47jZ/g57hQJGSzmxSTUv4DF26F
+        tRa12JLaXVtKMimJ3ZKLsUyWbEImdsUwF37C4zwzTZ2z7a4pp956v57ned9zZiIRcbTJgy5NNzIduvGj
+        jRtVbcKYY461UIeAWNpC2qxj/swG/U7dgAz2REhMgUYRJhaKNmZSOfR0R5GtfKA3YSokJIwLYvbR6HNq
+        T4QEiyJJcGD520/0LfskNPrMsT6byiNTfgdX9gnEaKMbFgp3fkNgjGWTa4mSDQr7BGI/qvQnTezdqySM
+        m+XGNsUKQli5ZJIMJC+xX3WUSWRl1tjD3qYvxcLhg+OZDKTP3OCKD275vCwePX55JhMwHkqFAA+vlnH8
+        /K2AGTPfUjm4xKhoOn1RwYyZbzs2b3Nq+wYl21WUGY+s/QEOPqTsVU0Bn7+6iK2HAAcEuesalrYKHsnF
+        m4t4WHDwJU7vVHDy5GDXqoN+250b3/A/v/MvkqOAAMpRUaEAAAAASUVORK5CYII=
 </value>
   </data>
-  <data name="toolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+  <metadata name="mgBufferControl1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>745, 17</value>
+  </metadata>
+  <data name="mgBufferControl1.Icon" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
-        ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
-        HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
-        rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
-        TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
-        oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
-        7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
-        xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
-        LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
-        KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFoSURBVDhPpVNdKwRRGN47jZ/g57hQJGSzmxSTUv4DF26F
+        tRa12JLaXVtKMimJ3ZKLsUyWbEImdsUwF37C4zwzTZ2z7a4pp956v57ned9zZiIRcbTJgy5NNzIduvGj
+        jRtVbcKYY461UIeAWNpC2qxj/swG/U7dgAz2REhMgUYRJhaKNmZSOfR0R5GtfKA3YSokJIwLYvbR6HNq
+        T4QEiyJJcGD520/0LfskNPrMsT6byiNTfgdX9gnEaKMbFgp3fkNgjGWTa4mSDQr7BGI/qvQnTezdqySM
+        m+XGNsUKQli5ZJIMJC+xX3WUSWRl1tjD3qYvxcLhg+OZDKTP3OCKD275vCwePX55JhMwHkqFAA+vlnH8
+        /K2AGTPfUjm4xKhoOn1RwYyZbzs2b3Nq+wYl21WUGY+s/QEOPqTsVU0Bn7+6iK2HAAcEuesalrYKHsnF
+        m4t4WHDwJU7vVHDy5GDXqoN+250b3/A/v/MvkqOAAMpRUaEAAAAASUVORK5CYII=
 </value>
   </data>
-  <data name="toolStripButton3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+  <metadata name="ctxViewer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>641, 17</value>
+  </metadata>
+  <data name="mgInvokeComponentMenuStripItem4.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIISURBVDhPpZP7S1NxGMbPPxKaXVUkMEq8IpKUCoY/hGgI
-        ymqkDYYXcCjDZOANURSjCNGFQUTsl4GXVMxKk62YU4fXQpaIlygHQxBRH8/zwvyaIAYe+HLgnPN8nue9
-        HA3nvDTq63oW/jm13XOwvPTB3DYFY5MH+bXfcN8ygfTSMSSXfESicQDxBqdYHwH29g9w2tnZ3UcguIvN
-        rR3417exuBJE5N1n/wfwLgXEOc38Bc6xNRHb+/y4nm49G0Bnit2zf9H6bkliE/jKuYxrd6oVgDWfjB+K
-        TWeKMyrGEVfowITvD9re/9ABVQrAhh0HHK+ZselMMaN/mvwtDb+aVqkA7HYIwIj3ysfluPTorJnP6Ezx
-        oHsD1s5ZXEktUwCOioB5f1CEPR9+wTG6iuiserTo8dkwng7HT/R+XUPF8xlcTjErAOdMcW6NW8STiwG8
-        7vej8oUPN/PsEv3t8Ao0TZP3T1u8uJRkUgAuSYHtO97oLxmXd5t9Ho8aPTK+GzntqNfrLm2fFoihwYOI
-        xGIF4KjoGBLzY1OrF9k6OOFxnwDC4wxIMX1G0pMhgVyMNyoA13PAtS7OrJk1PrC69LUdQWxuF6IybHrX
-        LRI7JrtZdoDAo1XmbjMyD+tjSXxGcXRmnYg5ttD9QuxDhN0uUgDOmbvNTpPOJaGAo2K36cyaGZvOFIfd
-        KlSA8/zRh9ABIDUG+1JpAAAAAElFTkSuQmCC
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFoSURBVDhPpVNdKwRRGN47jZ/g57hQJGSzmxSTUv4DF26F
+        tRa12JLaXVtKMimJ3ZKLsUyWbEImdsUwF37C4zwzTZ2z7a4pp956v57ned9zZiIRcbTJgy5NNzIduvGj
+        jRtVbcKYY461UIeAWNpC2qxj/swG/U7dgAz2REhMgUYRJhaKNmZSOfR0R5GtfKA3YSokJIwLYvbR6HNq
+        T4QEiyJJcGD520/0LfskNPrMsT6byiNTfgdX9gnEaKMbFgp3fkNgjGWTa4mSDQr7BGI/qvQnTezdqySM
+        m+XGNsUKQli5ZJIMJC+xX3WUSWRl1tjD3qYvxcLhg+OZDKTP3OCKD275vCwePX55JhMwHkqFAA+vlnH8
+        /K2AGTPfUjm4xKhoOn1RwYyZbzs2b3Nq+wYl21WUGY+s/QEOPqTsVU0Bn7+6iK2HAAcEuesalrYKHsnF
+        m4t4WHDwJU7vVHDy5GDXqoN+250b3/A/v/MvkqOAAMpRUaEAAAAASUVORK5CYII=
 </value>
   </data>
+  <data name="mgInvokeComponentMenuStripItem5.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABjSURBVDhPY2AY+sDGxuY/Ob6A64MxiDUIQz1IgFwMdjlV
+        XEBRGJCjGUXPxCC2Vd1BbP/QMVD8PzZxmBhIH9ggkMD/Fyn/F5ea/SeFBumDG/D9FNt/UjDIIrgBFHuB
+        4kAccAMAcR22AO16RYIAAAAASUVORK5CYII=
+</value>
+  </data>
+  <metadata name="mgMeasureControl1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 56</value>
+  </metadata>
+  <data name="mgMeasureControl1.Icon" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABjSURBVDhPY2AY+sDGxuY/Ob6A64MxiDUIQz1IgFwMdjlV
+        XEBRGJCjGUXPxCC2Vd1BbP/QMVD8PzZxmBhIH9ggkMD/Fyn/F5ea/SeFBumDG/D9FNt/UjDIIrgBFHuB
+        4kAccAMAcR22AO16RYIAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="mgInvokeComponentMenuStripItem6.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHySURBVDhPnZPLSxtRFMb9T6rUTW3Ulmw0GhqMNk0wSqCO
+        YhnNIkZUjCKUgvj4C7rSlUtXQksKRUHQxk0XhYpF8IETkpiHjxiT0TgTI0nm6z0DloxJbOmFj3Mf5/7u
+        me8wVVVFY2hyasLmcPjr6l8o1TW1eKZrVGhN+8V5ZeedbznB1PEGS5+82No/xHd/QI1Ln71oNppgc3D+
+        ipCuHk74uLCIH4EQdiIx/GLaDkfx8zii6ujsHIPDI6C8EsjY+w8TbRYbdo7D2D89Qzx9A+nuTp3vxk7+
+        aDsYQqupDZSvgXRz/cLK6hqOzuOIiSIKioLrTAZC/AKH7OViLXu/oJt7UIWu4aVyEI0hnEwhm8tBYYAT
+        8QrBxCUCD7QXieI5M1hTwZPqpwhfJnF6da1eTkqyCoimxBKFLhKg7mgAOkaMsIPEjaRepkg+lFOQ+UL5
+        GgD3jhfWv/kgypm/yvt1FZSvAUxPz3qaDUbI2Sxk5n45kTepdBpNhlZQfkkr+/oG/J7JKci3t8gVCiWS
+        WFdGx8bBDzhhbn+t9eCexvO88Ir12efbgsS8yOfzLErY2NiEocWI3t5+2O12uN3uypDZ+XkPgepZa6k7
+        FGlN+/SyXq+H1WqFy+WqDHnsp7mHWCwWOJ2PfM6/QMxm8/9VQXCqhDQzM4ffTfzkLal2r4sAAAAASUVO
+        RK5CYII=
+</value>
+  </data>
+  <metadata name="mgQueryControl1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>894, 17</value>
+  </metadata>
+  <data name="mgQueryControl1.Icon" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHySURBVDhPnZPLSxtRFMb9T6rUTW3Ulmw0GhqMNk0wSqCO
+        YhnNIkZUjCKUgvj4C7rSlUtXQksKRUHQxk0XhYpF8IETkpiHjxiT0TgTI0nm6z0DloxJbOmFj3Mf5/7u
+        me8wVVVFY2hyasLmcPjr6l8o1TW1eKZrVGhN+8V5ZeedbznB1PEGS5+82No/xHd/QI1Ln71oNppgc3D+
+        ipCuHk74uLCIH4EQdiIx/GLaDkfx8zii6ujsHIPDI6C8EsjY+w8TbRYbdo7D2D89Qzx9A+nuTp3vxk7+
+        aDsYQqupDZSvgXRz/cLK6hqOzuOIiSIKioLrTAZC/AKH7OViLXu/oJt7UIWu4aVyEI0hnEwhm8tBYYAT
+        8QrBxCUCD7QXieI5M1hTwZPqpwhfJnF6da1eTkqyCoimxBKFLhKg7mgAOkaMsIPEjaRepkg+lFOQ+UL5
+        GgD3jhfWv/kgypm/yvt1FZSvAUxPz3qaDUbI2Sxk5n45kTepdBpNhlZQfkkr+/oG/J7JKci3t8gVCiWS
+        WFdGx8bBDzhhbn+t9eCexvO88Ir12efbgsS8yOfzLErY2NiEocWI3t5+2O12uN3uypDZ+XkPgepZa6k7
+        FGlN+/SyXq+H1WqFy+WqDHnsp7mHWCwWOJ2PfM6/QMxm8/9VQXCqhDQzM4ffTfzkLal2r4sAAAAASUVO
+        RK5CYII=
+</value>
+  </data>
+  <data name="mgInvokeComponentMenuStripItem2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABjSURBVDhPY2AY+sDGxuY/Ob6A64MxiDUIQz1IgFwMdjlV
+        XEBRGJCjGUXPxCC2Vd1BbP/QMVD8PzZxmBhIH9ggkMD/Fyn/F5ea/SeFBumDG/D9FNt/UjDIIrgBFHuB
+        4kAccAMAcR22AO16RYIAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="mgInvokeComponentMenuStripItem3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHySURBVDhPnZPLSxtRFMb9T6rUTW3Ulmw0GhqMNk0wSqCO
+        YhnNIkZUjCKUgvj4C7rSlUtXQksKRUHQxk0XhYpF8IETkpiHjxiT0TgTI0nm6z0DloxJbOmFj3Mf5/7u
+        me8wVVVFY2hyasLmcPjr6l8o1TW1eKZrVGhN+8V5ZeedbznB1PEGS5+82No/xHd/QI1Ln71oNppgc3D+
+        ipCuHk74uLCIH4EQdiIx/GLaDkfx8zii6ujsHIPDI6C8EsjY+w8TbRYbdo7D2D89Qzx9A+nuTp3vxk7+
+        aDsYQqupDZSvgXRz/cLK6hqOzuOIiSIKioLrTAZC/AKH7OViLXu/oJt7UIWu4aVyEI0hnEwhm8tBYYAT
+        8QrBxCUCD7QXieI5M1hTwZPqpwhfJnF6da1eTkqyCoimxBKFLhKg7mgAOkaMsIPEjaRepkg+lFOQ+UL5
+        GgD3jhfWv/kgypm/yvt1FZSvAUxPz3qaDUbI2Sxk5n45kTepdBpNhlZQfkkr+/oG/J7JKci3t8gVCiWS
+        WFdGx8bBDzhhbn+t9eCexvO88Ir12efbgsS8yOfzLErY2NiEocWI3t5+2O12uN3uypDZ+XkPgepZa6k7
+        FGlN+/SyXq+H1WqFy+WqDHnsp7mHWCwWOJ2PfM6/QMxm8/9VQXCqhDQzM4ffTfzkLal2r4sAAAAASUVO
+        RK5CYII=
+</value>
+  </data>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>248, 17</value>
+  </metadata>
   <data name="toolStripButton4.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@@ -193,10 +265,42 @@
   <metadata name="ctxLayer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>545, 17</value>
   </metadata>
-  <metadata name="ctxViewer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>641, 17</value>
-  </metadata>
   <metadata name="toolbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>353, 17</value>
   </metadata>
+  <data name="mgInvokeComponentButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFoSURBVDhPpVNdKwRRGN47jZ/g57hQJGSzmxSTUv4DF26F
+        tRa12JLaXVtKMimJ3ZKLsUyWbEImdsUwF37C4zwzTZ2z7a4pp956v57ned9zZiIRcbTJgy5NNzIduvGj
+        jRtVbcKYY461UIeAWNpC2qxj/swG/U7dgAz2REhMgUYRJhaKNmZSOfR0R5GtfKA3YSokJIwLYvbR6HNq
+        T4QEiyJJcGD520/0LfskNPrMsT6byiNTfgdX9gnEaKMbFgp3fkNgjGWTa4mSDQr7BGI/qvQnTezdqySM
+        m+XGNsUKQli5ZJIMJC+xX3WUSWRl1tjD3qYvxcLhg+OZDKTP3OCKD275vCwePX55JhMwHkqFAA+vlnH8
+        /K2AGTPfUjm4xKhoOn1RwYyZbzs2b3Nq+wYl21WUGY+s/QEOPqTsVU0Bn7+6iK2HAAcEuesalrYKHsnF
+        m4t4WHDwJU7vVHDy5GDXqoN+250b3/A/v/MvkqOAAMpRUaEAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="mgInvokeComponentButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABjSURBVDhPY2AY+sDGxuY/Ob6A64MxiDUIQz1IgFwMdjlV
+        XEBRGJCjGUXPxCC2Vd1BbP/QMVD8PzZxmBhIH9ggkMD/Fyn/F5ea/SeFBumDG/D9FNt/UjDIIrgBFHuB
+        4kAccAMAcR22AO16RYIAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="mgInvokeComponentButton3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHySURBVDhPnZPLSxtRFMb9T6rUTW3Ulmw0GhqMNk0wSqCO
+        YhnNIkZUjCKUgvj4C7rSlUtXQksKRUHQxk0XhYpF8IETkpiHjxiT0TgTI0nm6z0DloxJbOmFj3Mf5/7u
+        me8wVVVFY2hyasLmcPjr6l8o1TW1eKZrVGhN+8V5ZeedbznB1PEGS5+82No/xHd/QI1Ln71oNppgc3D+
+        ipCuHk74uLCIH4EQdiIx/GLaDkfx8zii6ujsHIPDI6C8EsjY+w8TbRYbdo7D2D89Qzx9A+nuTp3vxk7+
+        aDsYQqupDZSvgXRz/cLK6hqOzuOIiSIKioLrTAZC/AKH7OViLXu/oJt7UIWu4aVyEI0hnEwhm8tBYYAT
+        8QrBxCUCD7QXieI5M1hTwZPqpwhfJnF6da1eTkqyCoimxBKFLhKg7mgAOkaMsIPEjaRepkg+lFOQ+UL5
+        GgD3jhfWv/kgypm/yvt1FZSvAUxPz3qaDUbI2Sxk5n45kTepdBpNhlZQfkkr+/oG/J7JKci3t8gVCiWS
+        WFdGx8bBDzhhbn+t9eCexvO88Ir12efbgsS8yOfzLErY2NiEocWI3t5+2O12uN3uypDZ+XkPgepZa6k7
+        FGlN+/SyXq+H1WqFy+WqDHnsp7mHWCwWOJ2PfM6/QMxm8/9VQXCqhDQzM4ffTfzkLal2r4sAAAAASUVO
+        RK5CYII=
+</value>
+  </data>
 </root>
\ No newline at end of file

Modified: branches/2.4/MgDev/Desktop/MapViewerTest/Program.cs
===================================================================
--- branches/2.4/MgDev/Desktop/MapViewerTest/Program.cs	2012-04-30 16:16:35 UTC (rev 6606)
+++ branches/2.4/MgDev/Desktop/MapViewerTest/Program.cs	2012-05-03 14:23:12 UTC (rev 6607)
@@ -37,11 +37,15 @@
                 {
                     var resId = new MgResourceIdentifier(args[0]);
                     resId.Validate();
-
-                    frm.Load += (s, e) =>
+                    var fact = new MgServiceFactory();
+                    var resSvc = (MgResourceService)fact.CreateService(MgServiceType.ResourceService);
+                    if (resSvc.ResourceExists(resId))
                     {
-                        frm.LoadMap(resId);
-                    };
+                        frm.Load += (s, e) =>
+                        {
+                            frm.LoadMap(resId);
+                        };
+                    }
                 }
                 catch (MgException ex)
                 {



More information about the mapguide-commits mailing list