[mapguide-commits] r7409 - in branches/2.5/MgDev/Desktop: MapViewer MapViewer/AppLayoutEngine MapViewerTest MgDesktop MgDesktop/Services MgDesktop/Services/Feature/Commands MgDesktop/Services/Rendering MgDesktop/System UnitTest

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri Mar 22 05:10:43 PDT 2013


Author: jng
Date: 2013-03-22 05:10:42 -0700 (Fri, 22 Mar 2013)
New Revision: 7409

Modified:
   branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/AppLayout.cs
   branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/MgQuitComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/Shell.cs
   branches/2.5/MgDev/Desktop/MapViewer/BaseInteractionComponents.cs
   branches/2.5/MgDev/Desktop/MapViewer/IMapViewer.cs
   branches/2.5/MgDev/Desktop/MapViewer/IPropertyPane.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgBufferComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgGenericInvokeComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgInvokeComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgLayerSelectionHandler.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgLegend.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgLoadMapComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgLoadPackageComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgMapViewer.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgMapViewerProvider.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgMeasureComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgPrintComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgPrintControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgPropertyPane.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgQueryComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgQueryResultsDialog.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgSearchComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgSearchControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgTaskPane.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgThemeComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgThemeControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgTransientMapState.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsComponent.cs
   branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsControlImpl.cs
   branches/2.5/MgDev/Desktop/MapViewer/Util.cs
   branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.Designer.cs
   branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.cs
   branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.resx
   branches/2.5/MgDev/Desktop/MgDesktop/Platform.ini
   branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DescribeSchema.cpp
   branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp
   branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp
   branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h
   branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp
   branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.cpp
   branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.h
   branches/2.5/MgDev/Desktop/MgDesktop/Services/Rendering/MappingUtil.cpp
   branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.cpp
   branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.h
   branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.cpp
   branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.h
   branches/2.5/MgDev/Desktop/UnitTest/main.cpp
Log:
mg-desktop: Merge r7402, r7403, r7404, r7405, r7406 and r7407 to 2.5 branch

Modified: branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/AppLayout.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/AppLayout.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/AppLayout.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -5,41 +5,83 @@
 
 namespace OSGeo.MapGuide.Viewer.AppLayoutEngine
 {
+    /// <summary>
+    /// Models an Application Layout, defining the user interface and functionality of your application
+    /// </summary>
     public class AppLayout
     {
+        /// <summary>
+        /// The window title
+        /// </summary>
         [XmlElement]
         public string Title { get; set; }
 
+        /// <summary>
+        /// The application icon
+        /// </summary>
         [XmlElement]
         public string Icon { get; set; }
 
+        /// <summary>
+        /// The application locale
+        /// </summary>
         [XmlElement]
         public string Language { get; set; }
 
+        /// <summary>
+        /// A set of top-level application settings
+        /// </summary>
         [XmlArray]
         public List<NameValue> Settings { get; set; }
 
+        /// <summary>
+        /// Settings for the information pane (legend + properties)
+        /// </summary>
         [XmlElement]
         public InfoPaneSettings InfoPane { get; set; }
 
+        /// <summary>
+        /// Settings for the Map Definition to be loaded
+        /// </summary>
         [XmlElement]
         public MapReference Map { get; set; }
 
+        /// <summary>
+        /// Defines the layout of the application's menus
+        /// </summary>
         [XmlElement]
         public MenuDefinition Menu { get; set; }
 
+        /// <summary>
+        /// Defines the layout of the application's toolbar
+        /// </summary>
         [XmlElement]
         public ToolbarDefinition Toolbar { get; set; }
 
+        /// <summary>
+        /// Defines the layout of the viewer's context menu
+        /// </summary>
         [XmlElement]
         public MenuDefinition ContextMenu { get; set; }
 
+        /// <summary>
+        /// Defines settings for the application's task pane
+        /// </summary>
         [XmlElement]
         public TaskPaneDefinition TaskPane { get; set; }
 
+        /// <summary>
+        /// Defines the list of components available to this application
+        /// </summary>
         [XmlArray]
         public List<ComponentDefinition> Components { get; set; }
 
+        /// <summary>
+        /// Creates a default AppLayout based on the given map definition
+        /// </summary>
+        /// <param name="title"></param>
+        /// <param name="mapDefinition"></param>
+        /// <returns></returns>
         public static AppLayout CreateDefault(string title, string mapDefinition)
         {
             var layout = new AppLayout();
@@ -258,72 +300,142 @@
         }
     }
 
+    /// <summary>
+    /// Defines settings for the information pane (legend + properties)
+    /// </summary>
     public class InfoPaneSettings
     {
+        /// <summary>
+        /// The width of this pane
+        /// </summary>
         [XmlElement]
         public uint Width { get; set; }
 
+        /// <summary>
+        /// Settings for the legend
+        /// </summary>
         [XmlElement]
         public LegendSettings Legend { get; set; }
 
+        /// <summary>
+        /// Settings for the property pane
+        /// </summary>
         [XmlElement]
         public PropertyPaneSettings PropertyPane { get; set; }
 
+        /// <summary>
+        /// Gets whether this pane is visible
+        /// </summary>
         [XmlIgnore]
         public bool IsVisible { get { return this.Legend.Visible || this.PropertyPane.Visible; } }
     }
 
+    /// <summary>
+    /// Defines settigs for the legend
+    /// </summary>
     public class LegendSettings
     {
+        /// <summary>
+        /// Gets or sets whether this element is visible
+        /// </summary>
         [XmlElement]
         public bool Visible { get; set; }
 
+        /// <summary>
+        /// Gets or sets the value at which themes (containing a number of rules greater than this property) are compressed 
+        /// </summary>
         [XmlElement]
         public int? ThemeCompressionLimit { get; set; }
 
+        /// <summary>
+        /// Gets or sets whether tooltips are shown
+        /// </summary>
         [XmlElement]
         public bool ShowTooltips { get; set; }
     }
 
+    /// <summary>
+    /// Defines settings for the property pane
+    /// </summary>
     public class PropertyPaneSettings
     {
+        /// <summary>
+        /// Gets or sets whether this element is visible
+        /// </summary>
         [XmlElement]
         public bool Visible { get; set; }
     }
-
+    
+    /// <summary>
+    /// Defines settings for the Map Definition
+    /// </summary>
     public class MapReference
     {
+        /// <summary>
+        /// The name of this map
+        /// </summary>
         [XmlElement]
         public string Name { get; set; }
 
+        /// <summary>
+        /// The Map Definition resource id
+        /// </summary>
         [XmlElement]
         public string MapDefinition { get; set; }
     }
 
+    /// <summary>
+    /// Defines the layout of the application's menus
+    /// </summary>
     public class MenuDefinition
     {
+        /// <summary>
+        /// The list of top level items
+        /// </summary>
         [XmlArray]
         public List<ItemBase> Items { get; set; }
     }
 
+    /// <summary>
+    /// Defines the layout of the application's toolbar
+    /// </summary>
     public class ToolbarDefinition
     {
+        /// <summary>
+        /// The list of top level items
+        /// </summary>
         [XmlArray]
         public List<ItemBase> Items { get; set; }
     }
 
+    /// <summary>
+    /// Defines settings for the Task Pane
+    /// </summary>
     public class TaskPaneDefinition
     {
+        /// <summary>
+        /// The width of this element
+        /// </summary>
         [XmlElement]
         public uint Width { get; set; }
 
+        /// <summary>
+        /// Specifies the component ID of the Task Pane resident component. A Task Pane resident component
+        /// has a "Target" property of Task Pane.
+        /// </summary>
         [XmlElement]
         public string InitialComponentID { get; set; }
 
+        /// <summary>
+        /// Defines the layout of the menu in the Task Pane
+        /// </summary>
         [XmlElement]
         public MenuDefinition TaskMenu { get; set; }
     }
 
+    /// <summary>
+    /// The super class of all toolbar and menu items
+    /// </summary>
     [XmlInclude(typeof(CommandItem))]
     [XmlInclude(typeof(SeparatorItem))]
     [XmlInclude(typeof(SubMenu))]
@@ -332,42 +444,93 @@
         
     }
 
+    /// <summary>
+    /// A menu/toolbar separator
+    /// </summary>
     public class SeparatorItem : ItemBase
     {
     }
 
+    /// <summary>
+    /// A sub-menu item
+    /// </summary>
     public class SubMenu : ItemBase
     {
+        /// <summary>
+        /// Constructor
+        /// </summary>
         public SubMenu() { }
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="label"></param>
         public SubMenu(string label) { this.Label = label; }
 
+        /// <summary>
+        /// The label
+        /// </summary>
         [XmlElement]
         public string Label { get; set; }
 
+        /// <summary>
+        /// The list of child items
+        /// </summary>
         [XmlArray]
         public List<ItemBase> Items { get; set; }
     }
 
+    /// <summary>
+    /// A menu/toolbar items that invokes a registered component
+    /// </summary>
     public class CommandItem : ItemBase
     {
+        /// <summary>
+        /// Constructor
+        /// </summary>
         public CommandItem() { }
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="componentId"></param>
         public CommandItem(string componentId) { this.ComponentID = componentId; }
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="componentId"></param>
+        /// <param name="showLabel"></param>
         public CommandItem(string componentId, bool showLabel) { this.ComponentID = componentId; this.ShowLabel = showLabel; }
 
+        /// <summary>
+        /// The id of the component to invoke when this item is clicked
+        /// </summary>
         [XmlElement]
         public string ComponentID { get; set; }
 
+        /// <summary>
+        /// Gets whether to display labels in this item
+        /// </summary>
         [XmlElement]
         public bool ShowLabel { get; set; }
     }
 
+    /// <summary>
+    /// Defines a component, a discrete piece of built-in or custom application functionality
+    /// </summary>
     public class ComponentDefinition
     {
+        /// <summary>
+        /// Constructor
+        /// </summary>
         public ComponentDefinition() { this.Properties = new List<NameValue>(); }
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="typeName"></param>
+        /// <param name="componentID"></param>
         public ComponentDefinition(string typeName, string componentID) : base()
         {
             this.Assembly = null;
@@ -375,35 +538,68 @@
             this.ComponentID = componentID;
         }
 
+        /// <summary>
+        /// The id of this component
+        /// </summary>
         [XmlElement]
         public string ComponentID { get; set; }
 
+        /// <summary>
+        /// The label to assign to any toolbar/menu item that's tied to this component
+        /// </summary>
         [XmlElement]
         public string Label { get; set; }
 
+        /// <summary>
+        /// The fully qualified .net name of the class that implements this component
+        /// </summary>
         [XmlElement]
         public string ClassName { get; set; }
 
+        /// <summary>
+        /// The assembly that contains the .net class that implements this component. If empty
+        /// it is assumed to originate from the viewer assembly
+        /// </summary>
         [XmlElement]
         public string Assembly { get; set; }
 
+        /// <summary>
+        /// A list of properties that define and customize component behaviour
+        /// </summary>
         [XmlArray]
         public List<NameValue> Properties { get; set; }
     }
 
+    /// <summary>
+    /// A key-value pair used to define properties
+    /// </summary>
     public class NameValue
     {
+        /// <summary>
+        /// Constructor
+        /// </summary>
         public NameValue() { }
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="value"></param>
         public NameValue(string name, string value)
         {
             this.Name = name;
             this.Value = value;
         }
 
+        /// <summary>
+        /// The name of the property
+        /// </summary>
         [XmlElement]
         public string Name { get; set; }
 
+        /// <summary>
+        /// The property's value
+        /// </summary>
         [XmlElement]
         public string Value { get; set; }
     }
@@ -415,12 +611,39 @@
     /// </summary>
     public class StringPrefixes
     {
+        /// <summary>
+        /// Map Definition
+        /// </summary>
         public const string MAPDEFINITION = "map:"; //NOXLATE
+
+        /// <summary>
+        /// Component ID
+        /// </summary>
         public const string COMPONENTID = "component:"; //NOXLATE
+
+        /// <summary>
+        /// Color
+        /// </summary>
         public const string COLOR = "color:"; //NOXLATE
+
+        /// <summary>
+        /// A .net enum
+        /// </summary>
         public const string ENUM = "enum:"; //NOXLATE
+
+        /// <summary>
+        /// Viewer ID
+        /// </summary>
         public const string VIEWERID = "viewer:"; //NOXLATE
+
+        /// <summary>
+        /// Task Pane ID
+        /// </summary>
         public const string TASKPANEID = "taskpane:"; //NOXLATE
+        
+        /// <summary>
+        /// An array of string values
+        /// </summary>
         public const string STRINGARRAY = "stringarray:"; //NOXLATE
     }
 }

Modified: branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/MgQuitComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/MgQuitComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/MgQuitComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -5,14 +5,23 @@
 
 namespace OSGeo.MapGuide.Viewer.AppLayoutEngine
 {
+    /// <summary>
+    /// A component that exits the application when invoked
+    /// </summary>
     [ToolboxItem(true)]
     public class MgQuitComponent : MgComponent
     {
+        /// <summary>
+        /// Constructor
+        /// </summary>
         public MgQuitComponent()
         {
             this.Label = Strings.TextExitApplication;
         }
 
+        /// <summary>
+        /// Invokes this component
+        /// </summary>
         public override void Invoke()
         {
             System.Windows.Forms.Application.Exit();

Modified: branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/Shell.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/Shell.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/AppLayoutEngine/Shell.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -10,6 +10,9 @@
 
 namespace OSGeo.MapGuide.Viewer.AppLayoutEngine
 {
+    /// <summary>
+    /// The top-level window of an AppLayout application
+    /// </summary>
     public partial class Shell : Form, IShell
     {
         private Shell()
@@ -20,6 +23,9 @@
 
         private static Shell _instance;
 
+        /// <summary>
+        /// The shell instance
+        /// </summary>
         public static IShell Instance
         {
             get
@@ -32,6 +38,12 @@
             }
         }
 
+        /// <summary>
+        /// Initializes this map viewer and constructs the user interface based on the
+        /// given AppLayout document
+        /// </summary>
+        /// <param name="layout"></param>
+        /// <param name="provider"></param>
         public void Initialize(AppLayout layout, MgMapViewerProvider provider)
         {
             this.Text = layout.Title;
@@ -179,7 +191,11 @@
         private MgMapViewerProvider _provider;
 
         private string _invokeComponentOnStartup;
-
+        
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="e"></param>
         protected override void OnLoad(EventArgs e)
         {
             //Optimization: If legend or property pane aren't visible
@@ -531,21 +547,37 @@
             }
         }
 
+        /// <summary>
+        /// Sets the message for the cursor position element of the status bar
+        /// </summary>
+        /// <param name="message"></param>
         public void SetCursorPositionMessage(string message)
         {
             lblCoordinates.Text = message;
         }
 
+        /// <summary>
+        /// Sets the message for the selected feature count element of the status bar
+        /// </summary>
+        /// <param name="message"></param>
         public void SetFeatureSelectedMessage(string message)
         {
             lblSelected.Text = message;
         }
 
+        /// <summary>
+        /// Sets the message for the map scale element of the status bar
+        /// </summary>
+        /// <param name="message"></param>
         public void SetMapScaleMessage(string message)
         {
             lblMapScale.Text = message;
         }
 
+        /// <summary>
+        /// Sets the message for the map size element of the status bar
+        /// </summary>
+        /// <param name="message"></param>
         public void SetMapSizeMessage(string message)
         {
             lblMapSize.Text = message;
@@ -556,27 +588,44 @@
             taskPane.LoadInitialTask();
         }
 
+        /// <summary>
+        /// Gets the component by its registered component id
+        /// </summary>
+        /// <param name="componentId"></param>
+        /// <returns></returns>
         public MgComponent GetComponent(string componentId)
         {
             return _components.ContainsKey(componentId) ? _components[componentId] : null;
         }
 
-
+        /// <summary>
+        /// Gets the legend component
+        /// </summary>
         public IMapLegend Legend
         {
             get { return legend; }
         }
 
+        /// <summary>
+        /// Gets the property pane component
+        /// </summary>
         public IPropertyPane PropertyPane
         {
             get { return propertyPane; }
         }
 
+        /// <summary>
+        /// Gets the task pane component
+        /// </summary>
         public MgTaskPane TaskPane
         {
             get { return taskPane; }
         }
 
+        /// <summary>
+        /// Reloads the map viewer
+        /// </summary>
+        /// <param name="provider"></param>
         public void ReloadViewer(MgMapViewerProvider provider)
         {
             _provider = provider;
@@ -597,16 +646,37 @@
         }
     }
 
+    /// <summary>
+    /// Defines the top-level window of an AppLayout application
+    /// </summary>
     public interface IShell : IMapStatusBar
     {
+        /// <summary>
+        /// Gets the component by its registered component id
+        /// </summary>
+        /// <param name="componentId"></param>
+        /// <returns></returns>
         MgComponent GetComponent(string componentId);
 
+        /// <summary>
+        /// Gets the legend component
+        /// </summary>
         IMapLegend Legend { get; }
 
+        /// <summary>
+        /// Gets the property pane component
+        /// </summary>
         IPropertyPane PropertyPane { get; }
 
+        /// <summary>
+        /// Gets the task pane component
+        /// </summary>
         MgTaskPane TaskPane { get; }
 
+        /// <summary>
+        /// Reloads the map viewer
+        /// </summary>
+        /// <param name="provider"></param>
         void ReloadViewer(MgMapViewerProvider provider);
     }
 }

Modified: branches/2.5/MgDev/Desktop/MapViewer/BaseInteractionComponents.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/BaseInteractionComponents.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/BaseInteractionComponents.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -5,6 +5,8 @@
 using System.Windows.Forms;
 using System.Globalization;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     [ToolboxItem(true)]

Modified: branches/2.5/MgDev/Desktop/MapViewer/IMapViewer.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/IMapViewer.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/IMapViewer.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -282,7 +282,7 @@
         /// set outside of the viewer
         /// </summary>
         /// <remarks>
-        /// If you have modified the selection as a result of calling <see cref="SelectByGeometry"/>, calling
+        /// If you have modified the selection as a result of calling <see cref="M:OSGeo.MapGuide.Viewer.IMapViewer.SelectByGeometry"/>, calling
         /// this method is not necessary as it will have automatically do this.
         /// </remarks>
         void UpdateSelection();
@@ -293,7 +293,7 @@
         /// </summary>
         /// <param name="raise">Indicates if the <see cref="SelectionChanged"/> event should be raised as well</param>
         /// <remarks>
-        /// If you have modified the selection as a result of calling <see cref="SelectByGeometry"/>, calling
+        /// If you have modified the selection as a result of calling <see cref="M:OSGeo.MapGuide.Viewer.IMapViewer.SelectByGeometry"/>, calling
         /// this method is not necessary as it will have automatically do this.
         /// </remarks>
         void UpdateSelection(bool raise);
@@ -301,9 +301,9 @@
         /// <summary>
         /// Selects features from all selectable layers that intersects the given geometry
         /// </summary>
-        /// <param name="geom"></param>
+        /// <param name="geom">The geometry to perform intersection tests against</param>
         /// <remarks>
-        /// This method will automatically trigger selection updates. Calling <see cref="UpdateSelection"/> is not necessary if
+        /// This method will automatically trigger selection updates. Calling <see cref="M:OSGeo.MapGuide.Viewer.IMapViewer.UpdateSelection"/> is not necessary if
         /// you are calling this method
         /// </remarks>
         void SelectByGeometry(MgGeometry geom);
@@ -311,15 +311,31 @@
         /// <summary>
         /// Selects features from all selectable layers that intersects the given geometry up to the specified number
         /// </summary>
-        /// <param name="geom"></param>
+        /// <param name="geom">The geometry to perform intersection tests against</param>
         /// <param name="maxFeatures">The maximum number of features to select. Specify -1 for all features</param>
         /// <remarks>
-        /// This method will automatically trigger selection updates. Calling <see cref="UpdateSelection"/> is not necessary if
+        /// This method will automatically trigger selection updates. Calling <see cref="M:OSGeo.MapGuide.Viewer.IMapViewer.UpdateSelection"/> is not necessary if
         /// you are calling this method
         /// </remarks>
         void SelectByGeometry(MgGeometry geom, int maxFeatures);
 
         /// <summary>
+        /// Selects features from all selectable layers that intersects the given geometry up to the specified number
+        /// </summary>
+        /// <param name="geom">The geometry to perform intersection tests against</param>
+        /// <param name="maxFeatures">The maximum number of features to select. Specify -1 for all features</param>
+        /// <param name="selectionHandler">An optional handler method that is invoked upon change of selection</param>
+        /// <remarks>
+        /// If a selection handler is passed to this method two things will happen:
+        /// <list type="number">
+        ///     <item>The <see cref="E:OSGeo.MapGuide.Viewer.IMapViewer.SelectionChanged"/> event is not raised upon change of selection. Existing subscribers will not be notified of any selection change caused by this method</item>
+        ///     <item>The handler will be called with a <see cref="T:OSGeo.MapGuide.MgSelectionBase"/> object passed to it. If this query results in nothing selected, null is passed to this handler</item>
+        /// </list>
+        /// The handler is responsible for the selection given to it. You may call <see cref="M:OSGeo.MapGuide.MgSelectionBase.Dispose()"/> on this selection if desired when your handler is done with it
+        /// </remarks>
+        void SelectByGeometry(MgGeometry geom, int maxFeatures, Action<MgSelectionBase> selectionHandler);
+
+        /// <summary>
         /// Zooms to the initial map view
         /// </summary>
         void InitialMapView();
@@ -486,8 +502,17 @@
         Point MapToScreenUnits(double x, double y);
     }
 
+    /// <summary>
+    /// Defines a map view location already visited
+    /// </summary>
     public class MgMapViewHistoryEntry
     {
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <param name="scale"></param>
         public MgMapViewHistoryEntry(double x, double y, double scale)
         {
             this.X = x;
@@ -495,10 +520,19 @@
             this.Scale = scale;
         }
 
+        /// <summary>
+        /// The view location X coordinate
+        /// </summary>
         public double X { get; private set; }
 
+        /// <summary>
+        /// The view location Y coordinate
+        /// </summary>
         public double Y { get; private set; }
 
+        /// <summary>
+        /// The view scale
+        /// </summary>
         public double Scale { get; private set; }
     }
 

Modified: branches/2.5/MgDev/Desktop/MapViewer/IPropertyPane.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/IPropertyPane.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/IPropertyPane.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -140,8 +140,6 @@
             
         }
 
-        private MgMapViewerProvider _provider;
-
         internal MgSelectionSet(MgSelectionBase selection, MgMapViewerProvider provider)
         {
             _agfRw = new MgAgfReaderWriter();

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgBufferComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgBufferComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgBufferComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,6 +3,8 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgBufferControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -7,6 +7,8 @@
 using System.Windows.Forms;
 using System.Globalization;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     internal partial class MgBufferControlImpl : MgControlView
@@ -198,7 +200,7 @@
                     schema.GetClasses().Add(classDef);
 
                     //finally, creation of the feature source
-                    MgCreateSdfParams sdfParams = new MgCreateSdfParams("LatLong", map.GetMapSRS(), schema); //NOXLATE
+                    MgFileFeatureSourceParams sdfParams = new MgFileFeatureSourceParams("OSGeo.SDF", "LatLong", map.GetMapSRS(), schema); //NOXLATE
                     _featSvc.CreateFeatureSource(fsId, sdfParams);
 
                     //Add layer to map

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -7,6 +7,8 @@
 using System.Diagnostics;
 using System.Reflection;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>
@@ -204,6 +206,9 @@
 
         private Dictionary<string, PropertyInfo> _properties;
 
+        /// <summary>
+        /// Gets the defined properties of this component
+        /// </summary>
         public IEnumerable<PropertyInfo> ComponentProperties
         {
             get 
@@ -235,6 +240,11 @@
             }
         }
 
+        /// <summary>
+        /// Sets a value for the given property
+        /// </summary>
+        /// <param name="propertyName"></param>
+        /// <param name="value"></param>
         public void SetPropertyValue(string propertyName, object value)
         {
             CheckAndInitProperties();
@@ -245,6 +255,11 @@
             prop.SetValue(this, Convert.ChangeType(value, prop.PropertyType), null);
         }
 
+        /// <summary>
+        /// Gets the value of the given property
+        /// </summary>
+        /// <param name="propertyName"></param>
+        /// <returns></returns>
         public object GetPropertyValue(string propertyName)
         {
             CheckAndInitProperties();
@@ -255,13 +270,39 @@
         }
     }
 
+    /// <summary>
+    /// Defines a method that's called when the viewer's busy state changes
+    /// </summary>
+    /// <param name="busy"></param>
     public delegate void ViewerBusyStateEventHandler(bool busy);
 
+    /// <summary>
+    /// Defines a listener for button state changes
+    /// </summary>
     public interface IButtonStateListener
     {
+        /// <summary>
+        /// The button needs to be enabled or disabled
+        /// </summary>
+        /// <param name="enabled"></param>
         void SetEnabled(bool enabled);
+        
+        /// <summary>
+        /// The button needs to be highlighted or un-highlighted
+        /// </summary>
+        /// <param name="outlined"></param>
         void SetActive(bool outlined);
+
+        /// <summary>
+        /// The text needs to be set on the button
+        /// </summary>
+        /// <param name="text"></param>
         void SetText(string text);
+
+        /// <summary>
+        /// The icon needs to be set on the button
+        /// </summary>
+        /// <param name="icon"></param>
         void SetIcon(Image icon);
     }
 
@@ -286,6 +327,9 @@
     [ToolboxItem(false)]
     public class MgViewerComponent : MgComponent, ISupportInitialize
     {
+        /// <summary>
+        /// Constructor
+        /// </summary>
         protected MgViewerComponent()
         {
             this.TaskPane = null;
@@ -344,6 +388,9 @@
 
         internal MgControlView CreateControl() { return CreateControlView(); }
 
+        /// <summary>
+        /// Invokes the component
+        /// </summary>
         public override void Invoke()
         {
             var control = CreateControlView();

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -4,6 +4,8 @@
 using System.Windows.Forms;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>
@@ -36,10 +38,13 @@
         /// </summary>
         public virtual bool ModalWindow { get; set; }
 
+        /// <summary>
+        /// Gets or sets the content closer
+        /// </summary>
         public IContentCloser Closer { get; set; }
 
         /// <summary>
-        /// Raises the <see cref="ContentClosed"/> event
+        /// 
         /// </summary>
         protected void Close()
         {
@@ -59,8 +64,14 @@
         }
     }
 
+    /// <summary>
+    /// An interface for closing component UI content
+    /// </summary>
     public interface IContentCloser
     {
+        /// <summary>
+        /// Closes the UI content
+        /// </summary>
         void Close();
     }
 }

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgGenericInvokeComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgGenericInvokeComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgGenericInvokeComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,6 +3,8 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     [ToolboxItem(true)]

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgInvokeComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgInvokeComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgInvokeComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -21,13 +21,29 @@
         MgComponent TargetComponent { get; set; }
     }
 
+    /// <summary>
+    /// A design-time invoker that invokes the target MgComponent when the source
+    /// UI component is clicked
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
     [ToolboxItem(false)]
     public class ComponentInvokerBase<T> : Component where T : ToolStripItem
     {
+        /// <summary>
+        /// The set of bindings
+        /// </summary>
         protected Dictionary<T, MgComponent> _bindings;
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
         protected ComponentInvokerBase() { _bindings = new Dictionary<T, MgComponent>(); }
 
+        /// <summary>
+        /// Gets the target bound component to invoke when this item is clicked
+        /// </summary>
+        /// <param name="component"></param>
+        /// <returns></returns>
         [Category("MapGuide Viewer")] //NOXLATE
         [DisplayName("Target Component")] //NOXLATE
         [Description("The target MapGuide component to invoke when this item is clicked")] //NOXLATE
@@ -40,6 +56,9 @@
                 return null;
         }
 
+        /// <summary>
+        /// Clears all registered bindings
+        /// </summary>
         public void Clear()
         {
             foreach (var key in _bindings.Keys)
@@ -57,16 +76,31 @@
                 binding.Component.Invoke();
         }
 
+        /// <summary>
+        /// Performs component setup
+        /// </summary>
+        /// <param name="component"></param>
+        /// <param name="value"></param>
         protected virtual void SetupComponent(T component, MgComponent value)
         {
             component.Click += OnComponentClicked;
         }
 
+        /// <summary>
+        /// Performs component teardown
+        /// </summary>
+        /// <param name="component"></param>
+        /// <param name="value"></param>
         protected virtual void TeardownComponent(T component, MgComponent value)
         {
             component.Click -= OnComponentClicked;
         }
 
+        /// <summary>
+        /// Associates the target component with teh source UI element
+        /// </summary>
+        /// <param name="component"></param>
+        /// <param name="value"></param>
         public void SetTargetComponent(T component, MgComponent value)
         {
             if (value == null)
@@ -172,15 +206,29 @@
         }
     }
 
+    /// <summary>
+    /// An design-time invoker that ties a <see cref="T:System.Windows.Forms.ToolStripMenuItem"/> to a
+    /// <see cref="T:OSGeo.MapGuide.Viewer.MgComponent"/>
+    /// </summary>
     [ToolboxItem(true)]
     [ProvideProperty("TargetComponent", typeof(ToolStripMenuItem))] //NOXLATE
     public class MgMenuItemComponentInvoker : ComponentInvokerBase<ToolStripMenuItem>, IExtenderProvider
     {
+        /// <summary>
+        /// Specifies whether this object can provide its extender properties to the specified object.
+        /// </summary>
+        /// <param name="extendee"></param>
+        /// <returns></returns>
         public bool CanExtend(object extendee)
         {
             return typeof(ToolStripMenuItem) == extendee.GetType();
         }
 
+        /// <summary>
+        /// Performs component setup
+        /// </summary>
+        /// <param name="component"></param>
+        /// <param name="value"></param>
         protected override void SetupComponent(ToolStripMenuItem component, MgComponent value)
         {
             component.ToolTipText = value.ToolTipText;
@@ -192,6 +240,11 @@
             base.SetupComponent(component, value);
         }
 
+        /// <summary>
+        /// Performs component teardown
+        /// </summary>
+        /// <param name="component"></param>
+        /// <param name="value"></param>
         protected override void TeardownComponent(ToolStripMenuItem component, MgComponent value)
         {
             var listener = component.Tag as MenuItemComponentBinding;
@@ -201,15 +254,29 @@
         }
     }
 
+    /// <summary>
+    /// An design-time invoker that ties a <see cref="T:System.Windows.Forms.ToolStripButton"/> to a
+    /// <see cref="T:OSGeo.MapGuide.Viewer.MgComponent"/>
+    /// </summary>
     [ToolboxItem(true)]
     [ProvideProperty("TargetComponent", typeof(ToolStripButton))] //NOXLATE
     public class MgToolButtonComponentInvoker : ComponentInvokerBase<ToolStripButton>, IExtenderProvider
     {
+        /// <summary>
+        /// Specifies whether this object can provide its extender properties to the specified object.
+        /// </summary>
+        /// <param name="extendee"></param>
+        /// <returns></returns>
         public bool CanExtend(object extendee)
         {
             return typeof(ToolStripButton) == extendee.GetType();
         }
 
+        /// <summary>
+        /// Performs component setup
+        /// </summary>
+        /// <param name="component"></param>
+        /// <param name="value"></param>
         protected override void SetupComponent(ToolStripButton component, MgComponent value)
         {
             component.ToolTipText = value.ToolTipText;
@@ -221,6 +288,11 @@
             base.SetupComponent(component, value);
         }
 
+        /// <summary>
+        /// Performs component teardown
+        /// </summary>
+        /// <param name="component"></param>
+        /// <param name="value"></param>
         protected override void TeardownComponent(ToolStripButton component, MgComponent value)
         {
             var listener = component.Tag as ToolbarButtonComponentBinding;

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgLayerSelectionHandler.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgLayerSelectionHandler.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgLayerSelectionHandler.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,8 +3,14 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
+    /// <summary>
+    /// Defines a method for handling viewer selections
+    /// </summary>
+    /// <param name="selectedFeatures"></param>
     public delegate void MgLayerSelectionEventHandler(MgSelectionSet selectedFeatures);
 
     [DefaultEvent("SelectionMade")] //NOXLATE

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgLegend.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgLegend.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgLegend.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -11,6 +11,8 @@
 using System.Diagnostics;
 using System.Windows.Forms.VisualStyles;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     using Legend.Model;
@@ -88,6 +90,9 @@
 
         private bool _busy = false;
 
+        /// <summary>
+        /// Gets whether the legend is currently in the state of rendering its tree
+        /// </summary>
         [Browsable(false)]
         public bool IsBusy
         {
@@ -420,6 +425,9 @@
             return null;
         }
 
+        /// <summary>
+        /// Gets or sets whether to display tooltips for tree nodes
+        /// </summary>
         public bool ShowTooltips
         {
             get { return trvLegend.ShowNodeToolTips; }
@@ -433,6 +441,9 @@
             }
         }
 
+        /// <summary>
+        /// Raised when a property has changed
+        /// </summary>
         public event PropertyChangedEventHandler PropertyChanged;
 
         private void OnPropertyChanged(string propertyName)

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgLineMeasureControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -71,15 +71,30 @@
         }
     }
 
+    /// <summary>
+    /// Defines a unit of measurement
+    /// </summary>
     public enum MeasurementUnit
     {
+        /// <summary>
+        /// Feet
+        /// </summary>
         Feet,
+        /// <summary>
+        /// Meters
+        /// </summary>
         Meters,
+        /// <summary>
+        /// Kilometers
+        /// </summary>
         Kilometers,
+        /// <summary>
+        /// Miles
+        /// </summary>
         Miles
     }
 
-    public class MeasuredLineSegment : INotifyPropertyChanged
+    internal class MeasuredLineSegment : INotifyPropertyChanged
     {
         public double MapDistanceMeters { get; set; }
 

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgLoadMapComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgLoadMapComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgLoadMapComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,6 +3,8 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     [ToolboxItem(true)]

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgLoadPackageComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgLoadPackageComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgLoadPackageComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -4,6 +4,8 @@
 using System.Windows.Forms;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     [ToolboxItem(true)]

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgMapViewer.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgMapViewer.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgMapViewer.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -15,6 +15,8 @@
 using System.Globalization;
 using System.Reflection;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>
@@ -1523,7 +1525,7 @@
         /// set outside of the viewer. This does not raise the <see cref="SelectionChanged"/> event
         /// </summary>
         /// <remarks>
-        /// If you have modified the selection as a result of calling <see cref="SelectByGeometry"/>, calling
+        /// If you have modified the selection as a result of calling <see cref="M:OSGeo.MapGuide.Viewer.IMapViewer.SelectByGeometry"/>, calling
         /// this method is not necessary as it will have automatically do this.
         /// </remarks>
         public void UpdateSelection()
@@ -1537,7 +1539,7 @@
         /// </summary>
         /// <param name="raise">Indicates if the <see cref="SelectionChanged"/> event should be raised as well</param>
         /// <remarks>
-        /// If you have modified the selection as a result of calling <see cref="SelectByGeometry"/>, calling
+        /// If you have modified the selection as a result of calling <see cref="M:OSGeo.MapGuide.Viewer.IMapViewer.SelectByGeometry"/>, calling
         /// this method is not necessary as it will have automatically do this.
         /// </remarks>
         public void UpdateSelection(bool raise)
@@ -2287,23 +2289,37 @@
         /// <param name="maxFeatures"></param>
         public void SelectByGeometry(MgGeometry geom, int maxFeatures)
         {
+            SelectByGeometry(geom, maxFeatures, null);
+        }
+
+        /// <summary>
+        /// Selects features from all selectable layers that intersects the given geometry
+        /// </summary>
+        /// <param name="geom"></param>
+        /// <param name="maxFeatures"></param>
+        /// <param name="selectionHandler"></param>
+        public void SelectByGeometry(MgGeometry geom, int maxFeatures, Action<MgSelectionBase> selectionHandler)
+        {
             //Don't select if dragging. This is the cause of the failure to render
             //multiple selections, which required a manual refresh afterwards
             if (isDragging)
                 return;
-
 #if TRACE
             var sw = new Stopwatch();
             sw.Start();
 #endif
+            MgSelectionBase newSel = null;
             //We will be either wiping or updating the existing selection set
             MgSelectionQueryResult sel = _provider.QueryMapFeatures(MgQueryRequestType.Selection, null, geom, MgFeatureSpatialOperations.Intersects, "", maxFeatures, (1 | 2)) as MgSelectionQueryResult; //1=Visible, 2=Selectable, 4=HasTooltips
             if (sel != null)
             {
-                MgSelectionBase newSel = sel.Selection;
+                newSel = sel.Selection;
                 string newXml = newSel.ToXml();
                 _selection.FromXml(newXml);
-                newSel.Dispose();
+
+                //If specified, we need to retain this for passing to the given selection handler
+                if (selectionHandler == null)
+                    newSel.Dispose();
             }
             else
             {
@@ -2320,9 +2336,16 @@
                 _selectionImage = null;
             }
             RenderSelection(true); //This is either async or queued up. Either way do this before firing off selection changed
-            var handler = this.SelectionChanged;
-            if (handler != null)
-                handler(this, EventArgs.Empty);
+            if (selectionHandler == null)
+            {
+                var handler = this.SelectionChanged;
+                if (handler != null)
+                    handler(this, EventArgs.Empty);
+            }
+            else
+            {
+                selectionHandler(newSel);
+            }
         }
 
         protected override void OnResize(EventArgs e)

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgMapViewerProvider.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgMapViewerProvider.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgMapViewerProvider.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -5,6 +5,8 @@
 using System.Collections.Specialized;
 using System.Diagnostics;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgMeasureComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgMeasureComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgMeasureComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,6 +3,8 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgPrintComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgPrintComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgPrintComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,6 +3,8 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     [ToolboxItem(true)]

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgPrintControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgPrintControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgPrintControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -6,6 +6,8 @@
 using System.Text;
 using System.Windows.Forms;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     public partial class MgPrintControlImpl : MgControlView

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgPropertyPane.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgPropertyPane.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgPropertyPane.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -7,6 +7,8 @@
 using System.Windows.Forms;
 using System.Collections;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>
@@ -201,6 +203,10 @@
         }
     }
 
+    /// <summary>
+    /// An adapter that allows an <see cref="T:System.Collections.IDictionary"/> to be presented
+    /// in a <see cref="T:System.Windows.Forms.PropertyGrid"/>
+    /// </summary>
     public class MgDictionaryPropertyGridAdapter : ICustomTypeDescriptor
     {
         IDictionary _dictionary;

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgQueryComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgQueryComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgQueryComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,6 +3,8 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     /// <summary>

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgQueryControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -6,6 +6,8 @@
 using System.Text;
 using System.Windows.Forms;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     internal partial class MgQueryControlImpl : MgControlView

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgQueryResultsDialog.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgQueryResultsDialog.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgQueryResultsDialog.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -6,8 +6,13 @@
 using System.Text;
 using System.Windows.Forms;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
+    /// <summary>
+    /// A dialog for displaying feature query results in a grid
+    /// </summary>
     public partial class MgQueryResultsDialog : Form
     {
         private string _geomProp;
@@ -325,7 +330,7 @@
         }
     }
 
-    public struct Bounds
+    internal struct Bounds
     {
         public double LowerX;
         public double LowerY;
@@ -333,7 +338,7 @@
         public double UpperY;
     }
 
-    public class BoxedGeometry
+    internal class BoxedGeometry
     {
         public override string ToString()
         {

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgSearchComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgSearchComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgSearchComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -2,6 +2,8 @@
 using System.Collections.Generic;
 using System.Text;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     public class MgSearchComponent : MgViewerComponent

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgSearchControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgSearchControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgSearchControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -6,6 +6,8 @@
 using System.Text;
 using System.Windows.Forms;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     public partial class MgSearchControlImpl : MgControlView

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgTaskPane.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgTaskPane.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgTaskPane.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -7,6 +7,8 @@
 using System.Windows.Forms;
 using OSGeo.MapGuide.Viewer.Tasks;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     public partial class MgTaskPane : UserControl

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgThemeComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgThemeComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgThemeComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -3,6 +3,8 @@
 using System.Text;
 using System.ComponentModel;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     [ToolboxItem(true)]

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgThemeControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgThemeControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgThemeControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -8,6 +8,8 @@
 using System.Xml;
 using System.Globalization;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     public partial class MgThemeControlImpl : MgControlView

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgTransientMapState.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgTransientMapState.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgTransientMapState.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -4,22 +4,60 @@
 
 namespace OSGeo.MapGuide.Viewer
 {
+    /// <summary>
+    /// Represents a temporary change in map state. Used primarily to set the current in-memory viewer map
+    /// into a temporary different display state for rendering and plotting.
+    /// 
+    /// Implements IDisposable semantics allowing for temporary map state to be explicity defined within a
+    /// C# using block with auto-reversion
+    /// </summary>
     public abstract class MgTransientMapState : IDisposable
     {
         private Stack<MgdMapStateTransition> _states;
 
+        /// <summary>
+        /// The original state
+        /// </summary>
         protected MgMapDisplayParameters _origState;
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
         protected MgTransientMapState()
         {
             _states = new Stack<MgdMapStateTransition>();
         }
 
+        /// <summary>
+        /// Gets the current display state
+        /// </summary>
+        /// <returns></returns>
         protected abstract MgMapDisplayParameters GetCurrentState();
 
+        /// <summary>
+        /// Applies the view center
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
         protected abstract void ApplyViewCenter(double x, double y);
+
+        /// <summary>
+        /// Applies the view scale
+        /// </summary>
+        /// <param name="scale"></param>
         protected abstract void ApplyViewScale(double scale);
+
+        /// <summary>
+        /// Applies the display size
+        /// </summary>
+        /// <param name="width"></param>
+        /// <param name="height"></param>
         protected abstract void ApplyDisplaySize(int width, int height);
+
+        /// <summary>
+        /// Applies the DPI
+        /// </summary>
+        /// <param name="dpi"></param>
         protected abstract void ApplyDPI(int dpi);
 
         private void ApplyState(MgMapDisplayParameters state)
@@ -30,7 +68,10 @@
             if (state.DPI.HasValue)
                 ApplyDPI(state.DPI.Value);
         }
-
+        
+        /// <summary>
+        /// Gets the size of temporary state transitions on the map state stack
+        /// </summary>
         public int Depth { get { return _states.Count; } }
 
         /// <summary>
@@ -64,6 +105,9 @@
             return trans.NewState;
         }
 
+        /// <summary>
+        /// Reverts the map to the original display state
+        /// </summary>
         public void Dispose()
         {
             while (_states.Count > 0)
@@ -74,16 +118,31 @@
         }
     }
 
+    /// <summary>
+    /// Represents a temporary map display state
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
     public abstract class MgTransientMapState<T> : MgTransientMapState where T : MgMapBase
     {
+        /// <summary>
+        /// The map instance
+        /// </summary>
         protected T _map;
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="map"></param>
         protected MgTransientMapState(T map)
         {
             _map = map;
             _origState = GetCurrentState();
         }
 
+        /// <summary>
+        /// Gets the current display state
+        /// </summary>
+        /// <returns></returns>
         protected override MgMapDisplayParameters GetCurrentState()
         {
             var pt = _map.ViewCenter;
@@ -104,13 +163,44 @@
     /// </summary>
     public class MgMapDisplayParameters
     {
+        /// <summary>
+        /// The view center X coordinate
+        /// </summary>
         public double X { get; private set; }
+        
+        /// <summary>
+        /// The view center Y coordinate
+        /// </summary>
         public double Y { get; private set; }
+
+        /// <summary>
+        /// The view scale
+        /// </summary>
         public double Scale { get; private set; }
+
+        /// <summary>
+        /// The display width
+        /// </summary>
         public int Width { get; private set; }
+
+        /// <summary>
+        /// The display height
+        /// </summary>
         public int Height { get; private set; }
+
+        /// <summary>
+        /// The display DPI
+        /// </summary>
         public int? DPI { get; private set; }
-
+        
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <param name="scale"></param>
+        /// <param name="width"></param>
+        /// <param name="height"></param>
         public MgMapDisplayParameters(double x, double y, double scale, int width, int height)
         {
             this.X = x;
@@ -120,6 +210,15 @@
             this.Height = height;
         }
 
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <param name="scale"></param>
+        /// <param name="width"></param>
+        /// <param name="height"></param>
+        /// <param name="dpi"></param>
         public MgMapDisplayParameters(double x, double y, double scale, int width, int height, int dpi)
             : this(x, y, scale, width, height)
         {

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsComponent.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsComponent.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsComponent.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -7,6 +7,8 @@
 using System.Diagnostics;
 using System.Drawing;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     [ToolboxItem(true)]

Modified: branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsControlImpl.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsControlImpl.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/MgViewerOptionsControlImpl.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -8,6 +8,8 @@
 using System.Xml.Serialization;
 using System.IO;
 
+#pragma warning disable 1591
+
 namespace OSGeo.MapGuide.Viewer
 {
     public partial class MgViewerOptionsControlImpl : MgControlView

Modified: branches/2.5/MgDev/Desktop/MapViewer/Util.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewer/Util.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewer/Util.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -63,7 +63,7 @@
                 if (srs != string.Empty)
                     return srs;
             }
-            catch (MgException e)
+            catch (MgException)
             {
             }
 

Modified: branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.Designer.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.Designer.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.Designer.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -104,6 +104,13 @@
             this.toolStripMenuItem25 = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripMenuItem26 = new System.Windows.Forms.ToolStripMenuItem();
             this.lblLoading = new System.Windows.Forms.ToolStripLabel();
+            this.toolStripSplitButton1 = new System.Windows.Forms.ToolStripSplitButton();
+            this.pointToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.lineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.rectangleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.lineStringToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.polygonToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.circleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.taskPane = new OSGeo.MapGuide.Viewer.MgTaskPane();
             this.toolStrip1 = new System.Windows.Forms.ToolStrip();
             this.btnInitialTask = new System.Windows.Forms.ToolStripButton();
@@ -143,16 +150,11 @@
             this.loadCompactViewerComponent = new OSGeo.MapGuide.Viewer.MgGenericInvokeComponent();
             this.profileComponent = new OSGeo.MapGuide.Viewer.MgGenericInvokeComponent();
             this.mgToolButtonComponentInvoker1 = new OSGeo.MapGuide.Viewer.MgToolButtonComponentInvoker();
+            this.mgZoomPreviousComponent1 = new OSGeo.MapGuide.Viewer.MgZoomPreviousComponent();
             this.mgZoomNextComponent1 = new OSGeo.MapGuide.Viewer.MgZoomNextComponent();
-            this.mgZoomPreviousComponent1 = new OSGeo.MapGuide.Viewer.MgZoomPreviousComponent();
             this.mgLayerSelectionHandler1 = new OSGeo.MapGuide.Viewer.MgLayerSelectionHandler();
-            this.toolStripSplitButton1 = new System.Windows.Forms.ToolStripSplitButton();
-            this.pointToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.lineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.rectangleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.lineStringToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.polygonToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.circleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.testToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.oneshotCallbackToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.appMenu.SuspendLayout();
             this.appContextMenu.SuspendLayout();
             this.appContainer.Panel1.SuspendLayout();
@@ -186,7 +188,8 @@
             // 
             this.appMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.fileToolStripMenuItem,
-            this.toolsToolStripMenuItem});
+            this.toolsToolStripMenuItem,
+            this.testToolStripMenuItem});
             this.appMenu.Location = new System.Drawing.Point(0, 0);
             this.appMenu.Name = "appMenu";
             this.appMenu.Size = new System.Drawing.Size(1008, 24);
@@ -591,10 +594,13 @@
             this.mapViewer.MouseWheelDelayRenderInterval = 800;
             this.mapViewer.Name = "mapViewer";
             this.mapViewer.PointPixelBuffer = 2;
+            this.mapViewer.RespectFiniteDisplayScales = false;
             this.mapViewer.SelectionColor = System.Drawing.Color.Blue;
             this.mapViewer.Size = new System.Drawing.Size(495, 658);
             this.mapViewer.TabIndex = 0;
             this.mapViewer.Text = "mgMapViewer1";
+            this.mapViewer.TooltipDelayInterval = 1000;
+            this.mapViewer.UseRenderMapIfTiledLayersExist = false;
             this.mapViewer.ZoomInFactor = 0.5;
             this.mapViewer.ZoomOutFactor = 2;
             this.mapViewer.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(this.OnViewerPropertyChanged);
@@ -960,6 +966,63 @@
             this.lblLoading.Size = new System.Drawing.Size(30, 22);
             this.lblLoading.Visible = false;
             // 
+            // toolStripSplitButton1
+            // 
+            this.toolStripSplitButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.pointToolStripMenuItem,
+            this.lineToolStripMenuItem,
+            this.rectangleToolStripMenuItem,
+            this.lineStringToolStripMenuItem,
+            this.polygonToolStripMenuItem,
+            this.circleToolStripMenuItem});
+            this.toolStripSplitButton1.Image = global::MapViewerTest.Properties.Resources.icon_tasks;
+            this.toolStripSplitButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.toolStripSplitButton1.Name = "toolStripSplitButton1";
+            this.toolStripSplitButton1.Size = new System.Drawing.Size(78, 22);
+            this.toolStripSplitButton1.Text = "Digitize";
+            // 
+            // pointToolStripMenuItem
+            // 
+            this.pointToolStripMenuItem.Name = "pointToolStripMenuItem";
+            this.pointToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
+            this.pointToolStripMenuItem.Text = "Point";
+            this.pointToolStripMenuItem.Click += new System.EventHandler(this.pointToolStripMenuItem_Click);
+            // 
+            // lineToolStripMenuItem
+            // 
+            this.lineToolStripMenuItem.Name = "lineToolStripMenuItem";
+            this.lineToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
+            this.lineToolStripMenuItem.Text = "Line";
+            this.lineToolStripMenuItem.Click += new System.EventHandler(this.lineToolStripMenuItem_Click);
+            // 
+            // rectangleToolStripMenuItem
+            // 
+            this.rectangleToolStripMenuItem.Name = "rectangleToolStripMenuItem";
+            this.rectangleToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
+            this.rectangleToolStripMenuItem.Text = "Rectangle";
+            this.rectangleToolStripMenuItem.Click += new System.EventHandler(this.rectangleToolStripMenuItem_Click);
+            // 
+            // lineStringToolStripMenuItem
+            // 
+            this.lineStringToolStripMenuItem.Name = "lineStringToolStripMenuItem";
+            this.lineStringToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
+            this.lineStringToolStripMenuItem.Text = "LineString";
+            this.lineStringToolStripMenuItem.Click += new System.EventHandler(this.lineStringToolStripMenuItem_Click);
+            // 
+            // polygonToolStripMenuItem
+            // 
+            this.polygonToolStripMenuItem.Name = "polygonToolStripMenuItem";
+            this.polygonToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
+            this.polygonToolStripMenuItem.Text = "Polygon";
+            this.polygonToolStripMenuItem.Click += new System.EventHandler(this.polygonToolStripMenuItem_Click);
+            // 
+            // circleToolStripMenuItem
+            // 
+            this.circleToolStripMenuItem.Name = "circleToolStripMenuItem";
+            this.circleToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
+            this.circleToolStripMenuItem.Text = "Circle";
+            this.circleToolStripMenuItem.Click += new System.EventHandler(this.circleToolStripMenuItem_Click);
+            // 
             // taskPane
             // 
             this.taskPane.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -1086,6 +1149,7 @@
             // 
             this.mgPrintComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgPrintComponent1.Icon")));
             this.mgPrintComponent1.Label = "Print";
+            this.mgPrintComponent1.OwnerParent = null;
             this.mgPrintComponent1.Target = OSGeo.MapGuide.Viewer.MgViewerTarget.TaskPane;
             this.mgPrintComponent1.TaskPane = this.taskPane;
             this.mgPrintComponent1.ToolTipText = "Print";
@@ -1175,6 +1239,7 @@
             this.mgBufferComponent1.DefaultLayerName = "Buffer 1";
             this.mgBufferComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgBufferComponent1.Icon")));
             this.mgBufferComponent1.Label = "Buffer";
+            this.mgBufferComponent1.OwnerParent = null;
             this.mgBufferComponent1.Target = OSGeo.MapGuide.Viewer.MgViewerTarget.TaskPane;
             this.mgBufferComponent1.TaskPane = this.taskPane;
             this.mgBufferComponent1.ToolTipText = null;
@@ -1184,6 +1249,7 @@
             // 
             this.mgMeasureComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgMeasureComponent1.Icon")));
             this.mgMeasureComponent1.Label = "Measure";
+            this.mgMeasureComponent1.OwnerParent = null;
             this.mgMeasureComponent1.Target = OSGeo.MapGuide.Viewer.MgViewerTarget.TaskPane;
             this.mgMeasureComponent1.TaskPane = this.taskPane;
             this.mgMeasureComponent1.ToolTipText = null;
@@ -1193,6 +1259,8 @@
             // 
             this.mgQueryComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgQueryComponent1.Icon")));
             this.mgQueryComponent1.Label = "Query";
+            this.mgQueryComponent1.LayerList = null;
+            this.mgQueryComponent1.OwnerParent = null;
             this.mgQueryComponent1.Target = OSGeo.MapGuide.Viewer.MgViewerTarget.TaskPane;
             this.mgQueryComponent1.TaskPane = this.taskPane;
             this.mgQueryComponent1.ToolTipText = null;
@@ -1202,6 +1270,7 @@
             // 
             this.mgViewerOptionsComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgViewerOptionsComponent1.Icon")));
             this.mgViewerOptionsComponent1.Label = "Viewer Options";
+            this.mgViewerOptionsComponent1.OwnerParent = null;
             this.mgViewerOptionsComponent1.PreferencesDirectory = "";
             this.mgViewerOptionsComponent1.Target = OSGeo.MapGuide.Viewer.MgViewerTarget.TaskPane;
             this.mgViewerOptionsComponent1.TaskPane = this.taskPane;
@@ -1244,6 +1313,7 @@
             // 
             this.mgThemeComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgThemeComponent1.Icon")));
             this.mgThemeComponent1.Label = "Theme";
+            this.mgThemeComponent1.OwnerParent = null;
             this.mgThemeComponent1.Target = OSGeo.MapGuide.Viewer.MgViewerTarget.TaskPane;
             this.mgThemeComponent1.TaskPane = this.taskPane;
             this.mgThemeComponent1.ToolTipText = "Theme";
@@ -1267,6 +1337,13 @@
             this.profileComponent.Viewer = this.mapViewer;
             this.profileComponent.Invoked += new System.EventHandler(this.profileComponent_Invoked);
             // 
+            // mgZoomPreviousComponent1
+            // 
+            this.mgZoomPreviousComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgZoomPreviousComponent1.Icon")));
+            this.mgZoomPreviousComponent1.Label = "Zoom Previous";
+            this.mgZoomPreviousComponent1.ToolTipText = "Zoom Previous";
+            this.mgZoomPreviousComponent1.Viewer = this.mapViewer;
+            // 
             // mgZoomNextComponent1
             // 
             this.mgZoomNextComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgZoomNextComponent1.Icon")));
@@ -1274,13 +1351,6 @@
             this.mgZoomNextComponent1.ToolTipText = "Zoom Next";
             this.mgZoomNextComponent1.Viewer = this.mapViewer;
             // 
-            // mgZoomPreviousComponent1
-            // 
-            this.mgZoomPreviousComponent1.Icon = ((System.Drawing.Image)(resources.GetObject("mgZoomPreviousComponent1.Icon")));
-            this.mgZoomPreviousComponent1.Label = "Zoom Previous";
-            this.mgZoomPreviousComponent1.ToolTipText = "Zoom Previous";
-            this.mgZoomPreviousComponent1.Viewer = this.mapViewer;
-            // 
             // mgLayerSelectionHandler1
             // 
             this.mgLayerSelectionHandler1.Layers = new string[] {
@@ -1288,63 +1358,21 @@
             this.mgLayerSelectionHandler1.Viewer = this.mapViewer;
             this.mgLayerSelectionHandler1.SelectionMade += new OSGeo.MapGuide.Viewer.MgLayerSelectionEventHandler(this.mgLayerSelectionHandler1_SelectionMade);
             // 
-            // toolStripSplitButton1
+            // testToolStripMenuItem
             // 
-            this.toolStripSplitButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.pointToolStripMenuItem,
-            this.lineToolStripMenuItem,
-            this.rectangleToolStripMenuItem,
-            this.lineStringToolStripMenuItem,
-            this.polygonToolStripMenuItem,
-            this.circleToolStripMenuItem});
-            this.toolStripSplitButton1.Image = global::MapViewerTest.Properties.Resources.icon_tasks;
-            this.toolStripSplitButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.toolStripSplitButton1.Name = "toolStripSplitButton1";
-            this.toolStripSplitButton1.Size = new System.Drawing.Size(78, 22);
-            this.toolStripSplitButton1.Text = "Digitize";
+            this.testToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.oneshotCallbackToolStripMenuItem});
+            this.testToolStripMenuItem.Name = "testToolStripMenuItem";
+            this.testToolStripMenuItem.Size = new System.Drawing.Size(41, 20);
+            this.testToolStripMenuItem.Text = "Test";
             // 
-            // pointToolStripMenuItem
+            // oneshotCallbackToolStripMenuItem
             // 
-            this.pointToolStripMenuItem.Name = "pointToolStripMenuItem";
-            this.pointToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-            this.pointToolStripMenuItem.Text = "Point";
-            this.pointToolStripMenuItem.Click += new System.EventHandler(this.pointToolStripMenuItem_Click);
+            this.oneshotCallbackToolStripMenuItem.Name = "oneshotCallbackToolStripMenuItem";
+            this.oneshotCallbackToolStripMenuItem.Size = new System.Drawing.Size(170, 22);
+            this.oneshotCallbackToolStripMenuItem.Text = "One-shot callback";
+            this.oneshotCallbackToolStripMenuItem.Click += new System.EventHandler(this.oneshotCallbackToolStripMenuItem_Click);
             // 
-            // lineToolStripMenuItem
-            // 
-            this.lineToolStripMenuItem.Name = "lineToolStripMenuItem";
-            this.lineToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-            this.lineToolStripMenuItem.Text = "Line";
-            this.lineToolStripMenuItem.Click += new System.EventHandler(this.lineToolStripMenuItem_Click);
-            // 
-            // rectangleToolStripMenuItem
-            // 
-            this.rectangleToolStripMenuItem.Name = "rectangleToolStripMenuItem";
-            this.rectangleToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-            this.rectangleToolStripMenuItem.Text = "Rectangle";
-            this.rectangleToolStripMenuItem.Click += new System.EventHandler(this.rectangleToolStripMenuItem_Click);
-            // 
-            // lineStringToolStripMenuItem
-            // 
-            this.lineStringToolStripMenuItem.Name = "lineStringToolStripMenuItem";
-            this.lineStringToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-            this.lineStringToolStripMenuItem.Text = "LineString";
-            this.lineStringToolStripMenuItem.Click += new System.EventHandler(this.lineStringToolStripMenuItem_Click);
-            // 
-            // polygonToolStripMenuItem
-            // 
-            this.polygonToolStripMenuItem.Name = "polygonToolStripMenuItem";
-            this.polygonToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-            this.polygonToolStripMenuItem.Text = "Polygon";
-            this.polygonToolStripMenuItem.Click += new System.EventHandler(this.polygonToolStripMenuItem_Click);
-            // 
-            // circleToolStripMenuItem
-            // 
-            this.circleToolStripMenuItem.Name = "circleToolStripMenuItem";
-            this.circleToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
-            this.circleToolStripMenuItem.Text = "Circle";
-            this.circleToolStripMenuItem.Click += new System.EventHandler(this.circleToolStripMenuItem_Click);
-            // 
             // MgAppWindow
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -1520,6 +1548,8 @@
         private System.Windows.Forms.ToolStripMenuItem lineStringToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem polygonToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem circleToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem testToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem oneshotCallbackToolStripMenuItem;
 
     }
 }
\ No newline at end of file

Modified: branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.cs
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.cs	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.cs	2013-03-22 12:10:42 UTC (rev 7409)
@@ -160,5 +160,40 @@
         {
             mapViewer.DigitizeCircle((x, y, r) => { MessageBox.Show("Done"); }, "Custom circle digitization prompt");
         }
+
+        private void oneshotCallbackToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            MgGeometryFactory geomFact = new MgGeometryFactory();
+            mapViewer.DigitizePoint((x, y) => {
+                MgCoordinate coord = geomFact.CreateCoordinateXY(x, y);
+                MgPoint pt = geomFact.CreatePoint(coord);
+
+                mapViewer.SelectByGeometry(pt, -1, (selection) => {
+                    if (selection == null)
+                    {
+                        MessageBox.Show("No selected features");
+                        return;
+                    }
+                    else
+                    {
+                        MgReadOnlyLayerCollection layers = selection.GetLayers();
+                        if (layers != null)
+                        {
+                            StringBuilder sb = new StringBuilder("Selection summary:");
+                            for (int i = 0; i < layers.GetCount(); i++)
+                            {
+                                MgLayerBase lyr = layers.GetItem(i);
+                                sb.Append(Environment.NewLine + lyr.GetName() + ": " + selection.GetSelectedFeaturesCount(lyr, lyr.GetFeatureClassName()));
+                            }
+                            MessageBox.Show(sb.ToString());
+                        }
+                        else 
+                        {
+                            MessageBox.Show("No selected features");
+                        }
+                    }
+                });
+            });
+        }
     }
 }

Modified: branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.resx
===================================================================
--- branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.resx	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MapViewerTest/MgAppWindow.resx	2013-03-22 12:10:42 UTC (rev 7409)
@@ -639,16 +639,16 @@
   <data name="toolStripButton13.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIXSURBVDhPnZNbaxNREMf3i/Si1oo29RYfhF6iSTQkNErA
-        bktlax5iEIXE1huU1qIUfPFN8EWEfgNBKT6IIJRYoaX64kM3RdMkRqvdbppsskn28vfMgUAvSREHhjnn
-        7MzvzPkPKwjb7Prt8XggFEoe6z5ptx/owFHHCZv2dL49r+F64Ioou30BzL6ew/xKEonVbzzOvplDj8uN
-        QEhMNoVcGhTlazduYvF7CsvpLD4zX1rLYDGVxurvDRR0Hc9fvATl7YHcuvcg7vUP4Es6g6+5n1gvFKFV
-        q3ydUjZRM02cPnOWx363F5S/A3JZHJFfvXuPlV/ryKoqLNvGVrmMXH4LhmXxYnIyk0EURbF2ABzHT9ky
-        K15jt1UMAzYD/FDz0Gs1XtjadrChd3Z2PeWgtvZDyGyq/EYqVrQSB2xoGsxdHdB3nelBdQRmkGeCg40s
-        xwr+FDVeTJF0IM+Xdf4k6oRilnX56PGMXX8CQQTxqiR/SHyEWio3dK1ShWFaoPiWaUX5dUBLS2tBmJiY
-        ivX2nUORtVZi6jfzAhO2p9cFyq8DDh/pesLXw8OjyTt376PChCPldzudx+JjkEbD8Hgvcg32mCRJ8nn3
-        BSwsfILBpkFGMcGe19fvwtDQCILBIKLRaHPI1PR0jEDdbLQ0HYq0p3O62el0wu/3IxKJNIfs99PUIT6f
-        D+HwPs/5F4jH4/m/LghOnZBPTj7EXzBH4FruleOnAAAAAElFTkSuQmCC
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIWSURBVDhPnZNLaxNRFMfni8TWV0Wb+ooLoY9oEg0JjRLQ
+        aalMzSIGUUiqtgqlT1y4cSe4EaHfQFCKCxEEiRUq6sZFJ0XTJEar006aTDJJ5vH3nguBPpIiPXA49945
+        53fP/R9GEDbZjZG7iWA4nDrWddJu338IR50nbNrT+ea8puv+K6Ls8Qcx93Ie75dSSC5/53Hu1Ty63R4E
+        w2KqJeTSVVG+fvMWFn+k8TmTwxfmn1ayWExnsPxHQVHX8fTZc1DeDsjtsQcJX6AfXzNZfMv/wmqxBK1W
+        4+v02jrqponTZ87y2OfxgfK3QC6LQ/KLN2+x9HsVOVWFZdvYqFSQL2zAsCxeTE5mMoiiKNYWgPP4KVtm
+        xSvstqphwGaAn2oBer3OC/e1HWjqHR2djzmorf0gsusqv5GK17QyByiaBnNbB/RdZ3pQHYEZ5IngZCPL
+        s4K/JY0XUyQdyAsVnT+JOqGYY13OzD60G08giCBek+R3yQ9Qy5WmrlVrMEwLFF8zrSi/AXA4HEVhfHwy
+        3tN7DiXWWpmp38qLTNjuHjcovwE4fKTzEV8PDg6n7o3eR5UJR8pvdzqPJ+5AGo7A67vINdhhkiTJ5z0X
+        sLDwEQabBhnFJHteb58bAwNDCIVCiMVirSGT09NxAnWx0dJ0KNKezulml8uFQCCAaDTaGrLbT9OA+P1+
+        RCK7POd/IF6vd29dEJw6IZ+YmMI/H6vgUxqti8IAAAAASUVORK5CYII=
 </value>
   </data>
   <metadata name="mgZoomPreviousComponent1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -657,29 +657,29 @@
   <data name="mgZoomPreviousComponent1.Icon" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIXSURBVDhPnZNbaxNREMf3i/Si1oo29RYfhF6iSTQkNErA
-        bktlax5iEIXE1huU1qIUfPFN8EWEfgNBKT6IIJRYoaX64kM3RdMkRqvdbppsskn28vfMgUAvSREHhjnn
-        7MzvzPkPKwjb7Prt8XggFEoe6z5ptx/owFHHCZv2dL49r+F64Ioou30BzL6ew/xKEonVbzzOvplDj8uN
-        QEhMNoVcGhTlazduYvF7CsvpLD4zX1rLYDGVxurvDRR0Hc9fvATl7YHcuvcg7vUP4Es6g6+5n1gvFKFV
-        q3ydUjZRM02cPnOWx363F5S/A3JZHJFfvXuPlV/ryKoqLNvGVrmMXH4LhmXxYnIyk0EURbF2ABzHT9ky
-        K15jt1UMAzYD/FDz0Gs1XtjadrChd3Z2PeWgtvZDyGyq/EYqVrQSB2xoGsxdHdB3nelBdQRmkGeCg40s
-        xwr+FDVeTJF0IM+Xdf4k6oRilnX56PGMXX8CQQTxqiR/SHyEWio3dK1ShWFaoPiWaUX5dUBLS2tBmJiY
-        ivX2nUORtVZi6jfzAhO2p9cFyq8DDh/pesLXw8OjyTt376PChCPldzudx+JjkEbD8Hgvcg32mCRJ8nn3
-        BSwsfILBpkFGMcGe19fvwtDQCILBIKLRaHPI1PR0jEDdbLQ0HYq0p3O62el0wu/3IxKJNIfs99PUIT6f
-        D+HwPs/5F4jH4/m/LghOnZBPTj7EXzBH4FruleOnAAAAAElFTkSuQmCC
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIWSURBVDhPnZNLaxNRFMfni8TWV0Wb+ooLoY9oEg0JjRLQ
+        aalMzSIGUUiqtgqlT1y4cSe4EaHfQFCKCxEEiRUq6sZFJ0XTJEar006aTDJJ5vH3nguBPpIiPXA49945
+        53fP/R9GEDbZjZG7iWA4nDrWddJu338IR50nbNrT+ea8puv+K6Ls8Qcx93Ie75dSSC5/53Hu1Ty63R4E
+        w2KqJeTSVVG+fvMWFn+k8TmTwxfmn1ayWExnsPxHQVHX8fTZc1DeDsjtsQcJX6AfXzNZfMv/wmqxBK1W
+        4+v02jrqponTZ87y2OfxgfK3QC6LQ/KLN2+x9HsVOVWFZdvYqFSQL2zAsCxeTE5mMoiiKNYWgPP4KVtm
+        xSvstqphwGaAn2oBer3OC/e1HWjqHR2djzmorf0gsusqv5GK17QyByiaBnNbB/RdZ3pQHYEZ5IngZCPL
+        s4K/JY0XUyQdyAsVnT+JOqGYY13OzD60G08giCBek+R3yQ9Qy5WmrlVrMEwLFF8zrSi/AXA4HEVhfHwy
+        3tN7DiXWWpmp38qLTNjuHjcovwE4fKTzEV8PDg6n7o3eR5UJR8pvdzqPJ+5AGo7A67vINdhhkiTJ5z0X
+        sLDwEQabBhnFJHteb58bAwNDCIVCiMVirSGT09NxAnWx0dJ0KNKezulml8uFQCCAaDTaGrLbT9OA+P1+
+        RCK7POd/IF6vd29dEJw6IZ+YmMI/H6vgUxqti8IAAAAASUVORK5CYII=
 </value>
   </data>
   <data name="toolStripButton14.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGSSURBVDhPrVPLTsJQEOUvjN/BAhIeG8WfgMQFjRL5Adhp
-        2AsxAvUb2OrKBYmJhGBIdGONmig+K4+CaWl72+I4c6VJDRRcOMlJp+2cM2emt4GAJ6LRaAHxiviagvKC
-        t2ZuHovFVsPh8JuQyWinzaZ51XmCy4dHOKnXWXJze0zvqMZXiLqWqqJ++9EFQmegwH23x/Obdxn2i0WD
-        alyBeDwOiC1+TxbT6bR+J8tIHIBhWUDRU1Vgts1h4rNrSZrUarVj4kwFfkTIXr3RYM/KEEwsprAcBxii
-        VKlQ0UKQA3hRFOhrGifbSOxi94NqdSmZxLmAPBzBQBuDxhi/9lWNk8viEdiTCYdlOyBJEsyMQMs5b7XY
-        p66DFyTgINF9doZjuov8tcRIJLK3k82OVcOAMTqYhxGOl0ylLN8zQYusiKKhogtanhcaCh+Wy3yk9cQG
-        H2EmQqHQCtkTBEG/aLeZYZpAoDyFnd0vkcvl/EVIlcaZd5SpczAY5C6Wivgd138Xyefzi8f5ixPfpS77
-        fYlIWEskdr8BQbKqUTrNYS4AAAAASUVORK5CYII=
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGQSURBVDhPrVPLTsJQEOUvjN/BAhIeG8WPkMQNRon8AOw0
+        7IUYS/Eb2OrKBTGRBAwLXQhGTRSflUfB9Hnb4jhzpUkNFFx4k5NOb+ecOTP3NhDwrGg0mke8Ir4moDjv
+        zZkZx2Kx5XA4/LaZTqun9bp51XmCy4dHOKlW2frGtkbfKMdXiKoWxbJ++9EFQmcgw323x+Obdwn2CwWD
+        clyBeDwOiC3+ThZTqZR+J0lIHIBhWUCrpyjAbJvDxL3rVmtcqVSOiTMR+BEhe9VajT3LQzAxmZblOMAQ
+        xVKJkuaCHMCLLENfVTnZRmIXqx+I4kIyiXMBaTiCgaqByhh/9hWVk4XyEdjjMYdlO9But2GqBRrOeaPB
+        PnUdvCABB4nu3hm26Q7y1xAjkcjeTiajKYYBGjqYhRG2t55MWr53ggYpiKKhoAsanhcqCh8KAm9pNbHG
+        W5haoVBoiezRcV40m8wwTSBQnMTK7klks1l/EVKldmZdZaocDAa5i4Uiftf130Vyudz8dv7ixHeoi35f
+        IhJWEondbwHEqjK0XtPuAAAAAElFTkSuQmCC
 </value>
   </data>
   <metadata name="mgZoomNextComponent1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -688,14 +688,14 @@
   <data name="mgZoomNextComponent1.Icon" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGSSURBVDhPrVPLTsJQEOUvjN/BAhIeG8WfgMQFjRL5Adhp
-        2AsxAvUb2OrKBYmJhGBIdGONmig+K4+CaWl72+I4c6VJDRRcOMlJp+2cM2emt4GAJ6LRaAHxiviagvKC
-        t2ZuHovFVsPh8JuQyWinzaZ51XmCy4dHOKnXWXJze0zvqMZXiLqWqqJ++9EFQmegwH23x/Obdxn2i0WD
-        alyBeDwOiC1+TxbT6bR+J8tIHIBhWUDRU1Vgts1h4rNrSZrUarVj4kwFfkTIXr3RYM/KEEwsprAcBxii
-        VKlQ0UKQA3hRFOhrGifbSOxi94NqdSmZxLmAPBzBQBuDxhi/9lWNk8viEdiTCYdlOyBJEsyMQMs5b7XY
-        p66DFyTgINF9doZjuov8tcRIJLK3k82OVcOAMTqYhxGOl0ylLN8zQYusiKKhogtanhcaCh+Wy3yk9cQG
-        H2EmQqHQCtkTBEG/aLeZYZpAoDyFnd0vkcvl/EVIlcaZd5SpczAY5C6Wivgd138Xyefzi8f5ixPfpS77
-        fYlIWEskdr8BQbKqUTrNYS4AAAAASUVORK5CYII=
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGQSURBVDhPrVPLTsJQEOUvjN/BAhIeG8WPkMQNRon8AOw0
+        7IUYS/Eb2OrKBTGRBAwLXQhGTRSflUfB9Hnb4jhzpUkNFFx4k5NOb+ecOTP3NhDwrGg0mke8Ir4moDjv
+        zZkZx2Kx5XA4/LaZTqun9bp51XmCy4dHOKlW2frGtkbfKMdXiKoWxbJ++9EFQmcgw323x+Obdwn2CwWD
+        clyBeDwOiC3+ThZTqZR+J0lIHIBhWUCrpyjAbJvDxL3rVmtcqVSOiTMR+BEhe9VajT3LQzAxmZblOMAQ
+        xVKJkuaCHMCLLENfVTnZRmIXqx+I4kIyiXMBaTiCgaqByhh/9hWVk4XyEdjjMYdlO9But2GqBRrOeaPB
+        PnUdvCABB4nu3hm26Q7y1xAjkcjeTiajKYYBGjqYhRG2t55MWr53ggYpiKKhoAsanhcqCh8KAm9pNbHG
+        W5haoVBoiezRcV40m8wwTSBQnMTK7klks1l/EVKldmZdZaocDAa5i4Uiftf130Vyudz8dv7ixHeoi35f
+        IhJWEondbwHEqjK0XtPuAAAAAElFTkSuQmCC
 </value>
   </data>
   <data name="toolStripButton6.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Platform.ini
===================================================================
(Binary files differ)

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DescribeSchema.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DescribeSchema.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/DescribeSchema.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -55,6 +55,11 @@
         // The reference to the FDO connection from the MgdFeatureConnection object must be cleaned up before the parent object
         // otherwise it leaves the FDO connection marked as still in use.
         FdoPtr<FdoIConnection> fdoConn = connection->GetConnection();
+
+        // Ensure all user-defined functions are loaded 
+        FdoPtr<FdoIExpressionCapabilities> ec = fdoConn->GetExpressionCapabilities();
+        FdoPtr<FdoFunctionDefinitionCollection> funcs = ec->GetFunctions();
+
         FdoPtr<FdoIDescribeSchema> fdoCommand = (FdoIDescribeSchema*)fdoConn->CreateCommand(FdoCommandType_DescribeSchema);
 
         classNameHintUsed = IsClassNameHintUsed(fdoCommand);

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectCommand.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -424,16 +424,26 @@
 
     MG_FEATURE_SERVICE_TRY()
 
+#ifdef DEBUG_FDO_JOIN
+    FdoPtr<FdoIdentifierCollection> cmdPropNames = m_command->GetPropertyNames();
+    for (FdoInt32 i = 0; i < cmdPropNames->GetCount(); i++)
+    {
+        FdoPtr<FdoIdentifier> ident = cmdPropNames->GetItem(i);
+        STRING idStr = ident->ToString();
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) [FdoISelect]: (%W)"), idStr.c_str()));
+    }
+#endif
+
     FdoPtr<FdoIFeatureReader> fdoReader = m_command->Execute();
     if (bForceOneToOne)
     {
         FdoPtr<FdoStringCollection> names = MgdFeatureUtil::MgToFdoStringCollection(idPropNames, false);
         FdoPtr<FdoIFeatureReader> forcedReader = new MgdFdoForcedOneToOneFeatureReader(fdoReader, names); 
-        ret = new MgdFeatureReader(m_connection, forcedReader);
+        ret = new MgdFeatureReader(m_connection, forcedReader, idPropNames);
     }
     else
     {
-        ret = new MgdFeatureReader(m_connection, fdoReader);
+        ret = new MgdFeatureReader(m_connection, fdoReader, idPropNames);
     }
     MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgdSelectCommand.ExecuteJoined")
 

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -48,6 +48,7 @@
 
     // Set a default join query batch size
     m_nJoinQueryBatchSize = MgdConfigProperties::DefaultFeatureServicePropertyJoinQueryBatchSize;
+    m_bUseFdoJoinOptimization = MgdConfigProperties::DefaultFeatureServicePropertyUseFdoJoinOptimization; 
 
     MgConfiguration* config = MgConfiguration::GetInstance();
     if(config)
@@ -62,6 +63,11 @@
                             MgdConfigProperties::FeatureServicePropertyDataCacheSize,
                             m_nDataCacheSize,
                             MgdConfigProperties::DefaultFeatureServicePropertyDataCacheSize);
+        // Get FDO Join use flag 
+ 	    config->GetBoolValue(MgdConfigProperties::FeatureServicePropertiesSection, 
+                             MgdConfigProperties::FeatureServicePropertyUseFdoJoinOptimization, 
+                             m_bUseFdoJoinOptimization, 
+                             MgdConfigProperties::DefaultFeatureServicePropertyUseFdoJoinOptimization); 
     }
 }
 
@@ -183,7 +189,7 @@
 
             MgStringCollection arguments;
             arguments.Add(message);
-            throw new MgFeatureServiceException(L"MgServerSelectFeatures.SelectFeatures", __LINE__, __WFILE__, &arguments, L"", NULL);
+            throw new MgFeatureServiceException(L"MgdSelectFeatures.SelectFeatures", __LINE__, __WFILE__, &arguments, L"", NULL);
         }
 
         // Custom function specified using SelectAggregate,
@@ -323,7 +329,7 @@
         else
             reader = m_command->Execute();
 
-        CHECKNULL((MgReader*)reader, L"MgServerSelectFeatures.SelectFeatures");
+        CHECKNULL((MgReader*)reader, L"MgdSelectFeatures.SelectFeatures");
 
         if (executeSelectAggregate && m_customPropertyFound)
         {
@@ -340,7 +346,7 @@
         }
     }
 
-    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgServerSelectFeatures.SelectFeatures")
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgdSelectFeatures.SelectFeatures")
 
     return mgReader.Detach();
 }
@@ -348,7 +354,7 @@
 
 void MgdSelectFeatures::ApplyQueryOptions(bool isSelectAggregate)
 {
-    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyQueryOptions");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyQueryOptions");
 
     if (m_options != NULL)
     {
@@ -365,8 +371,8 @@
 // ClassProperties
 void MgdSelectFeatures::ApplyClassProperties()
 {
-    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyClassProperties");
-    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyClassProperties");
+    CHECKNULL(m_options, L"MgdSelectFeatures.ApplyClassProperties");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyClassProperties");
 
     Ptr<MgStringCollection> properties = m_options->GetClassProperties();
 
@@ -381,25 +387,76 @@
     //secondary properties.
 
     FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
-    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyClassProperties");
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgdSelectFeatures.ApplyClassProperties");
 
     for (INT32 i=0; i < cnt; i++)
     {
         STRING propertyName = properties->GetItem(i);
 
         FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
-        CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyClassProperties");
+        CHECKNULL((FdoIdentifier*)fdoIden, L"MgdSelectFeatures.ApplyClassProperties");
 
         fic->Add(fdoIden);
     }
 }
 
+void MgdSelectFeatures::ApplyClassPropertiesForFdoJoin(CREFSTRING primaryAlias, CREFSTRING secondaryAlias, CREFSTRING secondaryPrefix)
+{
+    CHECKNULL(m_options, L"MgdSelectFeatures.ApplyClassPropertiesForFdoJoin");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyClassPropertiesForFdoJoin");
 
+    Ptr<MgStringCollection> properties = m_options->GetClassProperties();
+
+    if (properties == NULL)
+        return; // Nothing to do
+
+    INT32 cnt = properties->GetCount();
+    if (cnt <= 0)
+        return; // Nothing to do
+
+    FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgdSelectFeatures.ApplyClassPropertiesForFdoJoin");
+
+    //If we're given an explicit property list, it will be whatever is presented by the Extended Feature Class
+    //So we have to "re-shape" this property list into a aliased qualified property list like the standard FDO
+    //join query. Basically, were doing a reverse property mapping.
+
+    for (INT32 i=0; i < cnt; i++)
+    {
+        STRING propertyName = properties->GetItem(i);
+
+        //Check if this name starts with prefix
+        //
+        // If it does, it's a secondary join property and should be re-aliased as [secondaryAlias].[propertyNameWithoutPrefix]
+        // Otherwise, it should be re-aliased as [primaryAlias].[propertyNameAsIs]
+        STRING reAliasedPropName;
+        if (propertyName.compare(0, secondaryPrefix.length(), secondaryPrefix) == 0)
+        {
+            reAliasedPropName = secondaryAlias;
+            reAliasedPropName += L".";
+            reAliasedPropName += propertyName.substr(secondaryPrefix.length());
+        }
+        else
+        {
+            reAliasedPropName = primaryAlias;
+            reAliasedPropName += L".";
+            reAliasedPropName += propertyName;
+        }
+
+        //This will now be [alias].[reAliasedPropertyName] AS [propertyName]
+        FdoPtr<FdoExpression> expr = FdoExpression::Parse((FdoString*)reAliasedPropName.c_str());
+        FdoPtr<FdoComputedIdentifier> fdoIden = FdoComputedIdentifier::Create((FdoString*)propertyName.c_str(), expr);
+        CHECKNULL((FdoComputedIdentifier*)fdoIden, L"MgdSelectFeatures.ApplyClassPropertiesForFdoJoin");
+
+        fic->Add(fdoIden);
+    }
+}
+
 // Computed properties
 void MgdSelectFeatures::ApplyComputedProperties()
 {
-    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyComputedProperties");
-    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyComputedProperties");
+    CHECKNULL(m_options, L"MgdSelectFeatures.ApplyComputedProperties");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyComputedProperties");
 
     Ptr<MgStringPropertyCollection> properties = m_options->GetComputedProperties();
 
@@ -424,7 +481,7 @@
         if (str != NULL)
         {
             FdoPtr<FdoExpression> expression = FdoExpression::Parse(str);
-            CHECKNULL((FdoExpression*)expression, L"MgServerSelectFeatures.ApplyComputedProperties");
+            CHECKNULL((FdoExpression*)expression, L"MgdSelectFeatures.ApplyComputedProperties");
 
             bool udf = ContainsUdf(expression);
             if (!udf)
@@ -442,8 +499,8 @@
 //// Filter text
 //void MgdSelectFeatures::ApplyFilter()
 //{
-//    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyFilter");
-//    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFilter");
+//    CHECKNULL(m_options, L"MgdSelectFeatures.ApplyFilter");
+//    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyFilter");
 //
 //    STRING filterText = m_options->GetFilter();
 //    if (filterText.empty()) { return; } // Nothing to do
@@ -454,7 +511,7 @@
 // Fetch size
 void MgdSelectFeatures::ApplyFetchSize()
 {
-    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFetchSize");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyFetchSize");
     if(m_options)
         m_command->SetFetchSize(m_options->GetFetchSize());
     else
@@ -464,8 +521,8 @@
 // Spatial Filter
 void MgdSelectFeatures::ApplyFilter()
 {
-    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyFilter");
-    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFilter");
+    CHECKNULL(m_options, L"MgdSelectFeatures.ApplyFilter");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyFilter");
 
     FdoPtr<FdoFilter> regularFilter;
     FdoPtr<FdoSpatialCondition> spatialFilter;
@@ -477,7 +534,7 @@
     if (!filterText.empty())
     {
         regularFilter = FdoFilter::Parse(filterText.c_str());
-        #ifdef _DEBUG
+        #if defined(_DEBUG) || defined(DEBUG_FDO_JOIN)
         ACE_DEBUG((LM_ERROR, ACE_TEXT("FILTER(size=%d):\n%W\n\n"), filterText.length(), filterText.c_str()));
         #endif
     }
@@ -557,8 +614,8 @@
 // Ordering options
 void MgdSelectFeatures::ApplyOrderingOptions()
 {
-    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyOrderingOptions");
-    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyOrderingOptions");
+    CHECKNULL(m_options, L"MgdSelectFeatures.ApplyOrderingOptions");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyOrderingOptions");
 
     Ptr<MgStringCollection> properties = m_options->GetOrderingProperties();
 
@@ -576,11 +633,11 @@
 
         MgStringCollection arguments;
         arguments.Add(message);
-        throw new MgFeatureServiceException(L"MgServerSelectFeatures.ApplyOrderingOptions", __LINE__, __WFILE__, &arguments, L"", NULL);
+        throw new MgFeatureServiceException(L"MgdSelectFeatures.ApplyOrderingOptions", __LINE__, __WFILE__, &arguments, L"", NULL);
     }
 
     FdoPtr<FdoIdentifierCollection> fic = m_command->GetOrdering();
-    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyOrderingOptions");
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgdSelectFeatures.ApplyOrderingOptions");
 
     // Order option Asc or Desc (default is Asc)
     FdoOrderingOption option = MgdFeatureUtil::GetFdoOrderingOption(m_options->GetOrderOption());
@@ -593,7 +650,7 @@
         if (!propertyName.empty())
         {
             FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
-            CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyOrderingOptions");
+            CHECKNULL((FdoIdentifier*)fdoIden, L"MgdSelectFeatures.ApplyOrderingOptions");
 
             fic->Add(fdoIden);
         }
@@ -647,13 +704,13 @@
 void MgdSelectFeatures::AddFdoComputedProperty(CREFSTRING aliasName, FdoExpression* expression)
 {
     FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
-    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.AddFdoComputedProperty");
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgdSelectFeatures.AddFdoComputedProperty");
 
     FdoString* expName = aliasName.c_str();
     if (expName != NULL)
     {
         FdoPtr<FdoComputedIdentifier> fdoIden = FdoComputedIdentifier::Create(expName, expression);
-        CHECKNULL((FdoComputedIdentifier*)fdoIden, L"MgServerSelectFeatures.AddFdoComputedProperty");
+        CHECKNULL((FdoComputedIdentifier*)fdoIden, L"MgdSelectFeatures.AddFdoComputedProperty");
 
         fic->Add(fdoIden);
     }
@@ -661,10 +718,10 @@
 
 void MgdSelectFeatures::AddCustomComputedProperty(CREFSTRING aliasName, FdoExpression* expression)
 {
-    CHECKNULL((FdoExpression*)expression, L"MgServerSelectFeatures.AddCustomComputedProperty");
+    CHECKNULL((FdoExpression*)expression, L"MgdSelectFeatures.AddCustomComputedProperty");
 
     FdoPtr<FdoIdentifierCollection> fic = m_command->GetPropertyNames();
-    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.AddCustomComputedProperty");
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgdSelectFeatures.AddCustomComputedProperty");
 
     // If property is already found, two custom properties are not supported and therefore throw exception
     if (m_customPropertyFound)
@@ -673,7 +730,7 @@
 
         MgStringCollection arguments;
         arguments.Add(message);
-        throw new MgFeatureServiceException(L"MgServerSelectFeatures.AddCustomComputedProperty", __LINE__, __WFILE__, &arguments, L"", NULL);
+        throw new MgFeatureServiceException(L"MgdSelectFeatures.AddCustomComputedProperty", __LINE__, __WFILE__, &arguments, L"", NULL);
     }
 
     // Downcast to FdoFunction
@@ -731,7 +788,7 @@
 
                 MgStringCollection arguments;
                 arguments.Add(message);
-                throw new MgFeatureServiceException(L"MgServerSelectFeatures.ValidateConstraintsOnCustomFunctions",
+                throw new MgFeatureServiceException(L"MgdSelectFeatures.ValidateConstraintsOnCustomFunctions",
                     __LINE__, __WFILE__, &arguments, L"", NULL);
             }
             MgdFeatureUtil::ValidateCustomConstraints(m_customFunction);
@@ -750,7 +807,7 @@
     {
         m_command = MgdFeatureServiceCommand::CreateCommand(resource, FdoCommandType_SelectAggregates);
     }
-    CHECKNULL((MgdFeatureServiceCommand*)m_command, L"MgServerSelectFeatures.CreateCommand");
+    CHECKNULL((MgdFeatureServiceCommand*)m_command, L"MgdSelectFeatures.CreateCommand");
 }
 
 void MgdSelectFeatures::ValidateParam(MgResourceIdentifier* resource, CREFSTRING className)
@@ -811,8 +868,8 @@
 
 void MgdSelectFeatures::ApplyFdoGroupingProperties(MgStringCollection* propertyNames)
 {
-    CHECKNULL(m_options, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
-    CHECKNULL(m_command, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
+    CHECKNULL(m_options, L"MgdSelectFeatures.ApplyFdoGroupingProperties");
+    CHECKNULL(m_command, L"MgdSelectFeatures.ApplyFdoGroupingProperties");
 
     Ptr<MgStringCollection> properties = SAFE_ADDREF(propertyNames);
 
@@ -830,18 +887,18 @@
 
         MgStringCollection arguments;
         arguments.Add(message);
-        throw new MgFeatureServiceException(L"MgServerSelectFeatures.ApplyFdoGroupingProperties", __LINE__, __WFILE__, &arguments, L"", NULL);
+        throw new MgFeatureServiceException(L"MgdSelectFeatures.ApplyFdoGroupingProperties", __LINE__, __WFILE__, &arguments, L"", NULL);
     }
 
     FdoPtr<FdoIdentifierCollection> fic = ((MgdFeatureServiceCommand*)m_command)->GetGrouping();
-    CHECKNULL((FdoIdentifierCollection*)fic, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
+    CHECKNULL((FdoIdentifierCollection*)fic, L"MgdSelectFeatures.ApplyFdoGroupingProperties");
 
     for (INT32 i=0; i < cnt; i++)
     {
         STRING propertyName = properties->GetItem(i);
 
         FdoPtr<FdoIdentifier> fdoIden = FdoIdentifier::Create((FdoString*)propertyName.c_str());
-        CHECKNULL((FdoIdentifier*)fdoIden, L"MgServerSelectFeatures.ApplyFdoGroupingProperties");
+        CHECKNULL((FdoIdentifier*)fdoIden, L"MgdSelectFeatures.ApplyFdoGroupingProperties");
 
         fic->Add(fdoIden);
     }
@@ -873,7 +930,7 @@
         if (str != NULL)
         {
             FdoPtr<FdoExpression> expression = FdoExpression::Parse(str);
-            CHECKNULL((FdoExpression*)expression, L"MgServerSelectFeatures.ContainsCustomFunction");
+            CHECKNULL((FdoExpression*)expression, L"MgdSelectFeatures.ContainsCustomFunction");
 
             hasCustomFunction = ContainsUdf(expression);
         }
@@ -886,7 +943,7 @@
 
         MgStringCollection arguments;
         arguments.Add(message);
-        throw new MgFeatureServiceException(L"MgServerSelectFeatures.ContainsCustomFunction",
+        throw new MgFeatureServiceException(L"MgdSelectFeatures.ContainsCustomFunction",
             __LINE__, __WFILE__, &arguments, L"", NULL);
     }
 
@@ -913,15 +970,15 @@
 {
     bool bCalculationExists = false;
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.FindFeatureCalculation");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.FindFeatureCalculation");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.FindFeatureCalculation");
+    CHECKNULL(extensions, L"MgdSelectFeatures.FindFeatureCalculation");
 
     for (int i = 0; i < extensions->GetCount(); i++)
     {
         MdfModel::Extension* extension = extensions->GetAt(i);
-        CHECKNULL(extension, L"MgServerSelectFeatures.FindFeatureCalculation");
+        CHECKNULL(extension, L"MgdSelectFeatures.FindFeatureCalculation");
         STRING name = (STRING)extension->GetName();
 
         STRING parsedSchemaName, parsedExtensionName;
@@ -948,15 +1005,15 @@
 {
     bool bJoinPropertiesExists = false;
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.FindFeatureJoinProperties");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.FindFeatureJoinProperties");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.FindFeatureJoinProperties");
+    CHECKNULL(extensions, L"MgdSelectFeatures.FindFeatureJoinProperties");
 
     for (int i = 0; i < extensions->GetCount(); i++)
     {
         MdfModel::Extension* extension = extensions->GetAt(i);
-        CHECKNULL(extension, L"MgServerSelectFeatures.FindFeatureJoinProperties");
+        CHECKNULL(extension, L"MgdSelectFeatures.FindFeatureJoinProperties");
         STRING name = (STRING)extension->GetName();
 
         STRING parsedSchemaName, parsedExtensionName;
@@ -981,15 +1038,15 @@
 {
     MG_FEATURE_SERVICE_TRY()
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.UpdateCommandOnJoinCalculation");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation");
+    CHECKNULL(extensions, L"MgdSelectFeatures.UpdateCommandOnJoinCalculation");
 
     for (int i = 0; i < extensions->GetCount(); i++)
     {
         MdfModel::Extension* extension = extensions->GetAt(i);
-        CHECKNULL(extension, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation");
+        CHECKNULL(extension, L"MgdSelectFeatures.UpdateCommandOnJoinCalculation");
         STRING name = (STRING)extension->GetName();
 
         STRING parsedSchemaName, parsedExtensionName;
@@ -1042,22 +1099,22 @@
             break;
         }
     }
-    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceId, L"MgServerSelectFeatures.UpdateCommandOnJoinCalculation")
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceId, L"MgdSelectFeatures.UpdateCommandOnJoinCalculation")
 }
 
 void MgdSelectFeatures::UpdateCommandOnCalculation(MgResourceIdentifier* featureSourceId, CREFSTRING extensionName)
 {
     MG_FEATURE_SERVICE_TRY()
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.UpdateCommandOnCalculation");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.UpdateCommandOnCalculation");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.UpdateCommandOnCalculation");
+    CHECKNULL(extensions, L"MgdSelectFeatures.UpdateCommandOnCalculation");
 
     for (int i = 0; i < extensions->GetCount(); i++)
     {
         MdfModel::Extension* extension = extensions->GetAt(i);
-        CHECKNULL(extension, L"MgServerSelectFeatures.UpdateCommandOnCalculation");
+        CHECKNULL(extension, L"MgdSelectFeatures.UpdateCommandOnCalculation");
         STRING name = (STRING)extension->GetName();
 
         STRING parsedSchemaName, parsedExtensionName;
@@ -1177,7 +1234,7 @@
             break;
         }
     }
-    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceId, L"MgServerSelectFeatures.UpdateCommandOnCalculation")
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceId, L"MgdSelectFeatures.UpdateCommandOnCalculation")
 }
 
 MgdGwsFeatureReader* MgdSelectFeatures::JoinFeatures(MgResourceIdentifier* featureSourceIdentifier, CREFSTRING extensionName, FdoFilter* filter)
@@ -1189,15 +1246,15 @@
     FdoPtr<IGWSQueryDefinition> qd;
     FdoPtr<MgdGwsConnectionPool> pool = MgdGwsConnectionPool::Create();
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.JoinFeatures");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.JoinFeatures");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.JoinFeatures");
+    CHECKNULL(extensions, L"MgdSelectFeatures.JoinFeatures");
 
     for (int i = 0; i < extensions->GetCount(); i++)
     {
         MdfModel::Extension* extension = extensions->GetAt(i);
-        CHECKNULL(extension, L"MgServerSelectFeatures.JoinFeatures");
+        CHECKNULL(extension, L"MgdSelectFeatures.JoinFeatures");
         STRING name = (STRING)extension->GetName();
 
         STRING parsedSchemaName, parsedExtensionName;
@@ -1219,7 +1276,7 @@
             }
             else
             {
-                throw new MgdConnectionFailedException(L"MgServerSelectFeatures.JoinFeatures",
+                throw new MgdConnectionFailedException(L"MgdSelectFeatures.JoinFeatures",
                     __LINE__, __WFILE__, NULL, L"", NULL);
             }
 
@@ -1306,13 +1363,13 @@
                 lsellist,
                 GWSQualifiedName(primaryConnectionName.c_str(), primaryFsSchema.c_str(), primaryFsClassName.c_str()),
                 lfilter);
-            CHECKNULL(lqd, L"MgServerSelectFeatures.JoinFeatures");
+            CHECKNULL(lqd, L"MgdSelectFeatures.JoinFeatures");
             qd = lqd;
 
             IGWSJoinQueryDefinition* jqd = NULL;
 
             MdfModel::AttributeRelateCollection* attributeRelates = extension->GetAttributeRelates();
-            CHECKNULL(attributeRelates, L"MgServerSelectFeatures.JoinFeatures");
+            CHECKNULL(attributeRelates, L"MgdSelectFeatures.JoinFeatures");
 
             bool bForceOneToOne = true;
             Ptr<MgStringCollection> attributeNameDelimiters = new MgStringCollection();
@@ -1325,7 +1382,7 @@
             for (int attributeRelateIndex = 0; attributeRelateIndex < attributeRelates->GetCount(); attributeRelateIndex++)
             {
                 MdfModel::AttributeRelate* attributeRelate = attributeRelates->GetAt(attributeRelateIndex);
-                CHECKNULL(attributeRelate, L"MgServerSelectFeatures.JoinFeatures");
+                CHECKNULL(attributeRelate, L"MgdSelectFeatures.JoinFeatures");
 
                 // Get the secondary resource id
                 STRING secondaryResourceId = (STRING)attributeRelate->GetResourceId();
@@ -1366,7 +1423,7 @@
                     }
                     else
                     {
-                        throw new MgdConnectionFailedException(L"MgServerSelectFeatures.JoinFeatures",
+                        throw new MgdConnectionFailedException(L"MgdSelectFeatures.JoinFeatures",
                             __LINE__, __WFILE__, NULL, L"", NULL);
                     }
                 }
@@ -1386,7 +1443,7 @@
                     rsellist,
                     GWSQualifiedName(secondaryConnectionName.c_str(), secondaryFsSchema.c_str(), secondaryFsClassName.c_str()),
                     rfilter);
-                CHECKNULL(rqd, L"MgServerSelectFeatures.JoinFeatures");
+                CHECKNULL(rqd, L"MgdSelectFeatures.JoinFeatures");
 
                 // Get Join Attributes
                 FdoPtr<FdoStringCollection> lattrs = FdoStringCollection::Create();
@@ -1394,14 +1451,14 @@
 
                 // Determine the number of RelateProperties (attributes)
                 MdfModel::RelatePropertyCollection* relateProperties = attributeRelate->GetRelateProperties();
-                CHECKNULL(relateProperties, L"MgServerSelectFeatures.JoinFeatures");
+                CHECKNULL(relateProperties, L"MgdSelectFeatures.JoinFeatures");
                 int nRelatePropertyCount = relateProperties->GetCount();
 
                 // For each RelateProperty need to do the following
                 for (int relatePropertyIndex = 0; relatePropertyIndex < nRelatePropertyCount; relatePropertyIndex++)
                 {
                     MdfModel::RelateProperty* relateProperty = relateProperties->GetAt(relatePropertyIndex);
-                    CHECKNULL(relateProperty, L"MgServerSelectFeatures.JoinFeatures");
+                    CHECKNULL(relateProperty, L"MgdSelectFeatures.JoinFeatures");
 
                     // Get the FeatureClassProperty (primary attribute)
                     STRING primaryAttribute = (STRING)relateProperty->GetFeatureClassProperty();
@@ -1482,7 +1539,7 @@
         }
     }
 
-    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceIdentifier, L"MgServerSelectFeatures.JoinFeatures")
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(featureSourceIdentifier, L"MgdSelectFeatures.JoinFeatures")
 
     // Now that the reader has been created we will need to mark all of the connections it uses as OwnReader() because the GWS reader will be
     // taking ownership of the connections. We have to do it this late in the code in case an exception is thrown somewhere before this.
@@ -1494,7 +1551,7 @@
 
 void MgdSelectFeatures::ParseQualifiedClassNameForCalculation(MdfModel::Extension* extension, CREFSTRING qualifiedClassName, STRING& schemaName, STRING& className)
 {
-    CHECKNULL(extension, L"MgServerSelectFeatures.ParseQualifiedClassNameForCalculation");
+    CHECKNULL(extension, L"MgdSelectFeatures.ParseQualifiedClassNameForCalculation");
 
     MgUtil::ParseQualifiedClassName(qualifiedClassName, schemaName, className);
 
@@ -1510,15 +1567,15 @@
 {
     Ptr<MgResourceIdentifier> secResId;
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.GetSecondaryResourceIdentifier");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+    CHECKNULL(extensions, L"MgdSelectFeatures.GetSecondaryResourceIdentifier");
 
     for (int i = 0; i < extensions->GetCount(); i++)
     {
         MdfModel::Extension* extension = extensions->GetAt(i);
-        CHECKNULL(extension, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+        CHECKNULL(extension, L"MgdSelectFeatures.GetSecondaryResourceIdentifier");
 
         // Get the extension name
         STRING name = (STRING)extension->GetName();
@@ -1534,7 +1591,7 @@
         {
             // Determine the number of secondary sources (AttributeRelates)
             MdfModel::AttributeRelateCollection* attributeRelates = extension->GetAttributeRelates();
-            CHECKNULL(attributeRelates, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+            CHECKNULL(attributeRelates, L"MgdSelectFeatures.GetSecondaryResourceIdentifier");
             int nAttributeRelateCount = attributeRelates->GetCount();
 
             // Find the specified relation name
@@ -1542,7 +1599,7 @@
                 for (int attributeRelateIndex = 0; attributeRelateIndex < nAttributeRelateCount; attributeRelateIndex++)
                 {
                     MdfModel::AttributeRelate* attributeRelate = attributeRelates->GetAt(attributeRelateIndex);
-                    CHECKNULL(attributeRelate, L"MgServerSelectFeatures.GetSecondaryResourceIdentifier");
+                    CHECKNULL(attributeRelate, L"MgdSelectFeatures.GetSecondaryResourceIdentifier");
 
                     // Get the name for the join relationship
                     STRING attributeRelateName = (STRING)attributeRelate->GetName();
@@ -1570,6 +1627,10 @@
 {
     bool bSupported = false;
 
+    //If disabled on a global level, don't even bother continuing 
+    if (!m_bUseFdoJoinOptimization)
+        return false;
+
     MG_FEATURE_SERVICE_TRY()
 
     //This could be qualified, so parse it to be sure
@@ -1577,10 +1638,10 @@
     STRING extName;
     MgUtil::ParseQualifiedClassName(extensionName, schemaName, extName);
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.SupportsFdoJoin");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.SupportsFdoJoin");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.SupportsFdoJoin");
+    CHECKNULL(extensions, L"MgdSelectFeatures.SupportsFdoJoin");
 
     MdfModel::Extension* extension = NULL;
     for (INT32 i = 0; i < extensions->GetCount(); i++) 
@@ -1605,7 +1666,7 @@
     {
         if (!conn->IsConnectionOpen())
         {
-            throw new MgdConnectionFailedException(L"MgServerSelectFeatures.SupportsFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
+            throw new MgdConnectionFailedException(L"MgdSelectFeatures.SupportsFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
         }
 
         FdoPtr<FdoIConnection> fdoConn = conn->GetConnection();
@@ -1751,7 +1812,7 @@
         bSupported = true;
     }
 
-    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerSelectFeatures.SupportsFdoJoin")
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgdSelectFeatures.SupportsFdoJoin")
 
     return bSupported;
 }
@@ -1763,7 +1824,7 @@
         return true; //Inconsequential
 
     FdoPtr<FdoIDescribeSchema> descSchema = dynamic_cast<FdoIDescribeSchema*>(fdoConn->CreateCommand(FdoCommandType_DescribeSchema));
-    CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgServerSelectFeatures.SelectFdoJoin");
+    CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgdSelectFeatures.SelectFdoJoin");
 
     if (!schemaName.empty())
     {
@@ -1799,7 +1860,7 @@
     if (NULL == (FdoClassDefinition*)classDef)
     {
         //TODO: Refine message if available
-        throw new MgClassNotFoundException(L"MgServerSelectFeatures.IsFunctionOnPrimaryProperty", __LINE__, __WFILE__, NULL, L"", NULL);
+        throw new MgClassNotFoundException(L"MgdSelectFeatures.IsFunctionOnPrimaryProperty", __LINE__, __WFILE__, NULL, L"", NULL);
     }
 
     FdoPtr<FdoPropertyDefinitionCollection> properties = classDef->GetProperties();
@@ -1831,13 +1892,13 @@
     {
         if (!conn->IsConnectionOpen())
         {
-            throw new MgdConnectionFailedException(L"MgServerSelectFeatures.SupportsFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
+            throw new MgdConnectionFailedException(L"MgdSelectFeatures.SupportsFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
         }
 
         FdoPtr<FdoIConnection> fdoConn = conn->GetConnection();
 
         FdoPtr<FdoIDescribeSchema> descSchema = dynamic_cast<FdoIDescribeSchema*>(fdoConn->CreateCommand(FdoCommandType_DescribeSchema));
-        CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgServerSelectFeatures.SelectFdoJoin");
+        CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgdSelectFeatures.SelectFdoJoin");
 
         if (!secondarySchema.empty())
         {
@@ -1873,7 +1934,7 @@
         if (NULL == (FdoClassDefinition*)classDef)
         {
             //TODO: Refine message if available
-            throw new MgClassNotFoundException(L"MgServerSelectFeatures.FilterContainsSecondaryProperties", __LINE__, __WFILE__, NULL, L"", NULL);
+            throw new MgClassNotFoundException(L"MgdSelectFeatures.FilterContainsSecondaryProperties", __LINE__, __WFILE__, NULL, L"", NULL);
         }
 
         FdoPtr<FdoPropertyDefinitionCollection> propDefs = classDef->GetProperties();
@@ -1904,10 +1965,10 @@
     STRING extName;
     MgUtil::ParseQualifiedClassName(extensionName, schemaName, extName);
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.SelectFdoJoin");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.SelectFdoJoin");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.SelectFdoJoin");
+    CHECKNULL(extensions, L"MgdSelectFeatures.SelectFdoJoin");
 
     MdfModel::Extension* extension = NULL;
     for (INT32 i = 0; i < extensions->GetCount(); i++) 
@@ -1920,10 +1981,14 @@
         }
     }
 
-    CHECKNULL(extension, L"MgServerSelectFeatures.SelectFdoJoin");
-    m_command->SetFeatureClassName(extension->GetFeatureClass().c_str());
+    CHECKNULL(extension, L"MgdSelectFeatures.SelectFdoJoin");
+    FdoString* clsName = extension->GetFeatureClass().c_str();
+    m_command->SetFeatureClassName(clsName);
+#ifdef DEBUG_FDO_JOIN
+    ACE_DEBUG((LM_INFO, ACE_TEXT("\n\t(%t) [FdoISelect] Set primary feature class: %W"), clsName));
+#endif
     MdfModel::AttributeRelateCollection* relates = extension->GetAttributeRelates();
-    CHECKNULL(relates, L"MgServerSelectFeatures.SelectFdoJoin");
+    CHECKNULL(relates, L"MgdSelectFeatures.SelectFdoJoin");
     MdfModel::AttributeRelate* relate = relates->GetAt(0);
 
     const MdfModel::MdfString& prefix = relate->GetName();
@@ -1950,20 +2015,18 @@
     {
         if (!conn->IsConnectionOpen())
         {
-            throw new MgdConnectionFailedException(L"MgServerSelectFeatures.SelectFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
+            throw new MgdConnectionFailedException(L"MgdSelectFeatures.SelectFdoJoin", __LINE__, __WFILE__, NULL, L"", NULL);
         }
 
-        CHECKNULL(m_command, L"MgServerSelectFeatures.SelectFdoJoin");
+        CHECKNULL(m_command, L"MgdSelectFeatures.SelectFdoJoin");
         FdoPtr<FdoIConnection> fdoConn = conn->GetConnection();
 
         bool bAppliedProperties = false;
         if (m_options != NULL)
         {
-            //ApplyClassProperties();
             ApplyComputedProperties();
             // TODO: We need to find out if there are any filters involving the secondary side
             ApplyFilter();
-            // ApplySpatialFilter();
             ApplyOrderingOptions();
             // We don't apply aggregate options here because these go through the FDO Expression Engine
             ApplyAggregateOptions(isAggregate);
@@ -1974,7 +2037,7 @@
             Ptr<MgStringCollection> props = m_options->GetClassProperties();
             if (props->GetCount() > 0)
             {
-                ApplyClassProperties();
+                ApplyClassPropertiesForFdoJoin(primaryAlias, secondaryAlias, prefix);
                 bAppliedProperties = true;
             }
         }
@@ -2056,7 +2119,7 @@
     else
         ret = ((MgdSelectCommand*)m_command.p)->ExecuteJoined(idPropNames, bForceOneToOne);
 
-    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgServerSelectFeatures.SelectFdoJoin")
+    MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgdSelectFeatures.SelectFdoJoin")
 
     return ret.Detach();
 }
@@ -2072,10 +2135,10 @@
     STRING extName;
     MgUtil::ParseQualifiedClassName(extensionName, schemaName, extName);
 
-    CHECKNULL(m_featureSourceCacheItem.p, L"MgServerSelectFeatures.SupportsFdoJoin");
+    CHECKNULL(m_featureSourceCacheItem.p, L"MgdSelectFeatures.SupportsFdoJoin");
     MdfModel::FeatureSource* featureSource = m_featureSourceCacheItem->Get();
     MdfModel::ExtensionCollection* extensions = featureSource->GetExtensions();
-    CHECKNULL(extensions, L"MgServerSelectFeatures.SupportsFdoJoin");
+    CHECKNULL(extensions, L"MgdSelectFeatures.SupportsFdoJoin");
 
     MdfModel::Extension* extension = NULL;
     for (INT32 i = 0; i < extensions->GetCount(); i++) 
@@ -2088,10 +2151,10 @@
         }
     }
 
-    CHECKNULL(extension, L"MgServerSelectFeatures.SelectFdoJoin");
+    CHECKNULL(extension, L"MgdSelectFeatures.SelectFdoJoin");
     m_command->SetFeatureClassName(extension->GetFeatureClass().c_str());
     MdfModel::AttributeRelateCollection* relates = extension->GetAttributeRelates();
-    CHECKNULL(relates, L"MgServerSelectFeatures.SelectFdoJoin");
+    CHECKNULL(relates, L"MgdSelectFeatures.SelectFdoJoin");
     MdfModel::AttributeRelate* relate = relates->GetAt(0);
 
     const MdfModel::MdfString& prefix = relate->GetName();
@@ -2156,7 +2219,7 @@
 void MgdSelectFeatures::ApplyClassProperties(FdoIConnection* fdoConn, CREFSTRING schemaName, CREFSTRING className, MgStringCollection* idPropNames, CREFSTRING alias, CREFSTRING prefix)
 {
     FdoPtr<FdoIDescribeSchema> descSchema = dynamic_cast<FdoIDescribeSchema*>(fdoConn->CreateCommand(FdoCommandType_DescribeSchema));
-    CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgServerSelectFeatures.SelectFdoJoin");
+    CHECKNULL((FdoIDescribeSchema*)descSchema, L"MgdSelectFeatures.SelectFdoJoin");
 
     if (!schemaName.empty())
     {
@@ -2192,7 +2255,7 @@
     if (NULL == (FdoClassDefinition*)classDef)
     {
         //TODO: Refine message if available
-        throw new MgClassNotFoundException(L"MgServerSelectFeatures.ApplyClassProperties", __LINE__, __WFILE__, NULL, L"", NULL);
+        throw new MgClassNotFoundException(L"MgdSelectFeatures.ApplyClassProperties", __LINE__, __WFILE__, NULL, L"", NULL);
     }
 
     FdoPtr<FdoIdentifierCollection> propNames = m_command->GetPropertyNames();

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/SelectFeatures.h	2013-03-22 12:10:42 UTC (rev 7409)
@@ -95,8 +95,12 @@
     INT32 m_nJoinQueryBatchSize;
 
     INT32 m_nDataCacheSize;
+    // This is the overriding flag that decides if we should test for and use the FDO Join 
+    // APIs if possible 
+    bool m_bUseFdoJoinOptimization; 
 
     // FDO join optimization
+    void ApplyClassPropertiesForFdoJoin(CREFSTRING primaryAlias, CREFSTRING secondaryAlias, CREFSTRING secondaryPrefix); 
     bool IsFunctionOnPrimaryProperty(FdoFunction* function, FdoIConnection* conn, CREFSTRING schemaName, CREFSTRING className);
     bool SupportsFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extension, bool isAggregate);
     MgReader* SelectFdoJoin(MgResourceIdentifier* featureSourceId, CREFSTRING extension, bool isAggregate);

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/Feature/Commands/UpdateFeatures.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -135,7 +135,7 @@
         commited = true;
     }
 
-    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH_AND_THROW(resource, L"MgdUpdateFeaturesCommand.UpdateFeatures")
+    MG_FEATURE_SERVICE_CHECK_CONNECTION_CATCH(resource, L"MgdUpdateFeaturesCommand.UpdateFeatures")
 
     if (transaction != NULL && !commited)
     {

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -6,10 +6,11 @@
 #include "Services/Feature/FdoConnectionUtil.h"
 #include "Fdo.h"
 
-MgdFeatureReader::MgdFeatureReader(MgdFeatureConnection* conn, FdoIFeatureReader* reader)
+MgdFeatureReader::MgdFeatureReader(MgdFeatureConnection* conn, FdoIFeatureReader* reader, MgStringCollection* forceIdProps)
 {
 	m_reader = FDO_SAFE_ADDREF(reader);
     m_connection = SAFE_ADDREF(conn);
+    m_forceIdProps = SAFE_ADDREF(forceIdProps); //This is only passed in for select queries that involve the FDO Join APIs
 
     // The reader takes ownership of the FDO connection
     m_connection->OwnReader();
@@ -730,6 +731,39 @@
         // Convert FdoClassDefinition to MgClassDefinition
         m_classDef = MgdFeatureUtil::GetMgClassDefinition(fdoClassDefinition, true);
         CHECKNULL(m_classDef.p, L"MgdFeatureReader::GetClassDefinition");
+
+        // The class definition presented by a FDO reader from a join select query will probably
+        // not contain any identity properties, thereby violating our golden rule of selection (no id props = unselectable)
+        // so for such queries executed by MapGuide, we pass this list of identity properties on to this reader (sourced
+        // with the identity properties from the "primary" class definition) so that we can "rewrite" the converted MgClassDefinition
+        if (NULL != m_forceIdProps && m_forceIdProps->GetCount() > 0)
+        {
+            Ptr<MgPropertyDefinitionCollection> clsProps = m_classDef->GetProperties();
+            Ptr<MgPropertyDefinitionCollection> clsIdProps = m_classDef->GetIdentityProperties();
+
+            // This is most likely empty, but we're overwriting this anyway, so clear it
+            clsIdProps->Clear();
+
+            // Copy across any properties from the explicity identity property name list
+            for (INT32 i = 0; i < m_forceIdProps->GetCount(); i++)
+            {
+                STRING propName = m_forceIdProps->GetItem(i);
+                INT32 pidx = clsProps->IndexOf(propName);
+                if (pidx >= 0)
+                {
+                    Ptr<MgPropertyDefinition> p = clsProps->GetItem(pidx);
+                    clsIdProps->Add(p);
+                } //else should we care about correctness?
+            }
+        }
+
+#ifdef DEBUG_FDO_JOIN
+        Ptr<MgPropertyDefinitionCollection> idProps = m_classDef->GetIdentityProperties();
+        Ptr<MgPropertyDefinitionCollection> props = m_classDef->GetProperties();
+        INT32 idCount = idProps->GetCount();
+        INT32 propCount = props->GetCount();
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) [MgFeatureReader::GetClassDefinition] %d props, %d identity props"), propCount, idCount));
+#endif
     }
 
     MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgdFeatureReader::GetClassDefinition")
@@ -754,6 +788,39 @@
         // Convert FdoClassDefinition to MgClassDefinition
         m_classDef = MgdFeatureUtil::GetMgClassDefinition(fdoClassDefinition, false);
         CHECKNULL(m_classDef.p, L"MgdFeatureReader::GetClassDefinitionNoXml");
+
+        // The class definition presented by a FDO reader from a join select query will probably
+        // not contain any identity properties, thereby violating our golden rule of selection (no id props = unselectable)
+        // so for such queries executed by MapGuide, we pass this list of identity properties on to this reader (sourced
+        // with the identity properties from the "primary" class definition) so that we can "rewrite" the converted MgClassDefinition
+        if (NULL != m_forceIdProps && m_forceIdProps->GetCount() > 0)
+        {
+            Ptr<MgPropertyDefinitionCollection> clsProps = m_classDef->GetProperties();
+            Ptr<MgPropertyDefinitionCollection> clsIdProps = m_classDef->GetIdentityProperties();
+
+            // This is most likely empty, but we're overwriting this anyway, so clear it
+            clsIdProps->Clear();
+
+            // Copy across any properties from the explicity identity property name list
+            for (INT32 i = 0; i < m_forceIdProps->GetCount(); i++)
+            {
+                STRING propName = m_forceIdProps->GetItem(i);
+                INT32 pidx = clsProps->IndexOf(propName);
+                if (pidx >= 0)
+                {
+                    Ptr<MgPropertyDefinition> p = clsProps->GetItem(pidx);
+                    clsIdProps->Add(p);
+                } //else should we care about correctness?
+            }
+        }
+
+#ifdef DEBUG_FDO_JOIN
+        Ptr<MgPropertyDefinitionCollection> idProps = m_classDef->GetIdentityProperties();
+        Ptr<MgPropertyDefinitionCollection> props = m_classDef->GetProperties();
+        INT32 idCount = idProps->GetCount();
+        INT32 propCount = props->GetCount();
+        ACE_DEBUG((LM_INFO, ACE_TEXT("\n(%t) [MgFeatureReader::GetClassDefinition] %d props, %d identity props"), propCount, idCount));
+#endif
     }
 
     MG_FEATURE_SERVICE_CATCH_AND_THROW(L"MgdFeatureReader::GetClassDefinitionNoXml")

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.h
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.h	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/FeatureReader.h	2013-03-22 12:10:42 UTC (rev 7409)
@@ -13,7 +13,7 @@
 class MG_DESKTOP_API MgdFeatureReader : public MgFeatureReader
 {
 INTERNAL_API:
-	MgdFeatureReader(MgdFeatureConnection* conn, FdoIFeatureReader* reader);
+	MgdFeatureReader(MgdFeatureConnection* conn, FdoIFeatureReader* reader, MgStringCollection* forceIdProps = NULL);
 
 EXTERNAL_API:
 	virtual ~MgdFeatureReader();
@@ -206,6 +206,7 @@
 	FdoIFeatureReader* m_reader;
     Ptr<MgClassDefinition> m_classDef;
     Ptr<MgdFeatureConnection> m_connection;
+    Ptr<MgStringCollection> m_forceIdProps;
 };
 /// \}
 #endif
\ No newline at end of file

Modified: branches/2.5/MgDev/Desktop/MgDesktop/Services/Rendering/MappingUtil.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/Services/Rendering/MappingUtil.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/Services/Rendering/MappingUtil.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -451,14 +451,28 @@
 
             if (vl) //############################################################################ vector layer
             {
+                // Tweaking this logic for #1981:
+                //
+                // We first try to find a valid scale range, only when we can't find a valid scale range do we
+                // coerce the first one to [0 - Infinity]
+
+                MdfModel::VectorScaleRangeCollection* scaleRanges = vl->GetScaleRanges();
+                MdfModel::VectorScaleRange* scaleRange = NULL;
+                if (scaleRanges)
+                {
+                    // make sure we have a valid scale range
+                    scaleRange = Stylizer::FindScaleRange(*scaleRanges, scale);
+                }
+
+                // We have a selection but no applicable scale range
+                //
                 // Modify the layer scale range to also support infinite
                 // Need to apply default style as one will not be defined
-                if (selection)
+                if (selection && !scaleRange)
                 {
-                    MdfModel::VectorScaleRangeCollection* scaleRanges = vl->GetScaleRanges();
                     if (scaleRanges)
                     {
-                        MdfModel::VectorScaleRange* scaleRange = scaleRanges->GetAt(0);
+                        scaleRange = scaleRanges->GetAt(0);
                         if (scaleRange)
                         {
                             scaleRange->SetMinScale(0.0);
@@ -467,9 +481,6 @@
                     }
                 }
 
-                // make sure we have a valid scale range
-                MdfModel::VectorScaleRange* scaleRange = Stylizer::FindScaleRange(*vl->GetScaleRanges(), scale);
-
                 if (scaleRange)
                 {
                     minScale_Profile = scaleRange->GetMinScale();

Modified: branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -185,6 +185,8 @@
 const INT32  MgdConfigProperties::DefaultFeatureServicePropertyDataTransactionTimerInterval  = 60;
 const STRING MgdConfigProperties::FeatureServicePropertyFDOConnectionTimeoutCustom           = L"FDOConnectionTimeoutCustom";
 const STRING MgdConfigProperties::DefaultFeatureServicePropertyFDOConnectionTimeoutCustom    = L"OSGeo.WMS:120";
+const STRING MgdConfigProperties::FeatureServicePropertyUseFdoJoinOptimization               = L"UseFdoJoinOptimization";
+const bool   MgdConfigProperties::DefaultFeatureServicePropertyUseFdoJoinOptimization        = true;
 
 // ******************************************************************
 // Mapping Service Properties

Modified: branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.h
===================================================================
--- branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.h	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/MgDesktop/System/ConfigProperties.h	2013-03-22 12:10:42 UTC (rev 7409)
@@ -167,6 +167,10 @@
     static const STRING FeatureServicePropertyFDOConnectionTimeoutCustom;        /// value("FDOConnectionTimeoutCustom")
     static const STRING DefaultFeatureServicePropertyFDOConnectionTimeoutCustom; /// value("OSGeo.WMS:120")
 
+    /// Defines whether to use the FDO Join APIs for Feature Joins where applicable and supported
+    static const STRING FeatureServicePropertyUseFdoJoinOptimization;            /// value("UseFdoJoinOptimization")
+    static const bool DefaultFeatureServicePropertyUseFdoJoinOptimization;       /// value(true)
+
     /// MAPPING SERVICE PROPERTIES SECTION -------------------------------------------------------------------------------
 
     /// Mapping Service properties

Modified: branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -2817,6 +2817,145 @@
 ///----------------------------------------------------------------------------
 /// Test Case Description:
 ///
+/// This test case exercises the UpdateFeatures API for insertion
+///----------------------------------------------------------------------------
+void TestFeatureService::TestCase_UpdateFeaturesInsert()
+{
+    try
+    {
+        Ptr<MgdServiceFactory> fact = new MgdServiceFactory();
+        if (fact == 0)
+        {
+            throw new MgNullReferenceException(L"TestFeatureService.TestCase_SavePoint", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        Ptr<MgFeatureService> pService = dynamic_cast<MgFeatureService*>(fact->CreateService(MgServiceType::FeatureService));
+        if (pService == 0)
+        {
+            throw new MgServiceNotAvailableException(L"TestFeatureService.TestCase_SavePoint", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        Ptr<MgResourceIdentifier> featureSource = new MgResourceIdentifier(L"Library://UnitTests/Data/TestInsert.FeatureSource");
+
+        //Create our test data store (SQLite)
+        STRING scName = L"Default";
+        STRING srsWkt = L"LOCAL_CS[\"Non-Earth (Meter)\",LOCAL_DATUM[\"Local Datum\",0],UNIT[\"Meter\", 1],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]";
+        
+        //Setup schema
+        Ptr<MgFeatureSchema> schema = new MgFeatureSchema(L"Default", L"Test schema for TestCase_2218");
+        Ptr<MgClassDefinition> klass = new MgClassDefinition();
+        klass->SetName(L"TestClass");
+        Ptr<MgPropertyDefinitionCollection> clsProps = klass->GetProperties();
+        Ptr<MgPropertyDefinitionCollection> idProps = klass->GetIdentityProperties();
+        
+        //ID
+        Ptr<MgDataPropertyDefinition> idProperty = new MgDataPropertyDefinition(L"ID");
+        idProperty->SetDataType(MgPropertyType::Int32);
+        idProperty->SetAutoGeneration(false);
+        idProperty->SetNullable(false);
+        clsProps->Add(idProperty);
+        idProps->Add(idProperty);
+        //Name
+        Ptr<MgDataPropertyDefinition> nameProperty = new MgDataPropertyDefinition(L"Name");
+        nameProperty->SetDataType(MgPropertyType::String);
+        nameProperty->SetLength(255);
+        nameProperty->SetNullable(true);
+        clsProps->Add(nameProperty);
+        //Geom
+        Ptr<MgGeometricPropertyDefinition> geomProperty = new MgGeometricPropertyDefinition(L"Geom");
+        geomProperty->SetSpatialContextAssociation(scName);
+        clsProps->Add(geomProperty);
+
+        klass->SetDefaultGeometryPropertyName(L"Geom");
+
+        Ptr<MgClassDefinitionCollection> classes = schema->GetClasses();
+        classes->Add(klass);
+
+        //Create the feature source
+        Ptr<MgFileFeatureSourceParams> fileParams = new MgFileFeatureSourceParams(L"OSGeo.SQLite", scName, srsWkt, schema);
+        pService->CreateFeatureSource(featureSource, fileParams);
+
+        //Set up insert command
+        Ptr<MgFeatureCommandCollection> commands = new MgFeatureCommandCollection();
+        Ptr<MgPropertyCollection> propVals = new MgPropertyCollection();
+        
+        Ptr<MgInt32Property> idVal = new MgInt32Property(L"ID", 1);
+        Ptr<MgStringProperty> nameVal = new MgStringProperty(L"Name", L"Foo");
+        
+        Ptr<MgWktReaderWriter> wktRw = new MgWktReaderWriter();
+        Ptr<MgAgfReaderWriter> agfRw = new MgAgfReaderWriter();
+        Ptr<MgGeometry> geom = wktRw->Read(L"POINT (1 2)");
+        Ptr<MgByteReader> agf = agfRw->Write(geom);
+        Ptr<MgGeometryProperty> geomVal = new MgGeometryProperty(L"Geom", agf);
+
+        propVals->Add(idVal);
+        propVals->Add(nameVal);
+        propVals->Add(geomVal);
+
+        Ptr<MgInsertFeatures> insert = new MgInsertFeatures(L"Default:TestClass", propVals);
+        commands->Add(insert);
+
+        //Execute insert. Should be fine
+        Ptr<MgPropertyCollection> result = pService->UpdateFeatures(featureSource, commands, true);
+        CPPUNIT_ASSERT(result->GetCount() == 1);
+        INT32 i = 0;
+        Ptr<MgProperty> resItem1 = result->GetItem(i);
+        CPPUNIT_ASSERT(resItem1->GetPropertyType() == MgPropertyType::Feature);
+        Ptr<MgFeatureReader> rdr = ((MgFeatureProperty*)resItem1.p)->GetValue();
+        rdr->Close();
+
+        //Change name, retain same id
+        nameVal->SetValue(L"Bar");
+
+        //Execute again, expect MgFdoException due to constraint violation
+        CPPUNIT_ASSERT_THROW_MG(result = pService->UpdateFeatures(featureSource, commands, true), MgFdoException*);
+        
+        //Expect one inserted result
+        Ptr<MgFeatureQueryOptions> query = new MgFeatureQueryOptions();
+        Ptr<MgFeatureReader> qryReader = pService->SelectFeatures(featureSource, L"Default:TestClass", query);
+        INT32 count = 0;
+        while (qryReader->ReadNext()) { count++; }
+        qryReader->Close();
+        CPPUNIT_ASSERT(1 == count);
+
+        //Execute again, useTransaction = false. Should not throw exception, but log
+        //the error as a MgStringProperty
+        result = pService->UpdateFeatures(featureSource, commands, false);
+        CPPUNIT_ASSERT(result->GetCount() == 1);
+        resItem1 = result->GetItem(i);
+        CPPUNIT_ASSERT(resItem1->GetPropertyType() == MgPropertyType::String); //Errors are of type String
+
+        //Use new id
+        idVal->SetValue(2);
+
+        //Should be fine now
+        result = pService->UpdateFeatures(featureSource, commands, true);
+        CPPUNIT_ASSERT(result->GetCount() == 1);
+        resItem1 = result->GetItem(i);
+        CPPUNIT_ASSERT(resItem1->GetPropertyType() == MgPropertyType::Feature);
+        rdr = ((MgFeatureProperty*)resItem1.p)->GetValue();
+        rdr->Close();
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(FdoException* e)
+    {
+        FDO_SAFE_RELEASE(e);
+        CPPUNIT_FAIL("FdoException occurred");
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+///----------------------------------------------------------------------------
+/// Test Case Description:
+///
 /// This test case exercises the FDO join optimization
 ///----------------------------------------------------------------------------
 void TestFeatureService::TestCase_JoinFdoFeatures()
@@ -4514,4 +4653,70 @@
     {
         throw;
     }
+}
+
+///----------------------------------------------------------------------------
+/// Test Case Description:
+///
+/// This test case tests the correct response for a non-transactional failure
+/// in UpdateFeatures
+///----------------------------------------------------------------------------
+void TestFeatureService::TestCase_UpdateFeaturesPartialFailure()
+{
+    try
+    {
+        Ptr<MgdServiceFactory> fact = new MgdServiceFactory();
+        if (fact == 0)
+        {
+            throw new MgNullReferenceException(L"TestFeatureService.TestCase_UpdateFeaturesPartialFailure", __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        Ptr<MgFeatureService> featSvc = dynamic_cast<MgFeatureService*>(fact->CreateService(MgServiceType::FeatureService));
+        if (featSvc == 0)
+        {
+            throw new MgServiceNotAvailableException(L"TestFeatureService.TestCase_UpdateFeaturesPartialFailure",
+                __LINE__, __WFILE__, NULL, L"", NULL);
+        }
+
+        Ptr<MgResourceIdentifier> fsId = new MgResourceIdentifier(L"Library://UnitTests/Data/Sheboygan_Parcels.FeatureSource");
+        Ptr<MgPropertyCollection> props = new MgPropertyCollection();
+        Ptr<MgInt32Property> idProp = new MgInt32Property(L"id", 0);
+        props->Add(idProp);
+        Ptr<MgInsertFeatures> insert = new MgInsertFeatures(L"Parcels1", props); //Bogus class name to trigger exception
+        Ptr<MgFeatureCommandCollection> cmds = new MgFeatureCommandCollection();
+        cmds->Add(insert);
+
+        Ptr<MgPropertyCollection> result = featSvc->UpdateFeatures(fsId, cmds, false);
+        CPPUNIT_ASSERT(result->GetCount() > 0);
+
+        bool bPartialFailure = false;
+        for (INT32 i = 0; i < result->GetCount(); i++)
+        {
+            Ptr<MgProperty> prop = result->GetItem(i);
+            if (prop->GetPropertyType() == MgPropertyType::String)
+            {
+                bPartialFailure = true;
+                break;
+            }
+        }
+
+        CPPUNIT_ASSERT(bPartialFailure);
+    }
+    catch(MgException* e)
+    {
+        STRING message = e->GetDetails(TEST_LOCALE);
+        SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(FdoException* e)
+    {
+        STRING message = L"FdoException occurred: ";
+        message += e->GetExceptionMessage();
+        FDO_SAFE_RELEASE(e);
+        CPPUNIT_FAIL(MG_WCHAR_TO_CHAR(message.c_str()));
+    }
+    catch(...)
+    {
+        throw;
+    }
 }
\ No newline at end of file

Modified: branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.h
===================================================================
--- branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.h	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/UnitTest/TestFeatureService.h	2013-03-22 12:10:42 UTC (rev 7409)
@@ -47,6 +47,8 @@
     CPPUNIT_TEST(TestCase_InsertFeatures);
     CPPUNIT_TEST(TestCase_InsertFeaturesBatch);
     CPPUNIT_TEST(TestCase_UpdateFeatures);
+    CPPUNIT_TEST(TestCase_UpdateFeaturesInsert);
+    CPPUNIT_TEST(TestCase_UpdateFeaturesPartialFailure);
     CPPUNIT_TEST(TestCase_DeleteFeatures);
 //  TODO write test case when know how to make command collection
     CPPUNIT_TEST(TestCase_ExecuteSqlQuery);
@@ -102,6 +104,8 @@
     void TestCase_SelectFeaturesTransformed();
     void TestCase_SelectScrollable();
     void TestCase_SelectAggregate();
+    void TestCase_UpdateFeaturesInsert();
+    void TestCase_UpdateFeaturesPartialFailure();
     void TestCase_InsertFeatures();
     void TestCase_InsertFeaturesBatch();
     void TestCase_UpdateFeatures();

Modified: branches/2.5/MgDev/Desktop/UnitTest/main.cpp
===================================================================
--- branches/2.5/MgDev/Desktop/UnitTest/main.cpp	2013-03-22 11:39:59 UTC (rev 7408)
+++ branches/2.5/MgDev/Desktop/UnitTest/main.cpp	2013-03-22 12:10:42 UTC (rev 7409)
@@ -24,7 +24,6 @@
 #endif
 #endif
 
-#define TEST_COORDINATE_SYSTEM  1
 #define TEST_LOG_MANAGER        1
 #define TEST_RESOURCE_SERVICE   1
 #define TEST_FEATURE_SERVICE    1
@@ -51,6 +50,9 @@
     ACE_DEBUG((LM_INFO, ACE_TEXT("Initialize Platform.ini\n")));
     //Benchmark this
 #ifdef WIN32
+    //Muffle errors due to broken FDO RDBMS provider dlls, they aren't the ones exercised
+    //under test anyway
+    SetErrorMode(SEM_FAILCRITICALERRORS);
     long lStart = GetTickCount();
 #endif
     MgdPlatform::Initialize(L"Platform.ini");
@@ -70,14 +72,6 @@
 #if TEST_LOG_MANAGER == 1
     runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestLogManager").makeTest());
 #endif
-#ifdef _DEBUG
-    ACE_DEBUG((LM_INFO, ACE_TEXT(">>>>> Running all unit tests - Excluding Performance and CoordinateSystem. <<<<<\n\n")));
-#else
-    ACE_DEBUG((LM_INFO, ACE_TEXT(">>>>> Running all unit tests - Excluding Performance. <<<<<\n\n")));
-    #if TEST_COORDINATE_SYSTEM == 1
-    runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestCoordinateSystem").makeTest());
-    #endif
-#endif
 #if TEST_RESOURCE_SERVICE == 1
     runner.addTest(CppUnit::TestFactoryRegistry::getRegistry("TestResourceService").makeTest());
 #endif



More information about the mapguide-commits mailing list