[mapguide-commits] r6727 - in trunk/Tools/Maestro: . Maestro Maestro.MapViewer Maestro.MapViewer/Properties Maestro.MapViewer/Resources Maestro.TestViewer Maestro.TestViewer/Properties OSGeo.MapGuide.MaestroAPI OSGeo.MapGuide.MaestroAPI/Mapping OSGeo.MapGuide.MaestroAPI/Properties OSGeo.MapGuide.MaestroAPI/Services OSGeo.MapGuide.MaestroAPI.Http OSGeo.MapGuide.MaestroAPI.Native

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Fri Jun 1 10:26:06 PDT 2012


Author: jng
Date: 2012-06-01 10:26:06 -0700 (Fri, 01 Jun 2012)
New Revision: 6727

Added:
   trunk/Tools/Maestro/Maestro.MapViewer/
   trunk/Tools/Maestro/Maestro.MapViewer/CoreTypes.cs
   trunk/Tools/Maestro/Maestro.MapViewer/DefaultToolbar.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Interfaces.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Legend.resx
   trunk/Tools/Maestro/Maestro.MapViewer/Maestro.MapViewer.csproj
   trunk/Tools/Maestro/Maestro.MapViewer/MapStatusTracker.cs
   trunk/Tools/Maestro/Maestro.MapViewer/MapViewer.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Properties/
   trunk/Tools/Maestro/Maestro.MapViewer/Properties/AssemblyInfo.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.Designer.cs
   trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.resx
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/PoweredBy_en.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/about.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/buffer.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/control-180.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/control.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-copy.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-cut.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-duplicate.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-paste.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-xml.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/error.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/file-print.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/file-save.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/grab.cur
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/help.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/iconNavigator.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_etc.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_home.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_loading.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_pan.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_select.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_tasks.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_zoomselect.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/info.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/initial-center.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/invoke-script.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/invoke-url.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-ellipse.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-line.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-polygon.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-polyline.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-small.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_broken.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_dwf.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_group.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_raster.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_select.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_theme.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_unselect.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/load_package.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/measure.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/monitor_status.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/options.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/overview-map.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/preview.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/print.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/search.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-centre.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-clear.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-features.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-polygon.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-radius.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-zoom.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/ui-tooltip-balloon-bottom.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-back.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-forward.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-refresh.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/view_log.gif
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-dynamic.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-full.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-in-fixed.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-in.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-out-fixed.png
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoomin.cur
   trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoomout.cur
   trunk/Tools/Maestro/Maestro.TestViewer/
   trunk/Tools/Maestro/Maestro.TestViewer/Maestro.TestViewer.csproj
   trunk/Tools/Maestro/Maestro.TestViewer/MainForm.Designer.cs
   trunk/Tools/Maestro/Maestro.TestViewer/MainForm.cs
   trunk/Tools/Maestro/Maestro.TestViewer/MainForm.resx
   trunk/Tools/Maestro/Maestro.TestViewer/Program.cs
   trunk/Tools/Maestro/Maestro.TestViewer/Properties/
   trunk/Tools/Maestro/Maestro.TestViewer/Properties/AssemblyInfo.cs
   trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.Designer.cs
   trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.resx
   trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.Designer.cs
   trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.settings
   trunk/Tools/Maestro/Maestro.TestViewer/app.config
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/QueryMapOptions.cs
Modified:
   trunk/Tools/Maestro/Maestro/Maestro_All.sln
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/RequestBuilder.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/MapSelection.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapGroup.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapLayer.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/MgServerConnectionBase.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/AssemblyInfo.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs
Log:
This mega-submission includes the following changes:
 - #2014: Implement a map viewer for the Maestro RuntimeMap. This is the mg-desktop map viewer with all MapGuide APIs replaced with Maestro equivalents. The similarity of the 2 APIs (quite intentional really), has meant porting the viewer code across to Maestro becoming quite an easy affair. 2 new projects have been added to the solution:
   - Maestro.MapViewer: A re-usable SDK component library containing the map viewer control.
   - Maestro.TestViewer: A test application using the Maestro.MapViewer library
 - #2017: Workaround a nasty server-side bug with GETCLASSDEFINITION by requesting DESCRIBEFEATURESCHEMA with CLASSNAME hint instead.
 - Cleanup the initialization logic of the RuntimeMap class
 - Add cleaned up versions of the following APIs to better line up with their official MapGuide counterparts, existing variations have been flagged as deprecated and should no longer be used:
   - RenderDynamicOverlay
   - QueryMapFeatures

Modified: trunk/Tools/Maestro/Maestro/Maestro_All.sln
===================================================================
--- trunk/Tools/Maestro/Maestro/Maestro_All.sln	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/Maestro/Maestro_All.sln	2012-06-01 17:26:06 UTC (rev 6727)
@@ -139,192 +139,492 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Maestro.AddInManager", "..\Maestro.AddInManager\Maestro.AddInManager.csproj", "{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Maestro.MapViewer", "..\Maestro.MapViewer\Maestro.MapViewer.csproj", "{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Maestro.TestViewer", "..\Maestro.TestViewer\Maestro.TestViewer.csproj", "{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|x86 = Debug|x86
 		Release|Any CPU = Release|Any CPU
+		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{E0C36475-2B70-4F6D-ACE0-8943167806DC}.Release|x86.ActiveCfg = Release|Any CPU
 		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|x86.ActiveCfg = Release|Any CPU
 		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Any CPU.Build.0 = Release|Any CPU
+		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|x86.ActiveCfg = Release|Any CPU
 		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{F1E2F468-5030-4DBA-968C-9620284AFAA1}.Release|x86.ActiveCfg = Release|Any CPU
 		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Release|Any CPU.Build.0 = Release|Any CPU
+		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{59BE5E18-17B6-431D-836E-C0AABA6D69E8}.Release|x86.ActiveCfg = Release|Any CPU
 		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Release|Any CPU.Build.0 = Release|Any CPU
+		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{32BA7DF6-1AFA-441D-9231-5624C5920706}.Release|x86.ActiveCfg = Release|Any CPU
 		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{C7DCF771-5982-4859-A17F-01126E6F9BA6}.Release|x86.ActiveCfg = Release|Any CPU
 		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{0FD82B7B-1264-410F-86D1-47E9CCACD68E}.Release|x86.ActiveCfg = Release|Any CPU
 		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}.Release|x86.ActiveCfg = Release|Any CPU
 		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}.Release|x86.ActiveCfg = Release|Any CPU
 		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{0EA33E36-9C33-4D60-B378-B87FADAA0F40}.Release|x86.ActiveCfg = Release|Any CPU
 		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{CFD19053-2172-41D3-8460-0FD2123A1E88}.Release|x86.ActiveCfg = Release|Any CPU
 		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{80FA3158-8B5F-48D1-A393-0378AFE48A7E}.Release|x86.ActiveCfg = Release|Any CPU
 		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{6EF1E775-444B-4E5F-87FB-D687C43A68D7}.Release|x86.ActiveCfg = Release|Any CPU
 		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{B5EA049C-6AB7-4686-A2F4-4BA2EAC0E585}.Release|x86.ActiveCfg = Release|Any CPU
 		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{EDDB0F74-6FE7-4969-80B0-817A629722CD}.Release|x86.ActiveCfg = Release|Any CPU
 		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{AC5068F6-CFBE-4BCD-B68B-062725E424D4}.Release|x86.ActiveCfg = Release|Any CPU
 		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{B2A1F69E-52AA-42A2-8DED-89ADB9B14A38}.Release|x86.ActiveCfg = Release|Any CPU
 		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{D525B343-66D6-4D6B-9A55-78A173D94A51}.Release|x86.ActiveCfg = Release|Any CPU
 		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{BF6E996E-27AF-44CD-B3CF-A40874E15B2E}.Release|x86.ActiveCfg = Release|Any CPU
 		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{0A93ACA8-5B21-44E6-B0B7-5D1E72D3A6A2}.Release|x86.ActiveCfg = Release|Any CPU
 		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|x86.ActiveCfg = Release|Any CPU
 		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Release|Any CPU.Build.0 = Release|Any CPU
+		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{351D49A3-2E4A-4EC3-AFC2-D56598F44F51}.Release|x86.ActiveCfg = Release|Any CPU
 		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{50C12B5C-387C-4007-A1D1-CB181CB474CC}.Release|x86.ActiveCfg = Release|Any CPU
 		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{F976A709-D9DB-407E-A4CD-2CEA31C6B1D9}.Release|x86.ActiveCfg = Release|Any CPU
 		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{C8DB3E77-3AF4-471D-A214-69DBEB32750E}.Release|x86.ActiveCfg = Release|Any CPU
 		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{F84E21EE-360C-46EC-BD01-E66F8D9F5B3E}.Release|x86.ActiveCfg = Release|Any CPU
 		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{B3A2B816-9F41-4857-A111-09D2DF2550D6}.Release|x86.ActiveCfg = Release|Any CPU
 		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{3DDF6501-0148-474C-8674-7C7DA49C7F02}.Release|x86.ActiveCfg = Release|Any CPU
 		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{2419F940-BFB7-4F3F-B5DA-1052EB4706E5}.Release|x86.ActiveCfg = Release|Any CPU
 		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{6EE16FFD-296E-42FF-B994-8902C27AA0F4}.Release|x86.ActiveCfg = Release|Any CPU
 		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{D24F724A-1CBF-4EB6-A48B-92C08353C4CC}.Release|x86.ActiveCfg = Release|Any CPU
 		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{F4420153-9DF3-4407-AD65-E8ABED2B6E25}.Release|x86.ActiveCfg = Release|Any CPU
 		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{BEC17FD3-2ADB-4154-934D-494313C588EE}.Release|x86.ActiveCfg = Release|Any CPU
 		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Release|Any CPU.Build.0 = Release|Any CPU
+		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{16E6B250-C805-4C31-9A7D-F56A0051EC93}.Release|x86.ActiveCfg = Release|Any CPU
 		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{C0CA5D05-72C0-4F22-8618-B31BF0FFA190}.Release|x86.ActiveCfg = Release|Any CPU
 		{222CB020-5336-47D7-9BB9-A22D18953C80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{222CB020-5336-47D7-9BB9-A22D18953C80}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{222CB020-5336-47D7-9BB9-A22D18953C80}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{222CB020-5336-47D7-9BB9-A22D18953C80}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{222CB020-5336-47D7-9BB9-A22D18953C80}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{222CB020-5336-47D7-9BB9-A22D18953C80}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{222CB020-5336-47D7-9BB9-A22D18953C80}.Release|Any CPU.Build.0 = Release|Any CPU
+		{222CB020-5336-47D7-9BB9-A22D18953C80}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{222CB020-5336-47D7-9BB9-A22D18953C80}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{222CB020-5336-47D7-9BB9-A22D18953C80}.Release|x86.ActiveCfg = Release|Any CPU
 		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{E367FE8E-E46F-4DA0-86CE-E6F37E78DEE0}.Release|x86.ActiveCfg = Release|Any CPU
 		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Release|Any CPU.Build.0 = Release|Any CPU
+		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{8787FF3F-552F-46BE-B9D7-548B6162B079}.Release|x86.ActiveCfg = Release|Any CPU
 		{E204559D-EE92-4792-96E2-06F45654FAFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{E204559D-EE92-4792-96E2-06F45654FAFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E204559D-EE92-4792-96E2-06F45654FAFC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{E204559D-EE92-4792-96E2-06F45654FAFC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{E204559D-EE92-4792-96E2-06F45654FAFC}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{E204559D-EE92-4792-96E2-06F45654FAFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E204559D-EE92-4792-96E2-06F45654FAFC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E204559D-EE92-4792-96E2-06F45654FAFC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E204559D-EE92-4792-96E2-06F45654FAFC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{E204559D-EE92-4792-96E2-06F45654FAFC}.Release|x86.ActiveCfg = Release|Any CPU
 		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{19A769B5-7CFA-4E9F-90D8-BF4A17F918C4}.Release|x86.ActiveCfg = Release|Any CPU
 		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{3591C5BB-2B87-4FB4-AD87-9C8176DF9835}.Release|x86.ActiveCfg = Release|Any CPU
 		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{C75532C4-765B-418E-B09B-46D36B2ABDB1}.Release|x86.ActiveCfg = Release|Any CPU
 		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|x86.ActiveCfg = Release|Any CPU
 		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Debug|Any CPU.ActiveCfg = Debug|x86
 		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Debug|Any CPU.Build.0 = Debug|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Debug|x86.ActiveCfg = Debug|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Debug|x86.Build.0 = Debug|x86
 		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Release|Any CPU.ActiveCfg = Release|x86
 		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Release|Any CPU.Build.0 = Release|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Release|Mixed Platforms.Build.0 = Release|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Release|x86.ActiveCfg = Release|x86
+		{9CC51643-37D6-4B8F-A0EA-E7606AA561EB}.Release|x86.Build.0 = Release|x86
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}.Release|x86.ActiveCfg = Release|Any CPU
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Debug|x86.ActiveCfg = Debug|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Debug|x86.Build.0 = Debug|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Release|Any CPU.ActiveCfg = Release|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Release|Mixed Platforms.Build.0 = Release|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Release|x86.ActiveCfg = Release|x86
+		{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}.Release|x86.Build.0 = Release|x86
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer
___________________________________________________________________
Added: svn:ignore
   + bin
obj


Added: trunk/Tools/Maestro/Maestro.MapViewer/CoreTypes.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/CoreTypes.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/CoreTypes.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,205 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Drawing;
+
+namespace Maestro.MapViewer
+{
+    /// <summary>
+    /// A callback for circle digitization
+    /// </summary>
+    /// <param name="x">The X coordinate of the circle's center</param>
+    /// <param name="y">The Y coordinate of the circle's center</param>
+    /// <param name="radius">The circle's radius</param>
+    public delegate void CircleDigitizationCallback(double x, double y, double radius);
+
+    /// <summary>
+    /// A callback for line digitization
+    /// </summary>
+    /// <param name="x1">The X coordinate of the line's first point</param>
+    /// <param name="y1">The Y coordinate of the line's first point</param>
+    /// <param name="x2">The X coordinate of the line's second point</param>
+    /// <param name="y2">The Y coordinate of the line's second point</param>
+    public delegate void LineDigitizationCallback(double x1, double y1, double x2, double y2);
+
+    /// <summary>
+    /// A callback for point digitization
+    /// </summary>
+    /// <param name="x">The X coordinate of the point</param>
+    /// <param name="y">The Y coordinate of the point</param>
+    public delegate void PointDigitizationCallback(double x, double y);
+
+    /// <summary>
+    /// A callback for polygon digitization
+    /// </summary>
+    /// <param name="coordinates">A n by 2 array of polygon coordinates, where n is the number of vertices</param>
+    public delegate void PolygonDigitizationCallback(double[,] coordinates);
+
+    /// <summary>
+    /// A callback for line string digitization
+    /// </summary>
+    /// <param name="coordinates">A n by 2 array of line string coordinates, where n is the number of vertices</param>
+    public delegate void LineStringDigitizationCallback(double[,] coordinates);
+
+    /// <summary>
+    /// A callback for rectangle digitization
+    /// </summary>
+    /// <param name="llx">The X coordinate of the rectangle's lower left point</param>
+    /// <param name="lly">The Y coordinate of the rectangle's lower left point</param>
+    /// <param name="urx">The X coordinate of the rectangle's upper right point</param>
+    /// <param name="ury">The Y coordinate of the rectangle's upper right point</param>
+    public delegate void RectangleDigitizationCallback(double llx, double lly, double urx, double ury);
+
+    public class MapViewHistoryEntry
+    {
+        public MapViewHistoryEntry(double x, double y, double scale)
+        {
+            this.X = x;
+            this.Y = y;
+            this.Scale = scale;
+        }
+
+        public double X { get; private set; }
+
+        public double Y { get; private set; }
+
+        public double Scale { get; private set; }
+    }
+
+    /// <summary>
+    /// Contains data of a MouseMapPositionChanged event
+    /// </summary>
+    public class MapPointEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the X coordinate 
+        /// </summary>
+        public readonly double X;
+
+        /// <summary>
+        /// Gets the Y coordinate
+        /// </summary>
+        public readonly double Y;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        public MapPointEventArgs(double x, double y)
+        {
+            this.X = x;
+            this.Y = y;
+        }
+    }
+
+    /// <summary>
+    /// The type of digitization in progress
+    /// </summary>
+    public enum MapDigitizationType
+    {
+        /// <summary>
+        /// No digitization in progress
+        /// </summary>
+        None,
+        /// <summary>
+        /// A point digitization is in progress
+        /// </summary>
+        Point,
+        /// <summary>
+        /// A line digitization is in progress
+        /// </summary>
+        Line,
+        /// <summary>
+        /// A line string digitization is in progress
+        /// </summary>
+        LineString,
+        /// <summary>
+        /// A rectangle digitization is in progress
+        /// </summary>
+        Rectangle,
+        /// <summary>
+        /// A polygon digitization is in progress
+        /// </summary>
+        Polygon,
+        /// <summary>
+        /// A circle digitization is in progress
+        /// </summary>
+        Circle
+    }
+
+    /// <summary>
+    /// The active viewer tool
+    /// </summary>
+    public enum MapActiveTool
+    {
+        /// <summary>
+        /// Zoom In command
+        /// </summary>
+        ZoomIn,
+        /// <summary>
+        /// Zoom Out command
+        /// </summary>
+        ZoomOut,
+        /// <summary>
+        /// Pan command
+        /// </summary>
+        Pan,
+        /// <summary>
+        /// Select command
+        /// </summary>
+        Select,
+        /// <summary>
+        /// No active command
+        /// </summary>
+        None
+    }
+
+    /// <summary>
+    /// Viewer rendering options
+    /// </summary>
+    public class ViewerRenderingOptions
+    {
+        public ViewerRenderingOptions(string format, int behavior, Color color)
+        {
+            this.Format = format;
+            this.Behavior = behavior;
+            this.Color = color;
+        }
+
+        /// <summary>
+        /// Gets the format.
+        /// </summary>
+        public string Format { get; private set; }
+
+        /// <summary>
+        /// Gets the behavior.
+        /// </summary>
+        public int Behavior { get; private set; }
+
+        /// <summary>
+        /// Gets the color.
+        /// </summary>
+        public Color Color { get; private set; }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.MapViewer/DefaultToolbar.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/DefaultToolbar.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/DefaultToolbar.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,378 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace Maestro.MapViewer
+{
+    /// <summary>
+    /// A toolbar that contains a default set of viewer commands
+    /// </summary>
+    [ToolboxItem(true)]
+    public class DefaultToolbar : ToolStrip, IDefaultToolbar
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MgDefaultToolbar"/> class.
+        /// </summary>
+        public DefaultToolbar()
+            : base()
+        {
+            this.GripStyle = ToolStripGripStyle.Visible;
+            this.ZoomIn = new ToolStripButton("", Properties.Resources.zoom_in_fixed, OnZoomIn)
+            {
+                ToolTipText = Properties.Resources.TextZoomIn,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.ZoomOut = new ToolStripButton("", Properties.Resources.zoom_out_fixed, OnZoomOut)
+            {
+                ToolTipText = Properties.Resources.TextZoomOut,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.ZoomExtents = new ToolStripButton("", Properties.Resources.zoom_full, OnZoomExtents)
+            {
+                ToolTipText = Properties.Resources.TextZoomExtents,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.SelectTool = new ToolStripButton("", Properties.Resources.select_features, OnSelect)
+            {
+                ToolTipText = Properties.Resources.TextSelect,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.Pan = new ToolStripButton("", Properties.Resources.icon_pan, OnPan)
+            {
+                ToolTipText = Properties.Resources.TextPan,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.ClearSelection = new ToolStripButton("", Properties.Resources.select_clear, OnClearSelection)
+            {
+                ToolTipText = Properties.Resources.TextClearSelection,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.RefreshMap = new ToolStripButton("", Properties.Resources.view_refresh, OnRefreshMap)
+            {
+                ToolTipText = Properties.Resources.TextRefreshMap,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.ToggleTooltips = new ToolStripButton(Properties.Resources.TextDisableTooltips, Properties.Resources.ui_tooltip_balloon_bottom, OnToggleTooltips)
+            {
+                ToolTipText = Properties.Resources.TextDisableTooltips,
+                DisplayStyle = ToolStripItemDisplayStyle.ImageAndText
+            };
+            this.Loading = new ToolStripButton("", Properties.Resources.icon_loading)
+            {
+                Alignment = ToolStripItemAlignment.Right,
+                ImageScaling = ToolStripItemImageScaling.None,
+                Visible = false
+            };
+            this.SelectPolygon = new ToolStripButton("", Properties.Resources.select_polygon, OnSelectPolygon)
+            {
+                ToolTipText = Properties.Resources.TextSelectPolygon,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.SelectRadius = new ToolStripButton("", Properties.Resources.select_radius, OnSelectRadius)
+            {
+                ToolTipText = Properties.Resources.TextSelectRadius,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+            this.CopyMap = new ToolStripButton("", Properties.Resources.edit_copy, OnCopyMap)
+            {
+                ToolTipText = Properties.Resources.TextCopyMap,
+                DisplayStyle = ToolStripItemDisplayStyle.Image
+            };
+
+            this.Items.AddRange(new ToolStripItem[]
+            {
+                CopyMap,
+                new ToolStripSeparator(),
+                ZoomIn,
+                ZoomOut,
+                ZoomExtents,
+                new ToolStripSeparator(),
+                SelectTool,
+                SelectRadius,
+                SelectPolygon,
+                Pan,
+                new ToolStripSeparator(),
+                ClearSelection,
+                RefreshMap,
+                new ToolStripSeparator(),
+                ToggleTooltips,
+                Loading
+            });
+        }
+
+        /// <summary>
+        /// Gets or sets the zoom out mode.
+        /// </summary>
+        /// <value>
+        /// The zoom out mode.
+        /// </value>
+        [Category("MapGuide Viewer")]
+        [Description("The behaviour of the zoom out command")]
+        [DefaultValue(ZoomOutMode.ClickToZoom)]
+        public ZoomOutMode ZoomOutMode
+        {
+            get;
+            set;
+        }
+
+        private IMapViewer _viewer;
+
+        /// <summary>
+        /// Gets or sets the viewer this toolbar is associated with
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The map viewer component this toolbar will control")]
+        public IMapViewer Viewer
+        {
+            get { return _viewer; }
+            set
+            {
+                if (_viewer != null)
+                {
+                    _viewer.PropertyChanged -= OnViewerPropertyChanged;
+                    _viewer = null;
+                }
+
+                _viewer = value;
+                if (_viewer != null)
+                    _viewer.PropertyChanged += OnViewerPropertyChanged;
+
+                TooltipStateChanged();
+                UpdateButtonCheckedState();
+            }
+        }
+
+        internal ToolStripButton Loading { get; private set; }
+
+        internal ToolStripButton ZoomIn { get; private set; }
+
+        void OnZoomIn(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.ActiveTool = MapActiveTool.ZoomIn;
+        }
+
+        internal ToolStripButton ZoomOut { get; private set; }
+
+        void OnZoomOut(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            if (this.ZoomOutMode == ZoomOutMode.ClickToZoom)
+            {
+                _viewer.ActiveTool = MapActiveTool.ZoomOut;
+            }
+            else
+            {
+                var map = _viewer.GetMap();
+                var centerPt = map.ViewCenter;
+
+                _viewer.ZoomToView(centerPt.X, centerPt.Y, map.ViewScale * _viewer.ZoomOutFactor, true);
+            }
+        }
+
+        internal ToolStripButton ZoomExtents { get; private set; }
+
+        void OnZoomExtents(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.InitialMapView();
+        }
+
+        internal ToolStripButton SelectTool { get; private set; }
+
+        void OnSelect(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.ActiveTool = MapActiveTool.Select;
+        }
+
+        internal ToolStripButton Pan { get; private set; }
+
+        void OnPan(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.ActiveTool = MapActiveTool.Pan;
+        }
+
+        internal ToolStripButton ClearSelection { get; private set; }
+
+        void OnClearSelection(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.ClearSelection();
+        }
+
+        internal ToolStripButton SelectRadius { get; private set; }
+
+        void OnSelectRadius(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.DigitizeCircle((x, y, r) =>
+            {
+                _viewer.SelectByWkt(MakeWktCircle(x, y, r));
+            });
+        }
+
+        internal ToolStripButton SelectPolygon { get; private set; }
+
+        void OnSelectPolygon(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.DigitizePolygon((coordinates) =>
+            {
+                StringBuilder wkt = new StringBuilder("POLYGON ((");
+                for (int i = 0; i < coordinates.GetLength(0); i++)
+                {
+                    if (i > 0)
+                        wkt.Append(", ");
+                    wkt.Append(coordinates[i, 0] + " " + coordinates[i, 1]);
+                }
+                wkt.Append("))");
+                _viewer.SelectByWkt(wkt.ToString());
+            });
+        }
+
+        internal ToolStripButton RefreshMap { get; private set; }
+
+        void OnRefreshMap(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.RefreshMap();
+        }
+
+        internal ToolStripButton ToggleTooltips { get; private set; }
+
+        void OnToggleTooltips(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.FeatureTooltipsEnabled = !_viewer.FeatureTooltipsEnabled;
+            TooltipStateChanged();
+        }
+
+        internal ToolStripButton CopyMap { get; private set; }
+
+        void OnCopyMap(object sender, EventArgs e)
+        {
+            if (_viewer == null)
+                return;
+
+            _viewer.CopyMap();
+        }
+
+        private void TooltipStateChanged()
+        {
+            if (_viewer == null)
+                return;
+
+            if (_viewer.FeatureTooltipsEnabled)
+            {
+                this.ToggleTooltips.Text = Properties.Resources.TextDisableTooltips;
+                this.ToggleTooltips.ToolTipText = Properties.Resources.TooltipDisableTooltips;
+            }
+            else
+            {
+                this.ToggleTooltips.Text = Properties.Resources.TextEnableTooltips;
+                this.ToggleTooltips.ToolTipText = Properties.Resources.TooltipEnableTooltips;
+            }
+        }
+
+        private void UpdateButtonCheckedState()
+        {
+            var at = (_viewer == null) ? MapActiveTool.None : _viewer.ActiveTool;
+            this.Pan.Checked = (at == MapActiveTool.Pan);
+            this.SelectTool.Checked = (at == MapActiveTool.Select);
+            this.ZoomIn.Checked = (at == MapActiveTool.ZoomIn);
+            this.ZoomOut.Checked = (at == MapActiveTool.ZoomOut);
+        }
+
+        private void OnViewerPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == "IsBusy")
+            {
+                var busy = _viewer.IsBusy;
+                this.ZoomExtents.Enabled = this.ZoomIn.Enabled
+                                         = this.ZoomOut.Enabled
+                                         = this.ClearSelection.Enabled
+                                         = this.Pan.Enabled
+                                         = this.SelectTool.Enabled
+                                         = this.SelectPolygon.Enabled
+                                         = this.SelectRadius.Enabled
+                                         = this.ToggleTooltips.Enabled
+                                         = this.CopyMap.Enabled
+                                         = this.RefreshMap.Enabled = !busy;
+                this.Loading.Visible = busy;
+            }
+            else if (e.PropertyName == "ActiveTool" || e.PropertyName == "DigitizingType")
+            {
+                UpdateButtonCheckedState();
+            }
+        }
+
+        static string MakeWktPolygon(double x1, double y1, double x2, double y2)
+        {
+            return "POLYGON((" + x1 + " " + y1 + ", " + x2 + " " + y1 + ", " + x2 + " " + y2 + ", " + x1 + " " + y2 + ", " + x1 + " " + y1 + "))";
+        }
+
+        static string MakeWktCircle(double x, double y, double r)
+        {
+            return "CURVEPOLYGON ((" + (x - r) + " " + y + " (CIRCULARARCSEGMENT (" + x + " " + (y - r) + ", " + (x + r) + " " + y + "), CIRCULARARCSEGMENT (" + x + " " + (y + r) + ", " + (x - r) + " " + y + "))))";
+        }
+    }
+
+    /// <summary>
+    /// Determines the behaviour of the zoom out command in the <see cref="MgDefaultToolbar"/>
+    /// </summary>
+    public enum ZoomOutMode
+    {
+        /// <summary>
+        /// The user must click on the map to zoom out from that selected point
+        /// </summary>
+        ClickToZoom,
+        /// <summary>
+        /// The map automatically zooms out on command invocation
+        /// </summary>
+        AutoZoom
+    }
+}

Added: trunk/Tools/Maestro/Maestro.MapViewer/Interfaces.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Interfaces.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Interfaces.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,288 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using OSGeo.MapGuide.ObjectModels.Common;
+using System.Drawing;
+using OSGeo.MapGuide.MaestroAPI.Mapping;
+using System.ComponentModel;
+using System.Collections.ObjectModel;
+
+namespace Maestro.MapViewer
+{
+    /// <summary>
+    /// A map viewer component
+    /// </summary>
+    public interface IMapViewer : INotifyPropertyChanged
+    {
+        /// <summary>
+        /// Clears the current selection
+        /// </summary>
+        void ClearSelection();
+
+        /// <summary>
+        /// Starts the digitization process for a circle
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        void DigitizeCircle(CircleDigitizationCallback callback);
+
+        /// <summary>
+        /// Starts the digitization process for a line
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        void DigitizeLine(LineDigitizationCallback callback);
+
+        /// <summary>
+        /// Starts the digitization process for a point
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        void DigitizePoint(PointDigitizationCallback callback);
+
+        /// <summary>
+        /// Starts the digitization process for a polygon
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        void DigitizePolygon(PolygonDigitizationCallback callback);
+
+        /// <summary>
+        /// Starts the digitization process for a line string (polyline)
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        void DigitizeLineString(LineStringDigitizationCallback callback);
+
+        /// <summary>
+        /// Starts the digitization process for a line string (polyline)
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        /// <param name="segmentDigitized">The callback to be invoked when a new segment of the current line string is digitized</param>
+        void DigitizeLineString(LineStringDigitizationCallback callback, LineDigitizationCallback segmentDigitized);
+
+        /// <summary>
+        /// Starts the digitization process for a rectangle
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        void DigitizeRectangle(RectangleDigitizationCallback callback);
+
+        /// <summary>
+        /// Gets the current runtime map
+        /// </summary>
+        /// <returns></returns>
+        RuntimeMap GetMap();
+
+        /// <summary>
+        /// Gets or sets the color used to render selected features
+        /// </summary>
+        Color SelectionColor { get; set; }
+
+        /// <summary>
+        /// Gets or sets the active tool
+        /// </summary>
+        MapActiveTool ActiveTool { get; set; }
+
+        /// <summary>
+        /// Gets or sets the factor by which to multiply the scale to zoom in
+        /// </summary>
+        double ZoomInFactor { get; set; }
+
+        /// <summary>
+        /// Gets or sets the factor by which to multiply the scale to zoom out
+        /// </summary>
+        double ZoomOutFactor { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether feature tooltips are enabled. If set to true, tooltip queries are
+        /// executed at the current mouse position if the active tool is Pan or Select
+        /// </summary>
+        bool FeatureTooltipsEnabled { get; set; }
+
+        /// <summary>
+        /// Gets whether the viewer has any active rendering operations
+        /// </summary>
+        bool IsBusy { get; }
+
+        /// <summary>
+        /// Gets the type of object being currently digitized. If the digitization type is None, then
+        /// the viewer is not currently digitizing
+        /// </summary>
+        MapDigitizationType DigitizingType { get; }
+
+        /// <summary>
+        /// Gets the currently rendered image
+        /// </summary>
+        /// <returns></returns>
+        System.Drawing.Image GetCurrentImage();
+
+        /// <summary>
+        /// Copies the image of the current map to the clipboard
+        /// </summary>
+        void CopyMap();
+
+        /// <summary>
+        /// Refreshes the current map view. Any changes to the runtime map state will be saved first before rendering begins
+        /// </summary>
+        void RefreshMap();
+
+        /// <summary>
+        /// Raised when the map has been refreshed
+        /// </summary>
+        event EventHandler MapRefreshed;
+
+        /// <summary>
+        /// Pans the view left by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        void PanLeft(bool refresh);
+
+        /// <summary>
+        /// Pans the view up by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        void PanUp(bool refresh);
+
+        /// <summary>
+        /// Pans the view right by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        void PanRight(bool refresh);
+
+        /// <summary>
+        /// Pans the view down by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        void PanDown(bool refresh);
+
+        /// <summary>
+        /// Updates the rendered selection. Call this method if you have manipulated the selection
+        /// set outside of the viewer
+        /// </summary>
+        void UpdateSelection();
+
+        /// <summary>
+        /// Updates the rendered selection. Call this method if you have manipulated the selection
+        /// set outside of the viewer
+        /// </summary>
+        /// <param name="raise">Indicates if the <see cref="SelectionChanged"/> event should be raised as well</param>
+        void UpdateSelection(bool raise);
+
+        /// <summary>
+        /// Selects features from all selectable layers that intersects the given geometry in WKT format
+        /// </summary>
+        void SelectByWkt(string wkt);
+
+        /// <summary>
+        /// Zooms to the initial map view
+        /// </summary>
+        void InitialMapView();
+
+        /// <summary>
+        /// Zooms to the specified map view
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <param name="scale"></param>
+        /// <param name="refresh"></param>
+        void ZoomToView(double x, double y, double scale, bool refresh);
+
+        /// <summary>
+        /// Raised when the scale of the current runtime map has changed
+        /// </summary>
+        event EventHandler MapScaleChanged;
+
+        /// <summary>
+        /// Raised when the selection has changed. Note that programmatic selection modifications
+        /// will not raise this event.
+        /// </summary>
+        event EventHandler SelectionChanged;
+
+        /// <summary>
+        /// Raised when the viewer has been initialized
+        /// </summary>
+        event EventHandler MapLoaded;
+
+        /// <summary>
+        /// Raised when the map cursor position has changed
+        /// </summary>
+        event EventHandler<MapPointEventArgs> MouseMapPositionChanged;
+
+        /// <summary>
+        /// Zooms to the view defined by the specified extent
+        /// </summary>
+        /// <param name="llx"></param>
+        /// <param name="lly"></param>
+        /// <param name="urx"></param>
+        /// <param name="ury"></param>
+        void ZoomToExtents(double llx, double lly, double urx, double ury);
+
+        /// <summary>
+        /// Gets or sets whether to show vertex coordinates when digitizing
+        /// </summary>
+        bool ShowVertexCoordinatesWhenDigitizing { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether to convert tiled layers to non-tiled layers. This is a workaround
+        /// setting for tiled maps to be displayed as viewer support for tiled layers is still not
+        /// implemented
+        /// </summary>
+        bool ConvertTiledGroupsToNonTiled { get; set; }
+
+        /// <summary>
+        /// Gets whether this viewer has a map loaded into it
+        /// </summary>
+        bool HasLoadedMap { get; }
+
+        /// <summary>
+        /// Gets or sets the amount of pixels to buffer out by when doing point-based selections with the Select tool
+        /// </summary>
+        int PointPixelBuffer { get; set; }
+
+        /// <summary>
+        /// Navigates to the previous view in the history stack
+        /// </summary>
+        void PreviousView();
+
+        /// <summary>
+        /// Navigates to the next view in the history stack
+        /// </summary>
+        void NextView();
+
+        /// <summary>
+        /// Gets the current index in the view history stack
+        /// </summary>
+        int ViewHistoryIndex { get; }
+
+        /// <summary>
+        /// Gets the view history stack. The first item being the earliest and the last item being the most recent.
+        /// </summary>
+        ReadOnlyCollection<MapViewHistoryEntry> ViewHistory { get; }
+    }
+
+    /// <summary>
+    /// A toolbar that contains a default set of viewer commands
+    /// </summary>
+    public interface IDefaultToolbar
+    {
+        /// <summary>
+        /// Gets or sets the viewer this toolbar is associated with
+        /// </summary>
+        IMapViewer Viewer { get; set; }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Legend.Designer.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,78 @@
+namespace Maestro.MapViewer
+{
+    partial class Legend
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.trvLegend = new System.Windows.Forms.TreeView();
+            this.imgLegend = new System.Windows.Forms.ImageList(this.components);
+            this.SuspendLayout();
+            // 
+            // trvLegend
+            // 
+            this.trvLegend.CheckBoxes = true;
+            this.trvLegend.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.trvLegend.DrawMode = System.Windows.Forms.TreeViewDrawMode.OwnerDrawAll;
+            this.trvLegend.ImageIndex = 0;
+            this.trvLegend.ImageList = this.imgLegend;
+            this.trvLegend.Location = new System.Drawing.Point(0, 0);
+            this.trvLegend.Name = "trvLegend";
+            this.trvLegend.SelectedImageIndex = 0;
+            this.trvLegend.ShowLines = false;
+            this.trvLegend.ShowNodeToolTips = true;
+            this.trvLegend.Size = new System.Drawing.Size(171, 244);
+            this.trvLegend.TabIndex = 0;
+            this.trvLegend.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.trvLegend_AfterCheck);
+            this.trvLegend.AfterCollapse += new System.Windows.Forms.TreeViewEventHandler(this.trvLegend_AfterCollapse);
+            this.trvLegend.AfterExpand += new System.Windows.Forms.TreeViewEventHandler(this.trvLegend_AfterExpand);
+            this.trvLegend.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.trvLegend_DrawNode);
+            this.trvLegend.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.trvLegend_NodeMouseClick);
+            // 
+            // imgLegend
+            // 
+            this.imgLegend.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+            this.imgLegend.ImageSize = new System.Drawing.Size(16, 16);
+            this.imgLegend.TransparentColor = System.Drawing.Color.Transparent;
+            // 
+            // Legend
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.trvLegend);
+            this.Name = "Legend";
+            this.Size = new System.Drawing.Size(171, 244);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TreeView trvLegend;
+        private System.Windows.Forms.ImageList imgLegend;
+    }
+}

Added: trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Legend.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,925 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using OSGeo.MapGuide.MaestroAPI.Mapping;
+using System.Windows.Forms.VisualStyles;
+using System.Diagnostics;
+using OSGeo.MapGuide.MaestroAPI.Services;
+using System.Xml;
+using System.IO;
+
+namespace Maestro.MapViewer
+{
+    public partial class Legend : UserControl
+    {
+        const string IMG_BROKEN = "lc_broken";
+        const string IMG_DWF = "lc_dwf";
+        const string IMG_GROUP = "lc_group";
+        const string IMG_RASTER = "lc_raster";
+        const string IMG_SELECT = "lc_select";
+        const string IMG_THEME = "lc_theme";
+        const string IMG_UNSELECT = "lc_unselect";
+        const string IMG_OTHER = "icon_etc";
+
+        private RuntimeMap _map;
+
+        private Image _selectableIcon;
+        private Image _unselectableIcon;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Legend"/> class.
+        /// </summary>
+        public Legend()
+        {
+            InitializeComponent();
+            this.ThemeCompressionLimit = 25;
+        }
+
+        private IMapViewer _viewer;
+
+        public IMapViewer Viewer
+        {
+            get { return _viewer; }
+            set
+            { 
+                _viewer = value;
+                if (_viewer != null && !this.DesignMode)
+                {
+                    _map = _viewer.GetMap();
+                    _viewer.MapRefreshed += new EventHandler(OnMapRefreshed);
+                    _viewer.MapLoaded += new EventHandler(OnMapLoaded);
+                    _selectableIcon = Properties.Resources.lc_select;
+                    _unselectableIcon = Properties.Resources.lc_unselect;
+                }
+            }
+        }
+
+        void OnMapLoaded(object sender, EventArgs e)
+        {
+            _map = _viewer.GetMap();
+        }
+
+        void OnMapRefreshed(object sender, EventArgs e)
+        {
+            this.RefreshLegend();
+        }
+
+        private Dictionary<string, RuntimeMapLayer> _layers = new Dictionary<string, RuntimeMapLayer>();
+        private Dictionary<string, RuntimeMapGroup> _groups = new Dictionary<string, RuntimeMapGroup>();
+        private Dictionary<string, string> _layerDefinitionContents = new Dictionary<string, string>();
+
+        /// <summary>
+        /// Refreshes this component
+        /// </summary>
+        public void RefreshLegend()
+        {
+            if (_noUpdate)
+                return;
+
+            if (_map == null)
+                return;
+
+            //System.Diagnostics.Trace.TraceInformation("MgLegend.RefreshLegend()");
+            var scale = _map.ViewScale;
+            var groups = _map.Groups;
+            var layers = _map.Layers;
+
+            ResetTreeView();
+
+            _layerDefinitionContents.Clear();
+            _layers.Clear();
+            _groups.Clear();
+
+            IResourceService resSvc = _map.ResourceService;
+
+            trvLegend.BeginUpdate();
+            try
+            {
+                //Process groups first
+                List<RuntimeMapGroup> remainingNodes = new List<RuntimeMapGroup>();
+                for (int i = 0; i < groups.Count; i++)
+                {
+                    var group = groups[i];
+                    _groups.Add(group.ObjectId, group);
+                    if (!group.ShowInLegend)
+                        continue;
+
+                    //Add ones without parents first.
+                    if (!string.IsNullOrEmpty(group.Group))
+                    {
+                        remainingNodes.Add(group);
+                    }
+                    else
+                    {
+                        var node = CreateGroupNode(group);
+                        trvLegend.Nodes.Add(node);
+                    }
+
+                    while (remainingNodes.Count > 0)
+                    {
+                        List<RuntimeMapGroup> toRemove = new List<RuntimeMapGroup>();
+                        for (int j = 0; j < remainingNodes.Count; j++)
+                        {
+                            var parentGroupName = remainingNodes[j].Group;
+                            var parentGroup = groups[parentGroupName];
+                            var parentId = parentGroup.ObjectId;
+
+                            var nodes = trvLegend.Nodes.Find(parentId, false);
+                            if (nodes.Length == 1)
+                            {
+                                var node = CreateGroupNode(remainingNodes[j]);
+                                nodes[0].Nodes.Add(node);
+                                toRemove.Add(remainingNodes[j]);
+                            }
+                        }
+                        //Whittle down this list
+                        if (toRemove.Count > 0)
+                        {
+                            foreach (var g in toRemove)
+                            {
+                                remainingNodes.Remove(g);
+                            }
+                        }
+                    }
+                }
+
+                //Now process layers
+                for (int i = 0; i < layers.Count; i++)
+                {
+                    var lyr = layers[i];
+                    var ldfId = lyr.LayerDefinitionID;
+
+                    if (!_layerDefinitionContents.ContainsKey(ldfId.ToString()))
+                    {
+                        _layerDefinitionContents[ldfId.ToString()] = string.Empty;
+                    }
+                }
+
+                //TODO: Surely we can optimize this better
+                var keys = new List<string>(_layerDefinitionContents.Keys);
+                foreach (var lid in keys)
+                {
+                    using (var sr = new StreamReader(resSvc.GetResourceXmlData(lid)))
+                    {
+                        _layerDefinitionContents[lid] = sr.ReadToEnd();
+                    }
+                }
+
+                List<RuntimeMapLayer> remainingLayers = new List<RuntimeMapLayer>();
+                for (int i = 0; i < layers.Count; i++)
+                {
+                    var layer = layers[i];
+                    _layers.Add(layer.ObjectId, layer);
+
+                    bool display = layer.ShowInLegend;
+                    bool visible = layer.IsVisibleAtScale(_map.ViewScale);
+                    if (!display)
+                        continue;
+
+                    if (!visible)
+                        continue;
+
+                    //Add ones without parents first.
+                    if (layer.Group != null)
+                    {
+                        remainingLayers.Add(layer);
+                    }
+                    else
+                    {
+                        var node = CreateLayerNode(layer);
+                        if (node != null)
+                        {
+                            trvLegend.Nodes.Add(node);
+                            if (layer.ExpandInLegend)
+                                node.Expand();
+                        }
+                    }
+
+                    while (remainingLayers.Count > 0)
+                    {
+                        List<RuntimeMapLayer> toRemove = new List<RuntimeMapLayer>();
+                        for (int j = 0; j < remainingLayers.Count; j++)
+                        {
+                            var parentGroup = remainingLayers[j].GetParentGroup();
+                            var parentId = parentGroup.ObjectId;
+                            var nodes = trvLegend.Nodes.Find(parentId, false);
+                            if (nodes.Length == 1)
+                            {
+                                var node = CreateLayerNode(remainingLayers[j]);
+                                if (node != null)
+                                {
+                                    nodes[0].Nodes.Add(node);
+                                    if (remainingLayers[j].ExpandInLegend)
+                                        node.Expand();
+                                }
+                                toRemove.Add(remainingLayers[j]);
+                            }
+                        }
+                        //Whittle down this list
+                        if (toRemove.Count > 0)
+                        {
+                            foreach (var g in toRemove)
+                            {
+                                remainingLayers.Remove(g);
+                            }
+                        }
+                    }
+                }
+
+                //Now expand any relevant groups
+                for (int i = 0; i < groups.Count; i++)
+                {
+                    var group = groups[i];
+                    if (group.ExpandInLegend)
+                    {
+                        var nodes = trvLegend.Nodes.Find(group.ObjectId, false);
+                        if (nodes.Length == 1)
+                        {
+                            nodes[0].Expand();
+                        }
+                    }
+                }
+            }
+            finally
+            {
+                trvLegend.EndUpdate();
+            }
+        }
+
+        private static void ClearNodes(TreeNodeCollection nodes)
+        {
+            foreach (TreeNode node in nodes)
+            {
+                if (node.Nodes.Count > 0)
+                    ClearNodes(node.Nodes);
+
+                var layerMeta = node.Tag as LayerNodeMetadata;
+                if (layerMeta != null && layerMeta.ThemeIcon != null)
+                {
+                    layerMeta.Layer = null;
+                    layerMeta.ThemeIcon.Dispose();
+                    layerMeta.ThemeIcon = null;
+                }
+            }
+            nodes.Clear();
+        }
+
+        private void ResetTreeView()
+        {
+            ClearNodes(trvLegend.Nodes);
+            imgLegend.Images.Clear();
+
+            imgLegend.Images.Add(IMG_BROKEN, Properties.Resources.lc_broken);
+            imgLegend.Images.Add(IMG_DWF, Properties.Resources.lc_dwf);
+            imgLegend.Images.Add(IMG_GROUP, Properties.Resources.lc_group);
+            imgLegend.Images.Add(IMG_RASTER, Properties.Resources.lc_raster);
+            imgLegend.Images.Add(IMG_SELECT, Properties.Resources.lc_select);
+            imgLegend.Images.Add(IMG_THEME, Properties.Resources.lc_theme);
+            imgLegend.Images.Add(IMG_UNSELECT, Properties.Resources.lc_unselect);
+            imgLegend.Images.Add(IMG_OTHER, Properties.Resources.icon_etc);
+        }
+
+        private TreeNode CreateLayerNode(RuntimeMapLayer layer)
+        {
+            var node = new TreeNode();
+            node.Name = layer.ObjectId;
+            node.Text = layer.LegendLabel;
+            node.Checked = layer.Visible;
+            node.ContextMenuStrip = this.LayerContextMenu;
+            var lt = layer.Type;
+            var fsId = layer.FeatureSourceID;
+
+            if (fsId.EndsWith("DrawingSource"))
+            {
+                node.SelectedImageKey = node.ImageKey = IMG_DWF;
+                node.Tag = new LayerNodeMetadata(layer);
+                node.ToolTipText = string.Format(Properties.Resources.DrawingLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID);
+            }
+            else
+            {
+                string layerData = null;
+                var ldfId = layer.LayerDefinitionID;
+                if (_layerDefinitionContents.ContainsKey(ldfId.ToString()))
+                    layerData = _layerDefinitionContents[ldfId.ToString()];
+
+                if (layerData == null)
+                    return null;
+
+                XmlDocument doc = new XmlDocument();
+                doc.LoadXml(layerData);
+                int type = 0;
+                XmlNodeList scaleRanges = doc.GetElementsByTagName("VectorScaleRange");
+                if (scaleRanges.Count == 0)
+                {
+                    scaleRanges = doc.GetElementsByTagName("GridScaleRange");
+                    if (scaleRanges.Count == 0)
+                    {
+                        scaleRanges = doc.GetElementsByTagName("DrawingLayerDefinition");
+                        if (scaleRanges.Count == 0)
+                            return null;
+                        type = 2;
+                    }
+                    else
+                        type = 1;
+                }
+
+                String[] typeStyles = new String[] { "PointTypeStyle", "LineTypeStyle", "AreaTypeStyle", "CompositeTypeStyle" };
+                String[] ruleNames = new String[] { "PointRule", "LineRule", "AreaRule", "CompositeRule" };
+
+                try
+                {
+                    Image layerIcon = _map.GetLegendImage(layer.LayerDefinitionID,
+                                                          _map.ViewScale,
+                                                          16,
+                                                          16,
+                                                          "PNG",
+                                                          -1,
+                                                          -1);
+                    if (layerIcon != null)
+                    {
+                        string id = Guid.NewGuid().ToString();
+                        imgLegend.Images.Add(id, layerIcon);
+                        node.SelectedImageKey = node.ImageKey = id;
+                        node.Tag = new LayerNodeMetadata(layer)
+                        {
+                            ThemeIcon = layerIcon
+                        };
+                        node.ToolTipText = string.Format(Properties.Resources.DefaultLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID, layer.QualifiedClassName);
+                    }
+                    else
+                    {
+                        node.SelectedImageKey = node.ImageKey = IMG_BROKEN;
+                    }
+                }
+                catch
+                {
+                    node.SelectedImageKey = node.ImageKey = IMG_BROKEN;
+                }
+
+                for (int sc = 0; sc < scaleRanges.Count; sc++)
+                {
+                    XmlElement scaleRange = (XmlElement)scaleRanges[sc];
+                    XmlNodeList minElt = scaleRange.GetElementsByTagName("MinScale");
+                    XmlNodeList maxElt = scaleRange.GetElementsByTagName("MaxScale");
+                    String minScale, maxScale;
+                    minScale = "0";
+                    maxScale = "1000000000000.0";   // as MDF's VectorScaleRange::MAX_MAP_SCALE
+                    if (minElt.Count > 0)
+                        minScale = minElt[0].ChildNodes[0].Value;
+                    if (maxElt.Count > 0)
+                        maxScale = maxElt[0].ChildNodes[0].Value;
+                    
+                    if (type != 0)
+                        break;
+
+                    for (int geomType = 0; geomType < typeStyles.Length; geomType++)
+                    {
+                        int catIndex = 0;
+                        XmlNodeList typeStyle = scaleRange.GetElementsByTagName(typeStyles[geomType]);
+                        for (int st = 0; st < typeStyle.Count; st++)
+                        {
+                            // We will check if this typestyle is going to be shown in the legend
+                            XmlNodeList showInLegend = ((XmlElement)typeStyle[st]).GetElementsByTagName("ShowInLegend");
+                            if (showInLegend.Count > 0)
+                                if (!bool.Parse(showInLegend[0].ChildNodes[0].Value))
+                                    continue;   // This typestyle does not need to be shown in the legend
+
+                            XmlNodeList rules = ((XmlElement)typeStyle[st]).GetElementsByTagName(ruleNames[geomType]);
+                            if (rules.Count > 1)
+                            {
+                                node.SelectedImageKey = node.ImageKey = IMG_THEME;
+                                var layerMeta = node.Tag as LayerNodeMetadata;
+                                if (layerMeta != null)
+                                {
+                                    layerMeta.ThemeIcon = Properties.Resources.lc_theme;
+                                    node.ToolTipText = string.Format(Properties.Resources.ThemedLayerTooltip, Environment.NewLine, layer.Name, layer.FeatureSourceID, layer.QualifiedClassName, rules.Count);
+                                }
+                                if (this.ThemeCompressionLimit > 0 && rules.Count > this.ThemeCompressionLimit)
+                                {
+                                    AddThemeRuleNode(layer, node, geomType, 0, rules, 0);
+                                    node.Nodes.Add(CreateCompressedThemeNode(rules.Count - 2));
+                                    AddThemeRuleNode(layer, node, geomType, rules.Count - 1, rules, rules.Count - 1);
+                                }
+                                else
+                                {
+                                    for (int r = 0; r < rules.Count; r++)
+                                    {
+                                        AddThemeRuleNode(layer, node, geomType, catIndex++, rules, r);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            
+            return node;
+        }
+
+        private void AddThemeRuleNode(RuntimeMapLayer layer, TreeNode node, int geomType, int catIndex, XmlNodeList rules, int r)
+        {
+            XmlElement rule = (XmlElement)rules[r];
+            XmlNodeList label = rule.GetElementsByTagName("LegendLabel");
+            XmlNodeList filter = rule.GetElementsByTagName("Filter");
+
+            String labelText = "";
+            if (label != null && label.Count > 0 && label[0].ChildNodes.Count > 0)
+                labelText = label[0].ChildNodes[0].Value;
+            //String filterText = "";
+            //if (filter != null && filter.Count > 0 && filter[0].ChildNodes.Count > 0)
+            //    filterText = filter[0].ChildNodes[0].Value;
+
+            var child = CreateThemeRuleNode(layer.LayerDefinitionID, _map.ViewScale, labelText, (geomType + 1), catIndex);
+            node.Nodes.Add(child);
+        }
+
+        private TreeNode CreateCompressedThemeNode(int count)
+        {
+            TreeNode node = new TreeNode();
+            node.Text = (count + " other styles");
+            node.ImageKey = node.SelectedImageKey = IMG_OTHER;
+            node.Tag = new LayerNodeMetadata(null) {
+                IsBaseLayer = false,
+                ThemeIcon = Properties.Resources.icon_etc,
+                IsThemeRule = true
+            };
+            return node;
+        }
+
+        private TreeNode CreateThemeRuleNode(string layerDefId, double viewScale, string labelText, int geomType, int categoryIndex)
+        {
+            Image layerIcon = null;
+            try
+            {
+                layerIcon = _map.GetLegendImage(layerDefId,
+                                                      viewScale,
+                                                      16,
+                                                      16,
+                                                      "PNG",
+                                                      geomType,
+                                                      categoryIndex);
+            }
+            catch
+            {
+                layerIcon = Properties.Resources.lc_broken;
+            }
+            TreeNode node = new TreeNode();
+            node.Text = labelText;
+            if (layerIcon != null)
+            {
+                var tag = new LayerNodeMetadata(null)
+                {
+                    IsBaseLayer = false,
+                    IsThemeRule = true
+                };
+                string id = Guid.NewGuid().ToString();
+                tag.ThemeIcon = layerIcon;
+                node.Tag = tag;
+            }
+            return node;
+        }
+
+        private TreeNode CreateGroupNode(RuntimeMapGroup group)
+        {
+            var node = new TreeNode();
+            node.Name = group.ObjectId;
+            node.Text = group.LegendLabel;
+            node.Checked = group.Visible;
+            node.SelectedImageKey = node.ImageKey = IMG_GROUP;
+            node.Tag = new GroupNodeMetadata(group);
+            node.ContextMenuStrip = this.GroupContextMenu;
+            return node;
+        }
+
+        private double _scale;
+
+        /// <summary>
+        /// Sets the applicable scale
+        /// </summary>
+        /// <param name="scale"></param>
+        public void SetScale(double scale)
+        {
+            _scale = scale;
+            RefreshLegend();
+        }
+
+        class LegendNodeMetadata
+        {
+            public bool IsGroup { get; protected set; }
+        }
+
+        class GroupNodeMetadata : LegendNodeMetadata
+        {
+            internal RuntimeMapGroup Group { get; set; }
+
+            public GroupNodeMetadata(RuntimeMapGroup group) 
+            { 
+                base.IsGroup = true;
+                this.Group = group;
+            }
+        }
+
+        class LayerNodeMetadata : LegendNodeMetadata
+        {
+            public LayerNodeMetadata(RuntimeMapLayer layer) 
+            { 
+                base.IsGroup = false;
+                this.Layer = layer;
+                this.IsSelectable = (layer != null) ? layer.Selectable : false;
+                this.DrawSelectabilityIcon = (layer != null);
+                this.IsThemeRule = false;
+            }
+
+            internal RuntimeMapLayer Layer { get; set; }
+
+            public bool DrawSelectabilityIcon { get; set; }
+
+            public bool IsSelectable { get; set; }
+
+            public bool IsThemeRule { get; set; }
+
+            public bool IsBaseLayer { get; set; }
+
+            public Image ThemeIcon { get; set; }
+        }
+
+        private bool HasVisibleParent(RuntimeMapGroup grp)
+        {
+            var current = _map.Groups[grp.Group];
+            if (current != null)
+                return current.Visible;
+            return true;
+        }
+
+        private bool HasVisibleParent(RuntimeMapLayer layer)
+        {
+            var current = _map.Groups[layer.Group];
+            if (current != null)
+                return current.Visible;
+
+            return true;
+        }
+
+        private void trvLegend_AfterCheck(object sender, TreeViewEventArgs e)
+        {
+            if (e.Node.Tag == null)
+                return;
+
+            if (((LegendNodeMetadata)e.Node.Tag).IsGroup) //Group
+            {
+                if (_groups.ContainsKey(e.Node.Name))
+                {
+                    var grp = _groups[e.Node.Name];
+                    grp.Visible = e.Node.Checked;
+                    var bVis = HasVisibleParent(grp);
+                    if (bVis)
+                        OnRequestRefresh();
+                }
+            }
+            else //Layer
+            {
+                if (_layers.ContainsKey(e.Node.Name))
+                {
+                    var layer = _layers[e.Node.Name];
+                    layer.Visible = e.Node.Checked;
+                    var bVis = HasVisibleParent(layer);
+                    if (bVis)
+                    {
+                        layer.ForceRefresh();
+                        OnRequestRefresh();
+                    }
+                }
+            }
+        }
+
+        private void trvLegend_AfterExpand(object sender, TreeViewEventArgs e)
+        {
+            if (e.Node.Tag == null)
+                return;
+
+            if (((LegendNodeMetadata)e.Node.Tag).IsGroup) //Group
+            {
+                if (_groups.ContainsKey(e.Node.Name))
+                {
+                    _groups[e.Node.Name].ExpandInLegend = true;
+                    _map.Save();
+                }
+            }
+            else //Layer
+            {
+                if (_layers.ContainsKey(e.Node.Name))
+                {
+                    var layer = _layers[e.Node.Name];
+                    layer.ExpandInLegend = true;
+                    _map.Save();
+                }
+            }
+        }
+
+        private void trvLegend_AfterCollapse(object sender, TreeViewEventArgs e)
+        {
+            if (e.Node.Tag == null)
+                return;
+
+            if (((LegendNodeMetadata)e.Node.Tag).IsGroup) //Group
+            {
+                if (_groups.ContainsKey(e.Node.Name))
+                {
+                    _groups[e.Node.Name].ExpandInLegend = true;
+                    _map.Save();
+                }
+            }
+            else //Layer
+            {
+                if (_layers.ContainsKey(e.Node.Name))
+                {
+                    var layer = _layers[e.Node.Name];
+                    layer.ExpandInLegend = true;
+                    _map.Save();
+                }
+            }
+        }
+
+        private bool _noUpdate = false;
+
+        private void OnRequestRefresh()
+        {
+            if (this.Viewer != null)
+                this.Viewer.RefreshMap();
+        }
+
+        private static bool IsThemeLayerNode(TreeNode node)
+        {
+            var meta = node.Tag as LayerNodeMetadata;
+            if (meta != null)
+                return meta.ThemeIcon != null || meta.IsBaseLayer;
+
+            return false;
+        }
+
+        private static bool IsLayerNode(TreeNode node)
+        {
+            var meta = node.Tag as LayerNodeMetadata;
+            return meta != null;
+        }
+
+        private void trvLegend_DrawNode(object sender, DrawTreeNodeEventArgs e)
+        {
+            if (IsLayerNode(e.Node) && !e.Bounds.IsEmpty)
+            {
+                //TODO: Render +/- for nodes with children (ie. Themed layers)
+                Color backColor, foreColor;
+
+                //For some reason, the default bounds are way off from what you would
+                //expect it to be. So we apply this offset for any text/image draw operations
+                int xoffset = -36;
+
+                if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
+                {
+                    backColor = SystemColors.Highlight;
+                    foreColor = SystemColors.HighlightText;
+                }
+                else if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
+                {
+                    backColor = SystemColors.HotTrack;
+                    foreColor = SystemColors.HighlightText;
+                }
+                else
+                {
+                    backColor = e.Node.BackColor;
+                    foreColor = e.Node.ForeColor;
+                }
+
+                var tag = e.Node.Tag as LayerNodeMetadata;
+                var checkBoxOffset = xoffset;
+                var selectabilityOffset = xoffset + 16;
+                var iconOffsetNoSelect = xoffset + 16;
+                if (tag != null && tag.IsThemeRule) //No checkbox for theme rule nodes
+                {
+                    selectabilityOffset = xoffset;
+                    iconOffsetNoSelect = xoffset;
+                }
+                var iconOffset = selectabilityOffset + 20;
+                var textOffset = iconOffset + 20;
+                var textOffsetNoSelect = iconOffsetNoSelect + 20;
+
+                //Uncomment if you need to "see" the bounds of the node
+                //e.Graphics.DrawRectangle(Pens.Black, e.Node.Bounds);
+
+                if (tag != null && !tag.IsThemeRule) //No checkbox for theme rule nodes
+                {
+                    CheckBoxRenderer.DrawCheckBox(
+                        e.Graphics,
+                        new Point(e.Node.Bounds.X + checkBoxOffset, e.Node.Bounds.Y),
+                        e.Node.Checked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal);
+                }
+                if (tag != null)
+                {
+                    if (tag.DrawSelectabilityIcon)
+                    {
+                        var icon = tag.IsSelectable ? _selectableIcon : _unselectableIcon;
+                        e.Graphics.DrawImage(icon, e.Node.Bounds.X + selectabilityOffset, e.Node.Bounds.Y);
+                        Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
+                    }
+                    if (tag.ThemeIcon != null)
+                    {
+                        if (tag.DrawSelectabilityIcon)
+                        {
+                            e.Graphics.DrawImage(tag.ThemeIcon, e.Node.Bounds.X + iconOffset, e.Node.Bounds.Y);
+                            Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
+                        }
+                        else
+                        {
+                            e.Graphics.DrawImage(tag.ThemeIcon, e.Node.Bounds.X + iconOffsetNoSelect, e.Node.Bounds.Y);
+                            Trace.TraceInformation("Painted icon at ({0},{1})", e.Node.Bounds.X, e.Node.Bounds.Y);
+                        }
+                    }
+
+                    using (SolidBrush brush = new SolidBrush(Color.Black))
+                    {
+                        e.Graphics.DrawString(e.Node.Text, trvLegend.Font, brush, e.Node.Bounds.X + (tag.DrawSelectabilityIcon ? textOffset : textOffsetNoSelect), e.Node.Bounds.Y);
+                    }
+                }
+                else
+                {
+                    using (SolidBrush brush = new SolidBrush(Color.Black))
+                    {
+                        e.Graphics.DrawString(e.Node.Text, trvLegend.Font, brush, e.Node.Bounds.X + 17.0f + xoffset, e.Node.Bounds.Y);
+                    }
+                }
+
+                e.DrawDefault = false;
+            }
+            else
+            {
+                e.DrawDefault = true;
+            }
+        }
+
+        private ContextMenuStrip _grpContextMenu;
+
+        private ContextMenuStrip _layerContextMenu;
+
+        /// <summary>
+        /// Gets or sets the context menu that is attached to group nodes
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The context menu to attach to group nodes")]
+        public ContextMenuStrip GroupContextMenu
+        {
+            get { return _grpContextMenu; }
+            set
+            {
+                if (_grpContextMenu != null)
+                    _grpContextMenu.Opening -= OnGroupContextMenuOpening;
+
+                _grpContextMenu = value;
+                if (_grpContextMenu != null)
+                    _grpContextMenu.Opening += OnGroupContextMenuOpening;
+                if (!this.DesignMode)
+                    RefreshLegend();
+            }
+        }
+
+        private void OnGroupContextMenuOpening(object sender, CancelEventArgs e)
+        {
+
+        }
+
+        /// <summary>
+        /// Gets or sets the context menu that is attached to layer nodes
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The context menu to attach to layer nodes")]
+        public ContextMenuStrip LayerContextMenu
+        {
+            get { return _layerContextMenu; }
+            set
+            {
+                if (_layerContextMenu != null)
+                    _layerContextMenu.Opening -= OnLayerContextMenuOpening;
+
+                _layerContextMenu = value;
+                if (_layerContextMenu != null)
+                    _layerContextMenu.Opening += OnLayerContextMenuOpening;
+                if (!this.DesignMode)
+                    RefreshLegend();
+            }
+        }
+
+        private int _themeCompressionLimit;
+
+        /// <summary>
+        /// Gets or sets the theme compression limit.
+        /// </summary>
+        /// <value>
+        /// The theme compression limit.
+        /// </value>
+        [Category("MapGuide Viewer")]
+        [Description("The number of rules a layer style must exceed in order to be displayed as a compressed theme")]
+        public int ThemeCompressionLimit
+        {
+            get { return _themeCompressionLimit; }
+            set { _themeCompressionLimit = value; }
+        }
+
+        private void OnLayerContextMenuOpening(object sender, CancelEventArgs e)
+        {
+
+        }
+
+        private void trvLegend_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
+        {
+            if (e.Button == MouseButtons.Right)
+            {
+                trvLegend.SelectedNode = e.Node;
+            }
+            var meta = e.Node.Tag as LayerNodeMetadata;
+            if (meta != null && meta.DrawSelectabilityIcon)
+            {
+                //Toggle layer's selectability if it's within the bounds of the selectability icon
+                var box = new Rectangle(
+                    new Point((e.Node.Bounds.Location.X - 36) + 16, e.Node.Bounds.Location.Y), 
+                    new Size(16, e.Node.Bounds.Height));
+                if (box.Contains(e.X, e.Y))
+                {
+                    var layer = meta.Layer;
+                    layer.Selectable = !layer.Selectable;
+                    _map.Save();
+                    meta.IsSelectable = layer.Selectable;
+
+                    //TODO: This bounds is a guess. We should calculate the bounds as part of node rendering, so we know the exact bounds by which to invalidate
+                    trvLegend.Invalidate(new Rectangle(e.Node.Bounds.Location.X - 36, e.Node.Bounds.Location.Y, e.Node.Bounds.Width + 36, e.Node.Bounds.Height));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the selected layer
+        /// </summary>
+        /// <returns></returns>
+        public RuntimeMapLayer GetSelectedLayer()
+        {
+            if (_map == null)
+                return null;
+
+            if (trvLegend.SelectedNode == null)
+                return null;
+
+            var lyr = trvLegend.SelectedNode.Tag as LayerNodeMetadata;
+            if (lyr != null)
+                return lyr.Layer;
+
+            return null;
+        }
+
+        /// <summary>
+        /// Gets the selected group
+        /// </summary>
+        /// <returns></returns>
+        public RuntimeMapGroup GetSelectedGroup()
+        {
+            if (_map == null)
+                return null;
+
+            if (trvLegend.SelectedNode == null)
+                return null;
+
+            var grp = trvLegend.SelectedNode.Tag as GroupNodeMetadata;
+            if (grp != null)
+                return grp.Group;
+
+            return null;
+        }
+
+        public bool ShowTooltips
+        {
+            get { return trvLegend.ShowNodeToolTips; }
+            set { trvLegend.ShowNodeToolTips = value; }
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.MapViewer/Legend.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Legend.resx	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Legend.resx	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="imgLegend.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file

Added: trunk/Tools/Maestro/Maestro.MapViewer/Maestro.MapViewer.csproj
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Maestro.MapViewer.csproj	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Maestro.MapViewer.csproj	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Maestro.MapViewer</RootNamespace>
+    <AssemblyName>Maestro.MapViewer</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\SDK\bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\GlobalAssemblyInfo.cs">
+      <Link>GlobalAssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="..\Properties\SignedAssemblyInfo.cs">
+      <Link>SignedAssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="CoreTypes.cs" />
+    <Compile Include="DefaultToolbar.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Interfaces.cs" />
+    <Compile Include="Legend.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Legend.Designer.cs">
+      <DependentUpon>Legend.cs</DependentUpon>
+    </Compile>
+    <Compile Include="MapStatusTracker.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="MapViewer.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\OSGeo.MapGuide.MaestroAPI\OSGeo.MapGuide.MaestroAPI.csproj">
+      <Project>{80FA3158-8B5F-48D1-A393-0378AFE48A7E}</Project>
+      <Name>OSGeo.MapGuide.MaestroAPI</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Legend.resx">
+      <DependentUpon>Legend.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\about.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\buffer.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\control.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\control-180.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\edit-copy.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\edit-cut.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\edit-duplicate.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\edit-paste.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\edit-xml.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\error.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\file-print.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\file-save.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\help.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\icon_etc.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\icon_home.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\icon_loading.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\icon_pan.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\icon_select.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\icon_tasks.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\icon_zoomselect.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\iconNavigator.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\info.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\initial-center.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\invoke-script.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\invoke-url.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\layer-shape.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\layer-shape-ellipse.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\layer-shape-line.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\layer-shape-polygon.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\layer-shape-polyline.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\layer-small.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\lc_broken.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\lc_dwf.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\lc_group.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\lc_raster.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\lc_select.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\lc_theme.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\lc_unselect.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\load_package.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\measure.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\monitor_status.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\options.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\overview-map.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\PoweredBy_en.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\preview.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\print.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\search.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\select-centre.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\select-clear.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\select-features.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\select-polygon.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\select-radius.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\select-zoom.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\ui-tooltip-balloon-bottom.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\view-back.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\view-forward.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\view_log.gif" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\view-refresh.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\zoom-dynamic.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\zoom-full.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\zoom-in.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\zoom-in-fixed.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\zoom-out-fixed.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\grab.cur" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\zoomin.cur" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\zoomout.cur" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

Added: trunk/Tools/Maestro/Maestro.MapViewer/MapStatusTracker.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/MapStatusTracker.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/MapStatusTracker.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,117 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel;
+using System.Windows.Forms;
+
+namespace Maestro.MapViewer
+{
+    public class MapStatusTracker : Component
+    {
+        private IMapViewer _viewer;
+
+        public IMapViewer Viewer
+        {
+            get { return _viewer; }
+            set 
+            {
+                if (_viewer != null)
+                    UnwireViewer(_viewer);
+                _viewer = value;
+                if (value != null)
+                    WireViewer(value);
+            }
+        }
+
+        public ToolStripLabel SelectedLabel { get; set; }
+
+        public ToolStripLabel ScaleLabel { get; set; }
+
+        public ToolStripLabel CoordinatesLabel { get; set; }
+
+        private void WireViewer(IMapViewer viewer)
+        {
+            viewer.MapScaleChanged += OnMapScaleChanged;
+            viewer.MouseMapPositionChanged += OnMapPositionChanged;
+            viewer.SelectionChanged += OnMapSelectionChanged;
+            viewer.MapRefreshed += OnMapRefreshed;
+        }
+
+        private void UnwireViewer(IMapViewer viewer)
+        {
+            viewer.MapScaleChanged -= OnMapScaleChanged;
+            viewer.MouseMapPositionChanged -= OnMapPositionChanged;
+            viewer.SelectionChanged -= OnMapSelectionChanged;
+            viewer.MapRefreshed -= OnMapRefreshed;
+        }
+
+        void OnMapRefreshed(object sender, EventArgs e)
+        {
+            if (this.ScaleLabel == null)
+                return;
+
+            var map = this.Viewer.GetMap();
+            if (this.ScaleLabel != null)
+                this.ScaleLabel.Text = string.Format("1:{0:0.00000}", map.ViewScale);
+        }
+
+        void OnMapSelectionChanged(object sender, EventArgs e)
+        {
+            if (this.SelectedLabel == null)
+                return;
+
+            var map = this.Viewer.GetMap();
+            var sel = map.Selection;
+            if (sel.Count > 0)
+            {
+                int total = 0;
+                for (int i = 0; i < sel.Count; i++)
+                    total += sel[i].Count;
+
+                this.SelectedLabel.Text = string.Format(Properties.Resources.TextSelectedFeatures, total);
+            }
+            else
+            {
+                this.SelectedLabel.Text = string.Format(Properties.Resources.TextSelectedFeatures, 0);
+            }
+        }
+
+        void OnMapPositionChanged(object sender, MapPointEventArgs e)
+        {
+            if (this.CoordinatesLabel == null)
+                return;
+
+            this.CoordinatesLabel.Text = string.Format(Properties.Resources.TextCoordinatePosition, e.X, e.Y);
+        }
+
+        void OnMapScaleChanged(object sender, EventArgs e)
+        {
+            if (this.ScaleLabel == null)
+                return;
+
+            var map = this.Viewer.GetMap();
+            if (this.ScaleLabel != null)
+                this.ScaleLabel.Text = string.Format("1:{0:0.00000}", map.ViewScale);
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.MapViewer/MapViewer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/MapViewer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/MapViewer.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,2376 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+using System.Drawing;
+using System.ComponentModel;
+using System.IO;
+using System.Drawing.Drawing2D;
+using System.Diagnostics;
+using System.Threading;
+using System.Xml;
+using System.Collections.Specialized;
+using System.Collections.ObjectModel;
+using OSGeo.MapGuide.MaestroAPI.Services;
+using OSGeo.MapGuide.MaestroAPI.Mapping;
+using OSGeo.MapGuide.MaestroAPI.Schema;
+using OSGeo.MapGuide.ObjectModels.Common;
+using OSGeo.MapGuide.ObjectModels;
+using OSGeo.MapGuide.MaestroAPI;
+
+namespace Maestro.MapViewer
+{
+    [ToolboxItem(true)]
+    public class MapViewer : Control, IMapViewer
+    {
+        private BackgroundWorker renderWorker;
+
+        private RuntimeMap _map;
+        private MapSelection _selection;
+        private ViewerRenderingOptions _overlayRenderOpts;
+        private ViewerRenderingOptions _selectionRenderOpts;
+
+        private Color _mapBgColor;
+
+        private double _orgX1;
+        private double _orgX2;
+        private double _orgY1;
+        private double _orgY2;
+
+        private double _extX1;
+        private double _extX2;
+        private double _extY1;
+        private double _extY2;
+
+        private Image _selectionImage;
+        private Image _mapImage;
+
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        internal Image Image
+        {
+            get { return _mapImage; }
+            set
+            {
+                _mapImage = value;
+                //Invalidate();
+            }
+        }
+
+        const double MINIMUM_ZOOM_SCALE = 5.0;
+
+#if VIEWER_DEBUG
+        private MgdLayer _debugLayer;
+
+        private void CreateDebugFeatureSource()
+        {
+            var id = new MgDataPropertyDefinition("ID");
+            id.DataType = MgPropertyType.Int32;
+            id.Nullable = false;
+            id.SetAutoGeneration(true);
+
+            var geom = new MgGeometricPropertyDefinition("Geometry");
+            geom.GeometryTypes = MgFeatureGeometricType.Point;
+            geom.SpatialContextAssociation = "MapCs";
+
+            var cls = new MgClassDefinition();
+            cls.Name = "Debug";
+            var props = cls.GetProperties();
+            props.Add(id);
+            props.Add(geom);
+
+            var idProps = cls.GetIdentityProperties();
+            idProps.Add(id);
+
+            cls.DefaultGeometryPropertyName = "Geometry";
+
+            var schema = new MgFeatureSchema("Default", "Default schema");
+            var classes = schema.GetClasses();
+            classes.Add(cls);
+
+            //We can make anything up here, there's no real concept of sessions
+            var sessionId = Guid.NewGuid().ToString();
+
+            var debugFsId = new MgResourceIdentifier("Session:" + sessionId + "//Debug" + Guid.NewGuid().ToString() + ".FeatureSource");
+            var createSdf = new MgCreateSdfParams("MapCs", _map.GetMapSRS(), schema);
+            var featureSvc = (MgdFeatureService)fact.CreateService(MgServiceType.FeatureService);
+            var resSvc = (MgResourceService)fact.CreateService(MgServiceType.ResourceService);
+            featureSvc.CreateFeatureSource(debugFsId, createSdf);
+
+            byte[] bytes = Encoding.UTF8.GetBytes(string.Format(Debug.DebugLayer, debugFsId.ToString(), "Default:Debug", "Geometry"));
+            var source = new MgByteSource(bytes, bytes.Length);
+
+            var debugLayerId = new MgResourceIdentifier("Session:" + sessionId + "//" + debugFsId.Name + ".LayerDefinition");
+            var breader = source.GetReader();
+            resSvc.SetResource(debugLayerId, breader, null);
+            
+            _debugLayer = new MgdLayer(debugLayerId, resSvc);
+            _debugLayer.SetLegendLabel("Debug Layer");
+            _debugLayer.SetVisible(true);
+            _debugLayer.SetDisplayInLegend(true);
+
+            var mapLayers = _map.GetLayers();
+            mapLayers.Insert(0, _debugLayer);
+
+            UpdateCenterDebugPoint();
+        }
+
+        private MgPropertyCollection _debugCenter;
+
+        private void UpdateCenterDebugPoint()
+        {
+            if (_debugCenter == null)
+                _debugCenter = new MgPropertyCollection();
+
+            var center = _wktRW.Read("POINT (" + _map.ViewCenter.Coordinate.X + " " + _map.ViewCenter.Coordinate.Y + ")");
+            var agf = _agfRW.Write(center);
+            if (!_debugCenter.Contains("Geometry"))
+            {
+                MgGeometryProperty geom = new MgGeometryProperty("Geometry", agf);
+                _debugCenter.Add(geom);
+            }
+            else
+            {
+                MgGeometryProperty geom = (MgGeometryProperty)_debugCenter.GetItem("Geometry");
+                geom.SetValue(agf);
+            }
+
+            int deleted = _debugLayer.DeleteFeatures("");
+            Trace.TraceInformation("Deleted {0} debug points", deleted);
+            var reader = _debugLayer.InsertFeatures(_debugCenter);
+            int inserted = 0;
+            while (reader.ReadNext())
+            {
+                inserted++;
+            }
+            reader.Close();
+            Trace.TraceInformation("Added {0} debug points", inserted);
+            _debugLayer.ForceRefresh();
+        }
+#endif
+
+        private int _viewHistoryIndex;
+        private List<MapViewHistoryEntry> _viewHistory;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MapViewer"/> class.
+        /// </summary>
+        public MapViewer()
+        {
+            _viewHistory = new List<MapViewHistoryEntry>();
+            _viewHistoryIndex = -1;
+            this.ShowVertexCoordinatesWhenDigitizing = false;
+            this.FeatureTooltipsEnabled = false;
+            this.TooltipsEnabled = false;
+            this.ZoomInFactor = 0.5;
+            this.ZoomOutFactor = 2.0;
+            this.SelectionColor = Color.Blue;
+            this.PointPixelBuffer = 2;
+
+            this.DigitizingFillTransparency = 100;
+            this.DigitizingOutline = Brushes.Red;
+            this.DigitzingFillColor = Color.White;
+            this.TooltipFillColor = Color.LightYellow;
+            this.TooltipFillTransparency = 200;
+
+            this.ActiveTool = MapActiveTool.None;
+            this.DoubleBuffered = true;
+            SetStyle(ControlStyles.UserPaint, true);
+            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+            SetStyle(ControlStyles.DoubleBuffer, true);
+            SetStyle(ControlStyles.UserPaint, true);
+            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
+            SetStyle(ControlStyles.DoubleBuffer, true);
+
+            _mapBgColor = Color.Transparent;
+            
+            renderWorker = new BackgroundWorker();
+
+            renderWorker.DoWork += renderWorker_DoWork;
+            renderWorker.RunWorkerCompleted += renderWorker_RunWorkerCompleted;
+
+            base.MouseUp += OnMapMouseUp;
+            base.MouseMove += OnMapMouseMove;
+            base.MouseDown += OnMapMouseDown;
+            base.MouseClick += OnMapMouseClick;
+            base.MouseDoubleClick += OnMapMouseDoubleClick;
+            base.MouseHover += OnMapMouseHover;
+            base.MouseEnter += OnMouseEnter;
+        }
+
+        /// <summary>
+        /// Raises the <see cref="E:System.Windows.Forms.Control.KeyUp"/> event.
+        /// </summary>
+        /// <param name="e">A <see cref="T:System.Windows.Forms.KeyEventArgs"/> that contains the event data.</param>
+        protected override void OnKeyUp(KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Escape)
+            {
+                CancelDigitization();
+            }
+        }
+
+        private void CancelDigitization()
+        {
+            if (this.DigitizingType != MapDigitizationType.None)
+            {
+                dPath.Clear();
+                dPtStart.X = 0;
+                dPtStart.Y = 0;
+                this.DigitizingType = MapDigitizationType.None;
+                Trace.TraceInformation("Digitization cancelled");
+                this.Invalidate();
+            }
+        }
+
+        void OnMouseEnter(object sender, EventArgs e)
+        {
+            this.Focus();   
+        }
+
+        void OnMapMouseHover(object sender, EventArgs e)
+        {
+            HandleMouseHover(e);
+        }
+
+        private void HandleMouseHover(EventArgs e)
+        {
+            
+        }
+
+        /// <summary>
+        /// Releases the unmanaged resources used by the <see cref="T:System.Windows.Forms.Control"/> and its child controls and optionally releases the managed resources.
+        /// </summary>
+        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                base.MouseUp -= OnMapMouseUp;
+                base.MouseMove -= OnMapMouseMove;
+                base.MouseDown -= OnMapMouseDown;
+                base.MouseClick -= OnMapMouseClick;
+                base.MouseDoubleClick -= OnMapMouseDoubleClick;
+                base.MouseHover -= OnMapMouseHover;
+                base.MouseEnter -= OnMouseEnter;
+
+                if (renderWorker != null)
+                {
+                    renderWorker.DoWork -= renderWorker_DoWork;
+                    renderWorker.RunWorkerCompleted -= renderWorker_RunWorkerCompleted;
+                }
+            }
+            base.Dispose(disposing);
+        }
+
+        private Color _selColor;
+
+        /// <summary>
+        /// Gets or sets the color used to render selected features
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The color to use for active selections")]
+        public Color SelectionColor
+        {
+            get { return _selColor; }
+            set 
+            { 
+                _selColor = value;
+                OnPropertyChanged("SelectionColor");
+            }
+        }
+
+        private Color _tooltipFillColor;
+
+        /// <summary>
+        /// Gets or sets the color of the tooltip fill.
+        /// </summary>
+        /// <value>
+        /// The color of the tooltip fill.
+        /// </value>
+        [Category("MapGuide Viewer")]
+        [Description("The color background for feature tooltips")]
+        internal Color TooltipFillColor
+        {
+            get { return _tooltipFillColor; }
+            set
+            {
+                if (!value.Equals(_tooltipFillColor))
+                {
+                    _tooltipFillColor = value;
+                    OnPropertyChanged("TooltipFillColor");
+                }
+            }
+        }
+
+        private int _tooltipFillTransparency;
+
+        [Category("MapGuide Viewer")]
+        [Description("The color background transparency for feature tooltips")]
+        [DefaultValue(200)]
+        internal int TooltipFillTransparency
+        {
+            get { return _tooltipFillTransparency; }
+            set
+            {
+                if (!value.Equals(_tooltipFillTransparency))
+                {
+                    _tooltipFillTransparency = value;
+                    OnPropertyChanged("TooltipFillTransparency");
+                }
+            }
+        }
+
+        private void UpdateSelectionRenderingOptions()
+        {
+            var value = this.SelectionColor;
+            if (_selectionRenderOpts != null)
+            {
+                var color = _selectionRenderOpts.Color;
+                if (!color.Equals(value))
+                {
+                    _selectionRenderOpts = null;
+
+                    _selectionRenderOpts = CreateSelectionRenderingOptions(value.R, value.G, value.B);
+                    Trace.TraceInformation("Selection color updated to ({0}, {1}, {2})", value.R, value.G, value.B);
+                }
+            }
+            
+        }
+
+        private bool _showVertexCoords;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether [show vertex coordinates when digitizing].
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if [show vertex coordinates when digitizing]; otherwise, <c>false</c>.
+        /// </value>
+        [Category("MapGuide Viewer")]
+        [Description("Indicates whether coordinate values are shown when digitizing geometry")]
+        [DefaultValue(false)]
+        public bool ShowVertexCoordinatesWhenDigitizing
+        {
+            get { return _showVertexCoords; }
+            set
+            {
+                if (!value.Equals(_showVertexCoords))
+                {
+                    _showVertexCoords = value;
+                    OnPropertyChanged("ShowVertexCoordinatesWhenDigitizing");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
+        /// </summary>
+        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
+        protected override void OnPaint(PaintEventArgs e)
+        {
+            base.OnPaint(e);
+            Trace.TraceInformation("OnPaint(e)");
+
+            if (!translate.IsEmpty)
+                e.Graphics.TranslateTransform(translate.X, translate.Y);
+
+            if (_mapImage != null)
+            {
+                Trace.TraceInformation("Render Map");
+                e.Graphics.DrawImage(_mapImage, new PointF(0, 0));
+            }
+
+            //Thread.Sleep(100);
+            if (_selectionImage != null)
+            {
+                Trace.TraceInformation("Render Selection");
+                e.Graphics.DrawImage(_selectionImage, new PointF(0, 0));
+            }
+
+            if (isDragging && (this.ActiveTool == MapActiveTool.Select || this.ActiveTool == MapActiveTool.ZoomIn))
+            {
+                DrawDragRectangle(e);
+            }
+            else
+            {
+                if (this.DigitizingType != MapDigitizationType.None)
+                {
+                    if (this.DigitizingType == MapDigitizationType.Point)
+                    {
+                        DrawTrackingTooltip(e, "Click to finish. Press ESC to cancel");
+                    }
+                    else
+                    {
+                        if (!dPtStart.IsEmpty)
+                        {
+                            switch (this.DigitizingType)
+                            {
+                                case MapDigitizationType.Circle:
+                                    DrawTracingCircle(e);
+                                    break;
+                                case MapDigitizationType.Line:
+                                    DrawTracingLine(e);
+                                    break;
+                                case MapDigitizationType.Rectangle:
+                                    DrawTracingRectangle(e);
+                                    break;
+                            }
+                        }
+                        else if (dPath.Count > 0)
+                        {
+                            switch (this.DigitizingType)
+                            {
+                                case MapDigitizationType.LineString:
+                                    DrawTracingLineString(e);
+                                    break;
+                                case MapDigitizationType.Polygon:
+                                    DrawTracingPolygon(e);
+                                    break;
+                            }
+                        }
+                    }
+                }
+                else //None
+                {
+                    if (this.ActiveTool != MapActiveTool.None)
+                    {
+                        if (!string.IsNullOrEmpty(_activeTooltipText))
+                            DrawTrackingTooltip(e, _activeTooltipText);
+                    }
+                }
+            }
+        }
+
+        private Brush _digitizingOutline;
+
+        [Category("MapGuide Viewer")]
+        [Description("The outline color for geometries being digitized")]
+        internal Brush DigitizingOutline
+        {
+            get { return _digitizingOutline; }
+            set
+            {
+                _digitizingOutline = value;
+                OnPropertyChanged("DigitizingOutline");
+            }
+        }
+
+        private int _digitizingFillTransparency;
+
+        [Category("MapGuide Viewer")]
+        [Description("The fill color transparency for geometries being digitized")]
+        [DefaultValue(100)]
+        internal int DigitizingFillTransparency
+        {
+            get { return _digitizingFillTransparency; }
+            set
+            {
+                if (!value.Equals(_digitizingFillTransparency))
+                {
+                    _digitizingFillTransparency = value;
+                    OnPropertyChanged("DigitizingFillTransparency");
+                }
+            }
+        }
+
+        [Category("MapGuide Viewer")]
+        [Description("The amount of pixels to buffer out by when doing point-based selections with the Select tool")]
+        public int PointPixelBuffer { get; set; }
+
+        private Color _digitizingFillColor;
+
+        [Category("MapGuide Viewer")]
+        [Description("The fill color for geometries being digitized")]
+        internal Color DigitzingFillColor
+        {
+            get { return _digitizingFillColor; }
+            set
+            {
+                _digitizingFillColor = value;
+                OnPropertyChanged("DigitzingFillColor");
+            }
+        }
+
+        private Pen CreateOutlinePen()
+        {
+            return new Pen(this.DigitizingOutline, 2.0f);
+        }
+
+        private Brush CreateFillBrush()
+        {
+            return new SolidBrush(Color.FromArgb(this.DigitizingFillTransparency, this.DigitzingFillColor));
+        }
+
+        private static double GetDistanceBetween(PointF a, PointF b)
+        {
+            return (Math.Sqrt(Math.Pow(Math.Abs(a.X - b.X), 2) + Math.Pow(Math.Abs(a.Y - b.Y), 2)));
+        }
+
+        private void DrawVertexCoordinates(PaintEventArgs e, double devX, double devY, bool mapSpace)
+        {
+            if (!this.ShowVertexCoordinatesWhenDigitizing)
+                return;
+
+            string text = "";
+            if (mapSpace)
+            {
+                var mapPt = ScreenToMapUnits(devX, devY);
+                text = string.Format("X: {0}, Y: {1}", mapPt.X, mapPt.Y);
+            }
+            else
+            {
+                text = string.Format("X: {0}, Y: {1}", devX, devY);
+            }
+
+            var f = Control.DefaultFont;
+            SizeF size = e.Graphics.MeasureString(text, Font);
+            var vertex = new PointF((float)devX, (float)devY);
+
+            //Offset so that the "box" for this string is centered on the vertex itself
+            vertex.X -= (size.Width / 2);
+
+            //Fill the surrounding box
+            e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(200, Color.WhiteSmoke)), vertex.X, vertex.Y, size.Width, size.Height);
+            e.Graphics.DrawRectangle(Pens.Red, vertex.X, vertex.Y, size.Width, size.Height);
+
+            //Draw the string
+            e.Graphics.DrawString(text, f, Brushes.Black, vertex);
+        }
+
+        private void DrawTrackingTooltip(PaintEventArgs e, string text)
+        {
+            if (string.IsNullOrEmpty(text)) //Nothing to draw
+                return;
+
+            var f = Control.DefaultFont;
+            
+            
+            int height = 0;
+            int width = 0;
+            string [] tokens = text.Split(new string[] {"\\n", "\\r\\n", "\n", Environment.NewLine }, StringSplitOptions.None);
+            foreach(string t in tokens)
+            {
+                var size = e.Graphics.MeasureString(t, f);
+                height += (int)size.Height;
+
+                width = Math.Max(width, (int)size.Width);
+            }
+
+            e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(this.TooltipFillTransparency, this.TooltipFillColor)), new Rectangle(_mouseX, _mouseY, width + 10, height + 4));
+            float y = 2.0f;
+            float heightPerLine = height / tokens.Length;
+            foreach (string t in tokens)
+            {
+                e.Graphics.DrawString(t, f, Brushes.Black, new PointF(_mouseX + 5.0f, _mouseY + y));
+                y += heightPerLine;
+            }
+        }
+
+        private void DrawTracingCircle(PaintEventArgs e)
+        {
+            var pt2 = new Point(dPtStart.X, dPtStart.Y);
+            var diameter = (float)GetDistanceBetween(dPtStart, new PointF(_mouseX, _mouseY)) * 2.0f;
+            //Trace.TraceInformation("Diameter ({0}, {1} -> {2}, {3}): {4}", dPtStart.X, dPtStart.Y, _mouseX, _mouseY, diameter);
+            pt2.Offset((int)-(diameter / 2), (int)-(diameter / 2));
+            e.Graphics.DrawEllipse(CreateOutlinePen(), pt2.X, pt2.Y, diameter, diameter);
+            e.Graphics.FillEllipse(CreateFillBrush(), pt2.X, pt2.Y, diameter, diameter);
+
+            DrawTrackingTooltip(e, "Click to finish. Press ESC to cancel");
+        }
+
+        private void DrawTracingLine(PaintEventArgs e)
+        {
+            e.Graphics.DrawLine(CreateOutlinePen(), dPtStart, new Point(_mouseX, _mouseY));
+            DrawVertexCoordinates(e, dPtStart.X, dPtStart.Y, true);
+            DrawVertexCoordinates(e, _mouseX, _mouseY, true);
+            DrawTrackingTooltip(e, "Click to finish. Press ESC to cancel");
+        }
+
+        private void DrawTracingLineString(PaintEventArgs e)
+        {
+            //Not enough points to constitute a line string or polygon
+            if (dPath.Count < 2)
+                return;
+            
+            e.Graphics.DrawLines(CreateOutlinePen(), dPath.ToArray());
+            foreach (var pt in dPath)
+            {
+                DrawVertexCoordinates(e, pt.X, pt.Y, true);
+            }
+
+            DrawTrackingTooltip(e, "Click again to add a new vertex.\nDouble-click to finish. Press ESC to cancel");
+        }
+
+        private void DrawTracingPolygon(PaintEventArgs e)
+        {
+            //Not enough points to constitute a line string or polygon
+            if (dPath.Count < 2)
+                return;
+
+            e.Graphics.DrawPolygon(CreateOutlinePen(), dPath.ToArray());
+            e.Graphics.FillPolygon(CreateFillBrush(), dPath.ToArray());
+            foreach (var pt in dPath)
+            {
+                DrawVertexCoordinates(e, pt.X, pt.Y, true);
+            }
+
+            DrawTrackingTooltip(e, "Click again to add a new vertex.\nDouble-click to finish. Press ESC to cancel");
+        }
+
+        private void DrawTracingRectangle(PaintEventArgs e)
+        {
+            var rect = GetRectangle(dragStart, new Point(_mouseX, _mouseY));
+            if (rect.HasValue)
+            {
+                var r = rect.Value;
+                Trace.TraceInformation("Draw rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+                e.Graphics.DrawRectangle(CreateOutlinePen(), r);
+                Trace.TraceInformation("Fill rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+                e.Graphics.FillRectangle(CreateFillBrush(), r);
+
+                DrawVertexCoordinates(e, r.Left, r.Top, true);
+                DrawVertexCoordinates(e, r.Left, r.Bottom, true);
+                DrawVertexCoordinates(e, r.Right, r.Top, true);
+                DrawVertexCoordinates(e, r.Right, r.Bottom, true);
+                DrawTrackingTooltip(e, "Click to finish. Press ESC to cancel");
+            }
+        }
+
+        private void DrawDragRectangle(PaintEventArgs e)
+        {
+            var rect = GetRectangle(dragStart, new Point(_mouseX, _mouseY));
+            if (rect.HasValue)
+            {
+                var r = rect.Value;
+                Trace.TraceInformation("Draw rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+                e.Graphics.DrawRectangle(CreateOutlinePen(), r);
+                Trace.TraceInformation("Fill rangle ({0} {1}, {2} {3})", r.Left, r.Top, r.Right, r.Bottom);
+                e.Graphics.FillRectangle(CreateFillBrush(), r);
+            }
+        }
+
+        private bool _featTooltipsEnabled;
+
+        /// <summary>
+        /// Gets or sets whether feature tooltips are enabled. If set to true, tooltip queries are
+        /// executed at the current mouse position if the active tool is Pan or Select
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public bool FeatureTooltipsEnabled
+        {
+            get { return _featTooltipsEnabled; }
+            set
+            {
+                if (value.Equals(_featTooltipsEnabled))
+                    return;
+
+                _featTooltipsEnabled = value;
+                if (!value)
+                {
+                    _activeTooltipText = null;
+                    Invalidate();
+                }
+
+                OnPropertyChanged("FeatureTooltipsEnabled");
+            }
+        }
+
+        /// <summary>
+        /// Internally determines whether a tooltip query can be executed. Must be true along
+        /// with <see cref="FeatureTooltipsEnabled"/> in order for a tooltip query to be executed
+        /// </summary>
+        internal bool TooltipsEnabled
+        {
+            get;
+            set;
+        }
+
+        #region Digitization
+
+        /*
+         * Digitization behaviour with respect to mouse and paint events
+         * 
+         * Point:
+         *  MouseClick -> Invoke Callback
+         * 
+         * Rectangle:
+         *  MouseClick -> set start, temp end
+         *  MouseMove -> update temp end
+         *  OnPaint -> Draw rectangle from start/temp end
+         *  MouseClick -> set end -> Invoke Callback
+         * 
+         * Line:
+         *  MouseClick -> set start, temp end
+         *  MouseMove -> update temp end
+         *  OnPaint -> Draw line from start/temp end
+         *  MouseClick -> set end -> Invoke Callback
+         * 
+         * LineString:
+         *  MouseClick -> append point to path
+         *  MouseMove -> update temp end
+         *  OnPaint -> Draw line with points in path + temp end
+         *  MouseDoubleClick -> append point to path -> Invoke Callback
+         * 
+         * Polygon:
+         *  MouseClick -> append point to path
+         *  MouseMove -> update temp end
+         *  OnPaint -> Draw polygon fill with points in path + temp end
+         *  MouseDoubleClick -> append point to path -> Invoke Callback
+         * 
+         * Circle:
+         *  MouseClick -> set start, temp end
+         *  MouseMove -> update temp end
+         *  OnPaint -> Draw circle from start with radius = (dist from start to temp end)
+         *  MouseClick -> set end -> Invoke Callback
+         */
+
+        private Point dPtStart; //Rectangle, Line, Circle
+        private Point dPtEnd; //Rectangle, Line, Circle
+        private List<Point> dPath = new List<Point>(); //LineString, Polygon
+
+        private Delegate _digitzationCallback;
+
+        private bool _digitizationYetToStart = true;
+
+        /// <summary>
+        /// Starts the digitization process for a circle
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        public void DigitizeCircle(CircleDigitizationCallback callback)
+        {
+            this.DigitizingType = MapDigitizationType.Circle;
+            _digitzationCallback = callback;
+            _digitizationYetToStart = true;
+        }
+
+        /// <summary>
+        /// Starts the digitization process for a line
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        public void DigitizeLine(LineDigitizationCallback callback)
+        {
+            this.DigitizingType = MapDigitizationType.Line;
+            _digitzationCallback = callback;
+            _digitizationYetToStart = true;
+        }
+
+        /// <summary>
+        /// Starts the digitization process for a point
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        public void DigitizePoint(PointDigitizationCallback callback)
+        {
+            this.DigitizingType = MapDigitizationType.Point;
+            _digitzationCallback = callback;
+            _digitizationYetToStart = true;
+        }
+
+        /// <summary>
+        /// Starts the digitization process for a polygon
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        public void DigitizePolygon(PolygonDigitizationCallback callback)
+        {
+            this.DigitizingType = MapDigitizationType.Polygon;
+            _digitzationCallback = callback;
+            _digitizationYetToStart = true;
+        }
+
+        /// <summary>
+        /// Starts the digitization process for a line string (polyline)
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        public void DigitizeLineString(LineStringDigitizationCallback callback)
+        {
+            this.DigitizingType = MapDigitizationType.LineString;
+            _digitzationCallback = callback;
+            _digitizationYetToStart = true;
+        }
+
+        private LineDigitizationCallback _segmentCallback;
+
+        /// <summary>
+        /// Starts the digitization process for a line string (polyline)
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        /// <param name="segmentCallback">The callback to be invoked when a new segment of the current line string is digitized</param>
+        public void DigitizeLineString(LineStringDigitizationCallback callback, LineDigitizationCallback segmentCallback)
+        {
+            this.DigitizingType = MapDigitizationType.LineString;
+            _digitzationCallback = callback;
+            _segmentCallback = segmentCallback;
+            _digitizationYetToStart = true;
+        }
+
+        /// <summary>
+        /// Starts the digitization process for a rectangle
+        /// </summary>
+        /// <param name="callback">The callback to be invoked when the digitization process completes</param>
+        public void DigitizeRectangle(RectangleDigitizationCallback callback)
+        {
+            this.DigitizingType = MapDigitizationType.Rectangle;
+            _digitzationCallback = callback;
+            _digitizationYetToStart = true;
+        }
+
+        private void ResetDigitzationState()
+        {
+            _digitzationCallback = null;
+            _segmentCallback = null;
+            dPath.Clear();
+            dPtEnd.X = dPtStart.Y = 0;
+            dPtStart.X = dPtStart.Y = 0;
+            this.DigitizingType = MapDigitizationType.None;
+            Invalidate();
+        }
+
+        private void OnCircleDigitized(Point ptStart, Point ptEnd)
+        {
+            var mapPt = ScreenToMapUnits(ptStart.X, ptStart.Y);
+            var mapEnd = ScreenToMapUnits(ptEnd.X, ptEnd.Y);
+
+            var radius = Math.Sqrt(Math.Pow(mapEnd.X - mapPt.X, 2) + Math.Pow(mapEnd.Y - mapPt.Y, 2));
+
+            var cb = (CircleDigitizationCallback)_digitzationCallback;
+            ResetDigitzationState();
+            cb(mapPt.X, mapPt.Y, radius);
+        }
+
+        private void OnPolygonDigitized(List<Point> path)
+        {
+            double[,] coords = new double[path.Count, 2];
+            for (int i = 0; i < path.Count; i++)
+            {
+                var pt = ScreenToMapUnits(path[i].X, path[i].Y);
+                coords[i, 0] = pt.X;
+                coords[i, 1] = pt.Y;
+            }
+
+            var cb = (PolygonDigitizationCallback)_digitzationCallback;
+            ResetDigitzationState();
+            cb(coords);
+        }
+
+        private void OnLineStringSegmentDigitized(Point p1, Point p2)
+        {
+            if (_segmentCallback != null)
+            {
+                var ptx1 = ScreenToMapUnits(p1.X, p1.Y);
+                var ptx2 = ScreenToMapUnits(p2.X, p2.Y);
+                _segmentCallback.Invoke(ptx1.X, ptx1.Y, ptx2.X, ptx2.Y);
+            }
+        }
+
+        private void OnLineStringDigitized(List<Point> path)
+        {
+            double[,] coords = new double[path.Count, 2];
+            for (int i = 0; i < path.Count; i++)
+            {
+                var pt = ScreenToMapUnits(path[i].X, path[i].Y);
+                coords[i, 0] = pt.X;
+                coords[i, 1] = pt.Y;
+            }
+
+            var cb = (LineStringDigitizationCallback)_digitzationCallback;
+            ResetDigitzationState();
+            cb(coords);
+        }
+
+        private void OnLineDigitized(Point start, Point end)
+        {
+            var mapStart = ScreenToMapUnits(start.X, start.Y);
+            var mapEnd = ScreenToMapUnits(end.X, end.Y);
+
+            var cb = (LineDigitizationCallback)_digitzationCallback;
+            ResetDigitzationState();
+            cb(mapStart.X, mapStart.Y, mapEnd.X, mapEnd.Y);
+        }
+
+        private void OnRectangleDigitized(Rectangle rect)
+        {
+            var mapLL = ScreenToMapUnits(rect.Left, rect.Bottom);
+            var mapUR = ScreenToMapUnits(rect.Right, rect.Top);
+
+            var cb = (RectangleDigitizationCallback)_digitzationCallback;
+            ResetDigitzationState();
+            cb(mapLL.X, mapLL.Y, mapUR.X, mapUR.Y);
+        }
+
+        private void OnPointDigitizationCompleted(Point p)
+        {
+            var mapPt = ScreenToMapUnits(p.X, p.Y);
+            var cb = (PointDigitizationCallback)_digitzationCallback;
+            ResetDigitzationState();
+            cb(mapPt.X, mapPt.Y);
+        }
+
+        #endregion
+
+        static ViewerRenderingOptions CreateMapRenderingOptions(short red, short green, short blue)
+        {
+            return new ViewerRenderingOptions("PNG", 2, Color.FromArgb(red, green, blue));
+        }
+
+        static ViewerRenderingOptions CreateSelectionRenderingOptions(short red, short green, short blue)
+        {
+            return new ViewerRenderingOptions("PNG", (1 | 4), Color.FromArgb(red, green, blue));
+        }
+
+        public void LoadMap(RuntimeMap map)
+        {
+            _map = map;
+            _map.StrictSelection = false;
+            InitViewerFromMap();
+        }
+
+        private void InitViewerFromMap()
+        {
+            this.BackColor = _map.BackgroundColor;
+            _map.DisplayWidth = this.Width;
+            _map.DisplayHeight = this.Height;
+            _selection = _map.Selection;
+            _overlayRenderOpts = CreateMapRenderingOptions(0, 0, 255);
+            _selectionRenderOpts = CreateSelectionRenderingOptions(0, 0, 255);
+
+            var env = _map.MapExtent;
+
+            _extX1 = _orgX1 = env.MinX;
+            _extY2 = _orgY2 = env.MinY;
+            _extX2 = _orgX2 = env.MaxX;
+            _extY1 = _orgY1 = env.MaxY;
+
+            if ((_orgX1 - _orgX2) == 0 || (_orgY1 - _orgY2) == 0)
+            {
+                _extX1 = _orgX1 = -.1;
+                _extY2 = _orgX2 = .1;
+                _extX2 = _orgY1 = -.1;
+                _extY1 = _orgY2 = .1;
+            }
+
+            if (this.ConvertTiledGroupsToNonTiled)
+            {
+                var groups = _map.Groups;
+                for (int i = 0; i < groups.Count; i++)
+                {
+                    var group = groups[i];
+                    //_provider.MakeGroupNormal(group);
+                    group.Type = RuntimeMapGroup.kNormal;
+                }
+            }
+
+#if VIEWER_DEBUG
+            CreateDebugFeatureSource();
+#endif
+            this.Focus();
+
+            //Reset history stack
+            _viewHistory.Clear();
+            OnPropertyChanged("ViewHistory");
+            _viewHistoryIndex = -1;
+            OnPropertyChanged("ViewHistoryIndex");
+
+            var handler = this.MapLoaded;
+            if (handler != null)
+                handler(this, EventArgs.Empty);
+
+            InitialMapView();
+        }
+
+        internal double MetersPerUnit
+        {
+            get
+            {
+                return _map.MetersPerUnit;
+            }
+        }
+
+        private double CalculateScale(double mcsW, double mcsH, int devW, int devH)
+        {
+            var mpu = this.MetersPerUnit;
+            var mpp = 0.0254 / _map.DisplayDpi;
+            if (devH * mcsW > devW * mcsH)
+                return mcsW * mpu / (devW * mpp); //width-limited
+            else
+                return mcsH * mpu / (devH * mpp); //height-limited
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether tiled groups are converted to normal groups. Must be set before
+        /// a map is loaded via the <see cref="Init"/> method
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("If true, the map being viewed will have all its tiled groups converted to non-tiled groups. Tiled groups are not supported by this viewer and are not rendered")]
+        [DefaultValue(false)]
+        public bool ConvertTiledGroupsToNonTiled
+        {
+            get;
+            set;
+        }
+
+        /// <summary>
+        /// Raised when the viewer has been initialized
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("Raised when the viewer has been initialized with a runtime map")]
+        public event EventHandler MapLoaded;
+
+        private System.Timers.Timer _delayedResizeTimer;
+
+        void OnDelayResizeTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
+        {
+            var action = new MethodInvoker(() =>
+            {
+                if (_map != null)
+                {
+                    Trace.TraceInformation("Performing delayed resize to (" + this.Width + ", " + this.Height + ")");
+                    _map.DisplayWidth = this.Width;
+                    _map.DisplayHeight = this.Height;
+                    UpdateExtents();
+                    RefreshMap(false);
+                }
+                _delayedResizeTimer.Stop();
+                Trace.TraceInformation("Delayed resize timer stopped");
+            });
+            if (this.InvokeRequired)
+                this.Invoke(action);
+            else
+                action();
+        }
+
+        void OnControlResized(object sender, EventArgs e)
+        {
+            if (_delayedResizeTimer == null)
+            {
+                _delayedResizeTimer = new System.Timers.Timer();
+                _delayedResizeTimer.Elapsed += OnDelayResizeTimerElapsed;
+                Trace.TraceInformation("Delay resize timer initialized");
+            }
+            if (_delayedResizeTimer.Enabled)
+            {
+                Trace.TraceInformation("Stopped delayed resize");
+                _delayedResizeTimer.Stop();
+            }
+
+            _delayedResizeTimer.Interval = 500;
+            _delayedResizeTimer.Start();
+            Trace.TraceInformation("Delayed resize re-scheduled");
+        }
+
+        /// <summary>
+        /// Clears the current selection
+        /// </summary>
+        public void ClearSelection()
+        {
+            //_provider.ClearSelection(_selection);
+            _selection.LoadXml("");
+            _map.Save();
+
+            if (_selectionImage != null)
+            {
+                _selectionImage.Dispose();
+                _selectionImage = null;
+            }
+
+            var handler = this.SelectionChanged;
+            if (handler != null)
+                handler(this, EventArgs.Empty);
+
+            this.Refresh();
+        }
+
+        /// <summary>
+        /// Gets the current runtime map
+        /// </summary>
+        /// <returns></returns>
+        public RuntimeMap GetMap()
+        {
+            return _map;
+        }
+
+        private bool HasSelection()
+        {
+            return _selection.Count > 0;
+        }
+
+        private static int GetSelectionTotal(MapSelection sel)
+        {
+            int total = 0;
+            for (int i = 0; i < sel.Count; i++)
+            {
+                total += sel[i].Count;
+            }
+            return total;
+        }
+
+        private MapDigitizationType _digitizingType = MapDigitizationType.None;
+
+        /// <summary>
+        /// Gets the type of object being currently digitized. If the digitization type is None, then
+        /// the viewer is not currently digitizing
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public MapDigitizationType DigitizingType
+        {
+            get { return _digitizingType; }
+            private set
+            {
+                if (_digitizingType.Equals(value))
+                    return;
+
+                if (value != MapDigitizationType.None)
+                {
+                    this.ActiveTool = MapActiveTool.None;
+                    this.Cursor = Cursors.Cross;
+                }
+                else
+                {
+                    this.Cursor = Cursors.Default;
+                }
+
+                _digitizingType = value;
+
+                OnPropertyChanged("DigitizingType");
+            }
+        }
+
+        class RenderWorkArgs
+        {
+            public ViewerRenderingOptions SelectionRenderingOptions { get; set; }
+
+            public ViewerRenderingOptions MapRenderingOptions { get; set; }
+
+            public bool RaiseEvents { get; set; }
+
+            public bool InvalidateRegardless { get; set; }
+        }
+
+        class RenderResult
+        {
+            public Image Image { get; set; }
+
+            public Image SelectionImage { get; set; }
+
+            public bool RaiseEvents { get; set; }
+
+            public bool InvalidateRegardless { get; set; }
+        }
+
+        /// <summary>
+        /// Refreshes the current map view
+        /// </summary>
+        public void RefreshMap()
+        {
+            RefreshMap(true);
+        }
+
+        /// <summary>
+        /// Updates the rendered selection. Call this method if you have manipulated the selection
+        /// set outside of the viewer. This does not raise the <see cref="SelectionChanged"/> event
+        /// </summary>
+        public void UpdateSelection()
+        {
+            UpdateSelection(false);
+        }
+
+        /// <summary>
+        /// Updates the rendered selection. Call this method if you have manipulated the selection
+        /// set outside of the viewer
+        /// </summary>
+        /// <param name="raise">Indicates if the <see cref="SelectionChanged"/> event should be raised as well</param>
+        public void UpdateSelection(bool raise)
+        {
+            RenderSelection();
+            if (raise)
+            {
+                var handler = this.SelectionChanged;
+                if (handler != null)
+                    handler(this, EventArgs.Empty);
+            }
+        }
+
+        internal void RenderSelection()
+        {
+            RenderSelection(false);
+        }
+
+        internal void RenderSelection(bool invalidateRegardless)
+        {
+            //This is our refresh action
+            RefreshAction action = new RefreshAction(() => 
+            {
+                if (HasSelection())
+                {
+                    this.IsBusy = true;
+                    UpdateSelectionRenderingOptions();
+                    renderWorker.RunWorkerAsync(new RenderWorkArgs()
+                    {
+                        SelectionRenderingOptions = _selectionRenderOpts,
+                        RaiseEvents = false,
+                        InvalidateRegardless = invalidateRegardless
+                    });
+                }
+                else
+                {
+                    if (invalidateRegardless)
+                        this.Invalidate();
+                }
+            });
+
+            //If an existing rendering operation is in progress queue it if 
+            //there isn't one queued. Because there is no point in doing the
+            //same thing more than once
+            if (this.IsBusy)
+            {
+                if (_queuedRefresh == null) //No refresh operations currently queued
+                    _queuedRefresh = action;
+            }
+            else //Otherwise execute it immediately
+            {
+                action();
+            }
+        }
+
+        delegate void RefreshAction();
+
+        RefreshAction _queuedRefresh = null;
+
+        internal void RefreshMap(bool raiseEvents)
+        {
+            //This is our refresh action
+            RefreshAction action = new RefreshAction(() => 
+            {
+                var args = new RenderWorkArgs()
+                {
+                    MapRenderingOptions = _overlayRenderOpts,
+                    RaiseEvents = raiseEvents
+                };
+                if (HasSelection())
+                {
+                    UpdateSelectionRenderingOptions();
+                    args.SelectionRenderingOptions = _selectionRenderOpts;
+                }
+                this.IsBusy = true;
+                renderWorker.RunWorkerAsync(args);
+            });
+
+            //If an existing rendering operation is in progress queue it if 
+            //there isn't one queued. Because there is no point in doing the
+            //same thing more than once
+            if (this.IsBusy)
+            {
+                if (_queuedRefresh == null) //No refresh operations currently queued
+                    _queuedRefresh = action;
+            }
+            else //Otherwise execute it immediately
+            {
+                action();   
+            }
+        }
+
+        /// <summary>
+        /// Raised when the map has been refreshed
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("Raised after the viewer has refreshed")]
+        public event EventHandler MapRefreshed;
+
+        private bool _busy = false;
+
+#if TRACE
+        private Stopwatch _renderSw = new Stopwatch();
+#endif
+
+        /// <summary>
+        /// Indicates whether a rendering operation is in progress
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public bool IsBusy
+        {
+            get { return _busy; }
+            private set
+            {
+                if (_busy.Equals(value))
+                    return;
+
+                _busy = value;
+#if TRACE
+                Trace.TraceInformation("IsBusy = " + _busy);
+                if (value)
+                {
+                    _renderSw.Reset();
+                    _renderSw.Start();
+                }
+                else
+                {
+                    _renderSw.Stop();
+                    Trace.TraceInformation("Rendering operation took {0}ms", _renderSw.ElapsedMilliseconds);
+                }
+#endif
+                OnPropertyChanged("IsBusy");
+            }
+        }
+
+        /// <summary>
+        /// Pans the view left by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        public void PanLeft(bool refresh)
+        {
+            PanTo(_extX1 + (_extX2 - _extX1) / 3, _extY2 + (_extY1 - _extY2) / 2, refresh);
+        }
+
+        /// <summary>
+        /// Pans the view up by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        public void PanUp(bool refresh)
+        {
+            PanTo(_extX1 + (_extX2 - _extX1) / 2, _extY1 - (_extY1 - _extY2) / 3, refresh);
+        }
+
+        /// <summary>
+        /// Pans the view right by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        public void PanRight(bool refresh)
+        {
+            PanTo(_extX2 - (_extX2 - _extX1) / 3, _extY2 + (_extY1 - _extY2) / 2, refresh);
+        }
+
+        /// <summary>
+        /// Pans the view down by a pre-defined distance
+        /// </summary>
+        /// <param name="refresh"></param>
+        public void PanDown(bool refresh)
+        {
+            PanTo(_extX1 + (_extX2 - _extX1) / 2, _extY2 + (_extY1 - _extY2) / 3, refresh);
+        }
+
+        /// <summary>
+        /// Zooms the extents.
+        /// </summary>
+        public void ZoomExtents()
+        {
+            var scale = CalculateScale((_orgX2 - _orgX1), (_orgY1 - _orgY2), this.Width, this.Height);
+            ZoomToView(_orgX1 + ((_orgX2 - _orgX1) / 2), _orgY2 + ((_orgY1 - _orgY2) / 2), scale, true);
+        }
+
+        /// <summary>
+        /// Zooms to the view defined by the specified extent
+        /// </summary>
+        /// <param name="llx"></param>
+        /// <param name="lly"></param>
+        /// <param name="urx"></param>
+        /// <param name="ury"></param>
+        public void ZoomToExtents(double llx, double lly, double urx, double ury)
+        {
+            var scale = CalculateScale((urx - llx), (ury - lly), this.Width, this.Height);
+            ZoomToView(llx + ((urx - llx) / 2), ury + ((lly - ury) / 2), scale, true);
+        }
+
+        /// <summary>
+        /// Zooms to scale.
+        /// </summary>
+        /// <param name="scale">The scale.</param>
+        public void ZoomToScale(double scale)
+        {
+            ZoomToView(_extX1 + (_extX2 - _extX1) / 2, _extY2 + (_extY1 - _extY2) / 2, scale, true);
+        }
+
+        /// <summary>
+        /// Zooms to the specified map view
+        /// </summary>
+        /// <param name="x"></param>
+        /// <param name="y"></param>
+        /// <param name="scale"></param>
+        /// <param name="refresh"></param>
+        public void ZoomToView(double x, double y, double scale, bool refresh)
+        {
+            ZoomToView(x, y, scale, refresh, true);
+        }
+
+        internal void PanTo(double x, double y, bool refresh)
+        {
+            ZoomToView(x, y, _map.ViewScale, refresh);
+        }
+
+        private void UpdateExtents()
+        {
+            //Update current extents
+            double mpu = this.MetersPerUnit;
+            double scale = _map.ViewScale;
+            double mpp = 0.0254 / _map.DisplayDpi;
+            var coord = _map.ViewCenter;
+
+            var mcsWidth = _map.DisplayWidth * mpp * scale / mpu;
+            var mcsHeight = _map.DisplayHeight * mpp * scale / mpu;
+
+            _extX1 = coord.X - mcsWidth / 2;
+            _extY1 = coord.Y + mcsHeight / 2;
+            _extX2 = coord.X + mcsWidth / 2;
+            _extY2 = coord.Y - mcsHeight / 2;
+        }
+
+        private bool PruneHistoryEntriesFromCurrentView()
+        {
+            if (_viewHistoryIndex < _viewHistory.Count - 1)
+            {
+                int removed = 0;
+                for (int i = _viewHistory.Count - 1; i > _viewHistoryIndex; i--)
+                {
+                    _viewHistory.RemoveAt(i);
+                    removed++;
+                }
+                return removed > 0;
+            }
+            return false;
+        }
+
+        internal void ZoomToView(double x, double y, double scale, bool refresh, bool raiseEvents)
+        {
+            ZoomToView(x, y, scale, refresh, raiseEvents, true);
+        }
+
+        /// <summary>
+        /// Navigates to the previous view in the history stack
+        /// </summary>
+        public void PreviousView()
+        {
+            var newIndex = _viewHistoryIndex - 1;
+            if (newIndex < 0)
+                return;
+
+            var view = _viewHistory[newIndex];
+            ZoomToView(view.X, view.Y, view.Scale, true, true, false);
+            _viewHistoryIndex = newIndex;
+            OnPropertyChanged("ViewHistoryIndex");
+        }
+
+        /// <summary>
+        /// Navigates to the next view in the history stack
+        /// </summary>
+        public void NextView()
+        {
+            //Cannot advance from current view
+            if (_viewHistoryIndex == _viewHistory.Count - 1)
+                return;
+
+            var newIndex = _viewHistoryIndex + 1;
+            if (newIndex > _viewHistory.Count - 1)
+                return;
+
+            var view = _viewHistory[newIndex];
+            ZoomToView(view.X, view.Y, view.Scale, true, true, false);
+            _viewHistoryIndex = newIndex;
+            OnPropertyChanged("ViewHistoryIndex");
+        }
+
+        /// <summary>
+        /// Gets the current index in the view history stack
+        /// </summary>
+        public int ViewHistoryIndex
+        {
+            get { return _viewHistoryIndex; }
+        }
+
+        /// <summary>
+        /// Gets the view history stack. The first item being the earliest and the last item being the most recent.
+        /// </summary>
+        public ReadOnlyCollection<MapViewHistoryEntry> ViewHistory
+        {
+            get { return _viewHistory.AsReadOnly(); }
+        }
+
+        internal void ZoomToView(double x, double y, double scale, bool refresh, bool raiseEvents, bool addToHistoryStack)
+        {
+            if (addToHistoryStack)
+            {
+                //If not current view, then any entries from the current view index are no longer needed
+                if (ViewHistoryIndex < _viewHistory.Count - 1)
+                    PruneHistoryEntriesFromCurrentView();
+
+                _viewHistory.Add(new MapViewHistoryEntry(x, y, scale));
+                OnPropertyChanged("ViewHistory");
+                _viewHistoryIndex = _viewHistory.Count - 1;
+                OnPropertyChanged("ViewHistoryIndex");
+            }
+
+            _map.ViewCenter.X = x;
+            _map.ViewCenter.Y = y;
+#if VIEWER_DEBUG
+            UpdateCenterDebugPoint();
+            //var mapExt = _map.MapExtent;
+            //var dataExt = _map.DataExtent;
+            Trace.TraceInformation("Map Extent is ({0},{1} {2},{3})", mapExt.LowerLeftCoordinate.X, mapExt.LowerLeftCoordinate.Y, mapExt.UpperRightCoordinate.X, mapExt.UpperRightCoordinate.Y);
+            Trace.TraceInformation("Data Extent is ({0},{1} {2},{3})", dataExt.LowerLeftCoordinate.X, dataExt.LowerLeftCoordinate.Y, dataExt.UpperRightCoordinate.X, dataExt.UpperRightCoordinate.Y);
+
+            Trace.TraceInformation("Center is (" + x + ", " + y + ")");
+#endif
+            var oldScale = _map.ViewScale;
+            _map.ViewScale = Math.Max(scale, MINIMUM_ZOOM_SCALE);
+
+            if (oldScale != _map.ViewScale)
+            {
+                var handler = this.MapScaleChanged;
+                if (handler != null)
+                    handler(this, EventArgs.Empty);
+            }
+
+            UpdateExtents();
+
+#if VIEWER_DEBUG
+            Trace.TraceInformation("Current extents is ({0},{1} {2},{3})", _extX1, _extY1, _extX2, _extY2);
+#endif
+
+            //Then refresh
+            if (refresh)
+                RefreshMap(raiseEvents);
+        }
+
+        /// <summary>
+        /// Raised when the scale of the current runtime map has changed
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("Raised when the zoom scale of the map has changed")]
+        public event EventHandler MapScaleChanged;
+
+        /// <summary>
+        /// Raised when the selection has changed. Note that programmatic selection modifications
+        /// will not raise this event.
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("Raised when active viewer selection has changed")]
+        public event EventHandler SelectionChanged;
+
+        private void renderWorker_DoWork(object sender, DoWorkEventArgs e)
+        {
+            _map.Save(); //We must sync up runtime map state before rendering
+
+            var args = (RenderWorkArgs)e.Argument;
+            var res = new RenderResult() { RaiseEvents = args.RaiseEvents, InvalidateRegardless = args.InvalidateRegardless };
+            if (args.MapRenderingOptions != null)
+            {
+                res.Image = Image.FromStream(_map.RenderDynamicOverlay(null, args.MapRenderingOptions.Format, args.MapRenderingOptions.Color, args.MapRenderingOptions.Behavior));
+            }
+            if (args.SelectionRenderingOptions != null)
+            {
+                res.SelectionImage = Image.FromStream(_map.RenderDynamicOverlay(null, args.SelectionRenderingOptions.Format, args.SelectionRenderingOptions.Color, args.SelectionRenderingOptions.Behavior));
+            }
+
+            e.Result = res;
+        }
+
+        private void renderWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+        {
+            this.IsBusy = AreWorkersBusy();
+            if (e.Error != null)
+            {
+                MessageBox.Show(e.Error.Message, "Error");
+            }
+            else
+            {
+                var res = (RenderResult)e.Result;
+                //reset translation
+                translate = new System.Drawing.Point();
+
+                bool bInvalidate = false;
+                //set the image
+                if (res.Image != null)
+                {
+                    if (this.Image != null)
+                    {
+                        this.Image.Dispose();
+                        this.Image = null;
+                    }
+                    Trace.TraceInformation("Set map image");
+                    this.Image = res.Image;
+                    bInvalidate = true;
+                }
+                if (res.SelectionImage != null)
+                {
+                    if (_selectionImage != null)
+                    {
+                        _selectionImage.Dispose();
+                        _selectionImage = null;
+                    }
+                    Trace.TraceInformation("Set selection image");
+                    _selectionImage = res.SelectionImage;
+                    bInvalidate = true;
+                }
+
+                //If there is a queued refresh action, execute it now
+                if (_queuedRefresh != null)
+                {
+                    Trace.TraceInformation("Executing queued rendering operation");
+                    _queuedRefresh();
+                    _queuedRefresh = null;
+                }
+                else 
+                {
+                    if (bInvalidate || res.InvalidateRegardless)
+                        Invalidate(true);
+
+                    /*
+                    var center = _map.ViewCenter;
+                    var ext = _map.DataExtent;
+                    System.Diagnostics.Trace.TraceInformation(
+                        "**POST-RENDER**{2}Map Center: {0}, {1}{2}Lower left: {3}, {4}{2}Upper Right: {5}, {6}",
+                        center.Coordinate.X,
+                        center.Coordinate.Y,
+                        Environment.NewLine,
+                        ext.LowerLeftCoordinate.X,
+                        ext.LowerLeftCoordinate.Y,
+                        ext.UpperRightCoordinate.X,
+                        ext.UpperRightCoordinate.Y);
+                    */
+                    if (res.RaiseEvents)
+                    {
+                        var handler = this.MapRefreshed;
+                        if (handler != null)
+                            handler(this, EventArgs.Empty);
+                    }
+                }
+            }
+        }
+
+        private bool AreWorkersBusy()
+        {
+            return renderWorker.IsBusy;
+        }
+
+        /// <summary>
+        /// Zooms to the initial map view
+        /// </summary>
+        public void InitialMapView()
+        {
+            InitialMapView(true);
+        }
+
+        private void InitialMapView(bool refreshMap)
+        {
+            var scale = CalculateScale((_orgX2 - _orgX1), (_orgY1 - _orgY2), this.Width, this.Height);
+            ZoomToView(_orgX1 + ((_orgX2 - _orgX1) / 2), _orgY2 + ((_orgY1 - _orgY2) / 2), scale, refreshMap);
+        }
+
+        private static Rectangle? GetRectangle(Point dPtStart, Point dPtEnd)
+        {
+            int? left = null;
+            int? right = null;
+            int? top = null;
+            int? bottom = null;
+
+            if (dPtEnd.X < dPtStart.X)
+            {
+                if (dPtEnd.Y < dPtStart.Y)
+                {
+                    left = dPtEnd.X;
+                    bottom = dPtStart.Y;
+                    top = dPtEnd.Y;
+                    right = dPtStart.X;
+                }
+                else if (dPtEnd.Y > dPtStart.Y)
+                {
+                    left = dPtEnd.X;
+                    bottom = dPtEnd.Y;
+                    top = dPtStart.Y;
+                    right = dPtStart.X;
+                }
+                else
+                {
+                    //Equal
+                }
+            }
+            else
+            {
+                if (dPtEnd.X > dPtStart.X)
+                {
+                    if (dPtEnd.Y < dPtStart.Y)
+                    {
+                        left = dPtStart.X;
+                        bottom = dPtStart.Y;
+                        top = dPtEnd.Y;
+                        right = dPtEnd.X;
+                    }
+                    else if (dPtEnd.Y > dPtStart.Y)
+                    {
+                        left = dPtStart.X;
+                        bottom = dPtEnd.Y;
+                        top = dPtStart.Y;
+                        right = dPtEnd.X;
+                    }
+                    else
+                    {
+                        //Equal
+                    }
+                }
+                //else equal
+            }
+            if (left.HasValue && right.HasValue && top.HasValue && bottom.HasValue)
+            {
+                return new Rectangle(left.Value, top.Value, (right.Value - left.Value), (bottom.Value - top.Value));
+            }
+            return null;
+        }
+
+        private double _zoomInFactor;
+        private double _zoomOutFactor;
+
+        /// <summary>
+        /// Gets or sets the factor by which to multiply the scale to zoom in
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The zoom in factor")]
+        public double ZoomInFactor
+        {
+            get { return _zoomInFactor; }
+            set
+            {
+                if (value.Equals(_zoomInFactor))
+                    return;
+                _zoomInFactor = value;
+                OnPropertyChanged("ZoomInFactor");
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the factor by which to multiply the scale to zoom out
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("The zoom out factor")]
+        public double ZoomOutFactor
+        {
+            get { return _zoomOutFactor; }
+            set
+            {
+                if (value.Equals(_zoomOutFactor))
+                    return;
+                _zoomOutFactor = value;
+                OnPropertyChanged("ZoomOutFactor");
+            }
+        }
+
+        private static string MakeWktPolygon(double x1, double y1, double x2, double y2)
+        {
+            return "POLYGON((" + x1 + " " + y1 + ", " + x2 + " " + y1 + ", " + x2 + " " + y2 + ", " + x1 + " " + y2 + ", " + x1 + " " + y1 + "))";
+        }
+
+        
+
+        private int? _lastTooltipX;
+        private int? _lastTooltipY;
+
+        private string QueryFirstVisibleTooltip(int x, int y)
+        {
+            //No intialized map
+            if (_map == null)
+                return "";
+
+            //No change in position
+            if (_lastTooltipX == x && _lastTooltipY == y && !string.IsNullOrEmpty(_activeTooltipText))
+                return _activeTooltipText;
+
+            if (_lastTooltipX.HasValue && _lastTooltipY.HasValue)
+            {
+                //Not considered a significant change
+                if (Math.Abs(x - _lastTooltipX.Value) < MOUSE_TOOLTIP_MOVE_TOLERANCE ||
+                    Math.Abs(y - _lastTooltipY.Value) < MOUSE_TOOLTIP_MOVE_TOLERANCE)
+                    return _activeTooltipText;
+            }
+
+            _lastTooltipX = x;
+            _lastTooltipY = y;
+
+            var pt1 = ScreenToMapUnits(x - this.PointPixelBuffer, x - this.PointPixelBuffer);
+            var pt2 = ScreenToMapUnits(x + this.PointPixelBuffer, y + this.PointPixelBuffer);
+            //Unlike mg-desktop, this is actually easy API-wise
+            var res = _map.QueryMapFeatures(
+                MakeWktPolygon(pt1.X, pt1.Y, pt2.X, pt2.Y),
+                1,
+                false,
+                "INTERSECTS",
+                new QueryMapOptions()
+                {
+                    LayerNames = GetAllLayerNames(_map),
+                    LayerAttributeFilter = QueryMapFeaturesLayerAttributes.VisibleWithToolTips
+                });
+            try
+            {
+                var doc = new XmlDocument();
+                doc.LoadXml(res);
+                return doc.DocumentElement["Tooltip"].InnerText;
+            }
+            catch
+            {
+                return string.Empty;
+            }
+        }
+
+        private static string[] GetAllLayerNames(RuntimeMap map)
+        {
+            var names = new List<string>();
+            for (int i = 0; i < map.Layers.Count; i++)
+            {
+                names.Add(map.Layers[i].Name);
+            }
+            return names.ToArray();
+        }
+
+        private static bool IsRasterClass(ClassDefinition cls)
+        {
+            foreach (var prop in cls.Properties)
+            {
+                if (prop.Type == OSGeo.MapGuide.MaestroAPI.Schema.PropertyDefinitionType.Raster)
+                    return true;
+            }
+            return false;
+        }
+
+        private static bool IsRasterLayer(RuntimeMapLayer layer)
+        {
+            var cls = layer.GetClassDefinition();
+
+            return IsRasterClass(cls);
+        }
+
+        public System.Drawing.Image GetCurrentImage()
+        {
+            var bmp = new Bitmap(this.Width, this.Height);
+            this.DrawToBitmap(bmp, this.ClientRectangle);
+            return bmp;
+        }
+
+        /// <summary>
+        /// Copies the image of the current map to the clipboard
+        /// </summary>
+        public void CopyMap()
+        {
+            Clipboard.SetImage(this.GetCurrentImage());
+        }
+
+        /// <summary>
+        /// Selects features from all selectable layers that intersects the given geometry
+        /// </summary>
+        /// <param name="geom"></param>
+        public void SelectByWkt(string wkt)
+        {
+            //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
+            _map.QueryMapFeatures(wkt, -1, true, "INTERSECTS", null);
+#if TRACE
+            sw.Stop();
+            Trace.TraceInformation("Selection processing completed in {0}ms", sw.ElapsedMilliseconds);
+#endif
+
+            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);
+        }
+
+        protected override void OnResize(EventArgs e)
+        {
+            OnControlResized(this, e);
+            base.OnResize(e);
+        }
+
+        #region Mouse handlers
+
+        private void OnMapMouseDown(object sender, MouseEventArgs e)
+        {
+            HandleMouseDown(e);
+        }
+
+        private void OnMapMouseMove(object sender, MouseEventArgs e)
+        {
+            HandleMouseMove(e);
+        }
+        
+        private void OnMapMouseUp(object sender, MouseEventArgs e)
+        {
+            HandleMouseUp(e);
+        }
+
+        private void OnMapMouseClick(object sender, MouseEventArgs e)
+        {
+            this.Focus();
+            HandleMouseClick(e);
+        }
+
+        private void OnMapMouseDoubleClick(object sender, MouseEventArgs e)
+        {
+            this.Focus();
+            HandleMouseDoubleClick(e);
+        }
+
+        private void HandleMouseDoubleClick(MouseEventArgs e)
+        {
+            //Not enough points to constitute a line string or polygon
+            if (dPath.Count < 2)
+                return;
+
+            if (this.DigitizingType == MapDigitizationType.LineString)
+            {
+                //Fix the last one, can't edit last one because points are value types
+                dPath.RemoveAt(dPath.Count - 1);
+                dPath.Add(new Point(e.X, e.Y));
+                OnLineStringDigitized(dPath);
+            }
+            else if (this.DigitizingType == MapDigitizationType.Polygon)
+            {
+                //Fix the last one, can't edit last one because points are value types
+                dPath.RemoveAt(dPath.Count - 1);
+                dPath.Add(new Point(e.X, e.Y));
+                OnPolygonDigitized(dPath);
+            }
+        }
+
+        private void HandleMouseClick(MouseEventArgs e)
+        {
+            if (e.Button == MouseButtons.Right)
+                return;
+
+            if (this.DigitizingType != MapDigitizationType.None)
+            {
+                //Points are easy, one click and you're done
+                if (this.DigitizingType == MapDigitizationType.Point)
+                {
+                    OnPointDigitizationCompleted(new Point(e.X, e.Y));
+                }
+                else
+                {
+                    //Check first click in digitization
+                    if (_digitizationYetToStart)
+                    {
+                        if (this.DigitizingType == MapDigitizationType.LineString ||
+                            this.DigitizingType == MapDigitizationType.Polygon)
+                        {
+                            dPath.Add(new Point(e.X, e.Y));
+                            dPath.Add(new Point(e.X, e.Y)); //This is a transient one
+                        }
+                        else
+                        {
+                            dPtStart.X = e.X;
+                            dPtStart.Y = e.Y;
+                        }
+                        _digitizationYetToStart = false;
+                    }
+                    else
+                    {
+                        if (this.DigitizingType == MapDigitizationType.LineString ||
+                            this.DigitizingType == MapDigitizationType.Polygon)
+                        {
+                            var pt = dPath[dPath.Count - 1];
+                            pt.X = e.X;
+                            pt.Y = e.Y;
+                            dPath.Add(new Point(e.X, e.Y)); //This is a transient one
+                            OnLineStringSegmentDigitized(dPath[dPath.Count - 3], dPath[dPath.Count - 2]);
+                        }
+                        else
+                        {
+                            //Fortunately, these are all 2-click affairs meaning this is
+                            //the second click
+                            switch (this.DigitizingType)
+                            {
+                                case MapDigitizationType.Circle:
+                                    {
+                                        dPtEnd.X = e.X;
+                                        dPtEnd.Y = e.Y;
+                                        OnCircleDigitized(dPtStart, dPtEnd);
+                                    }
+                                    break;
+                                case MapDigitizationType.Line:
+                                    {
+                                        dPtEnd.X = e.X;
+                                        dPtEnd.Y = e.Y;
+                                        OnLineDigitized(dPtStart, dPtEnd);
+                                    }
+                                    break;
+                                case MapDigitizationType.Rectangle:
+                                    {
+                                        dPtEnd.X = e.X;
+                                        dPtEnd.Y = e.Y;
+                                        var rect = GetRectangle(dPtStart, dPtEnd);
+                                        if (rect.HasValue)
+                                            OnRectangleDigitized(rect.Value);
+                                    }
+                                    break;
+                            }
+                        }
+                    }
+                }
+            }
+            else
+            {
+                if (this.ActiveTool == MapActiveTool.Select)
+                {
+                    var mapPt1 = ScreenToMapUnits(e.X - this.PointPixelBuffer, e.Y - this.PointPixelBuffer);
+                    var mapPt2 = ScreenToMapUnits(e.X + this.PointPixelBuffer, e.Y + this.PointPixelBuffer);
+
+                    var env = ObjectFactory.CreateEnvelope(
+                        Math.Min(mapPt1.X, mapPt2.X),
+                        Math.Min(mapPt1.Y, mapPt2.Y),
+                        Math.Max(mapPt1.X, mapPt2.X),
+                        Math.Max(mapPt1.Y, mapPt2.Y));
+
+                    SelectByWkt(MakeWktPolygon(env.MinX, env.MinY, env.MaxX, env.MaxY));
+                }
+                else if (this.ActiveTool == MapActiveTool.ZoomIn)
+                {
+                    if (!isDragging)
+                    {
+                        var mapPt = ScreenToMapUnits(e.X, e.Y);
+                        var scale = _map.ViewScale;
+                        ZoomToView(mapPt.X, mapPt.Y, scale * ZoomInFactor, true);
+                    }
+                }
+                else if (this.ActiveTool == MapActiveTool.ZoomOut)
+                {
+                    if (!isDragging)
+                    {
+                        var mapPt = ScreenToMapUnits(e.X, e.Y);
+                        var scale = _map.ViewScale;
+                        ZoomToView(mapPt.X, mapPt.Y, scale * ZoomOutFactor, true);
+                    }
+                }
+            }
+        }
+
+        private void HandleMouseDown(MouseEventArgs e)
+        {
+            if (e.Button == MouseButtons.Left)
+            {
+                dragStart = e.Location;
+                Trace.TraceInformation("Drag started at (" + dragStart.X + ", " + dragStart.Y + ")");
+
+                switch (this.ActiveTool)
+                {
+                    case MapActiveTool.Pan:
+                        Trace.TraceInformation("START PANNING");
+                        break;
+                    case MapActiveTool.Select:
+                        Trace.TraceInformation("START SELECT");
+                        break;
+                    case MapActiveTool.ZoomIn:
+                        Trace.TraceInformation("START ZOOM");
+                        break;
+                }
+            }
+        }
+
+        private System.Drawing.Point translate;
+
+        private System.Drawing.Point dragStart;
+        bool isDragging = false;
+        
+        private int _mouseX;
+        private int _mouseY;
+        
+        private string _activeTooltipText;
+
+        private int _mouseDx;
+        private int _mouseDy;
+
+        /// <summary>
+        /// A mouse is considered to have moved if the differerence in either X or Y directions is greater
+        /// than this number
+        /// </summary>
+        const int MOUSE_TOOLTIP_MOVE_TOLERANCE = 10;
+
+        private void HandleMouseMove(MouseEventArgs e)
+        {
+            if (_mouseX == e.X &&
+                _mouseY == e.Y)
+            {
+                return;
+            }
+
+            //Record displacement
+            _mouseDx = e.X - _mouseX;
+            _mouseDy = e.Y - _mouseY;
+
+            _mouseX = e.X;
+            _mouseY = e.Y;
+
+            var mapPt = ScreenToMapUnits(e.X, e.Y);
+            OnMouseMapPositionChanged(mapPt.X, mapPt.Y);
+
+            if (this.ActiveTool == MapActiveTool.Pan || this.ActiveTool == MapActiveTool.Select || this.ActiveTool == MapActiveTool.ZoomIn)
+            {
+                if (e.Location != dragStart && !isDragging && e.Button == MouseButtons.Left)
+                {
+                    isDragging = true;
+                }
+
+                if (this.ActiveTool == MapActiveTool.Pan)
+                {
+                    if (isDragging)
+                    {
+                        translate = new System.Drawing.Point(e.X - dragStart.X, e.Y - dragStart.Y);
+                    }
+                }
+
+                // FIXME: 
+                //
+                // We really need a JS setTimeout() equivalent for C# because that's what we want
+                // to do here, set a delayed call to QueryFirstVisibleTooltip() that is aborted if
+                // the mouse pointer has moved significantly since the last time.
+                //
+                // A timer based approach could probably work, but I haven't figured out the best 
+                // way yet.
+
+                this.TooltipsEnabled = !isDragging && this.FeatureTooltipsEnabled;
+
+                //Only query for tooltips if not digitizing
+                if (this.DigitizingType == MapDigitizationType.None &&
+                   (this.ActiveTool == MapActiveTool.Select || this.ActiveTool == MapActiveTool.Pan) &&
+                    this.TooltipsEnabled)
+                {
+#if TRACE
+                    var sw = new Stopwatch();
+                    sw.Start();
+#endif
+                    _activeTooltipText = QueryFirstVisibleTooltip(e.X, e.Y);
+#if TRACE
+                    sw.Stop();
+                    Trace.TraceInformation("QueryFirstVisibleTooltip() executed in {0}ms", sw.ElapsedMilliseconds);
+#endif
+                }
+                else
+                {
+                    _activeTooltipText = null;
+                }
+
+                if (e.Button == MouseButtons.Left || !string.IsNullOrEmpty(_activeTooltipText))
+                    Invalidate();
+            }
+            else if (this.DigitizingType != MapDigitizationType.None)
+            {
+                if (dPath.Count >= 2)
+                {
+                    //Fix the last one, can't edit last one because points are value types
+                    dPath.RemoveAt(dPath.Count - 1);
+                    dPath.Add(new Point(e.X, e.Y));
+                    Trace.TraceInformation("Updating last point of a {0} point path", dPath.Count);
+                }
+                Invalidate();
+            }
+        }
+
+        private void HandleMouseUp(MouseEventArgs e)
+        {
+            if (isDragging)
+            {
+                isDragging = false;
+
+                if (this.ActiveTool == MapActiveTool.Pan)
+                {
+                    //FIXME: This is not perfect. The view will be slightly off of where you released the mouse button
+
+                    //System.Diagnostics.Trace.TraceInformation("Dragged screen distance (" + translate.X + ", " + translate.Y + ")");
+
+                    int dx = e.X - dragStart.X;
+                    int dy = e.Y - dragStart.Y;
+
+                    var centerScreen = new Point(this.Location.X + (this.Width / 2), this.Location.Y + (this.Height / 2));
+
+                    centerScreen.X -= translate.X;
+                    centerScreen.Y -= translate.Y;
+
+                    var pt = _map.ViewCenter;
+                    var coord = ScreenToMapUnits(centerScreen.X, centerScreen.Y);
+
+                    double mdx = coord.X - pt.X;
+                    double mdy = coord.Y - pt.Y;
+
+                    ZoomToView(coord.X, coord.Y, _map.ViewScale, true);
+                    Trace.TraceInformation("END PANNING");
+                }
+                else if (this.ActiveTool == MapActiveTool.Select)
+                {
+                    var mapPt = ScreenToMapUnits(e.X, e.Y);
+                    var mapDragPt = ScreenToMapUnits(dragStart.X, dragStart.Y);
+                    var env = ObjectFactory.CreateEnvelope(
+                        Math.Min(mapPt.X, mapDragPt.X),
+                        Math.Min(mapPt.Y, mapDragPt.Y),
+                        Math.Max(mapPt.X, mapDragPt.X),
+                        Math.Max(mapPt.Y, mapDragPt.Y));
+                    SelectByWkt(MakeWktPolygon(env.MinX, env.MinY, env.MaxX, env.MaxY));
+                }
+                else if (this.ActiveTool == MapActiveTool.ZoomIn)
+                {
+                    var mapPt = ScreenToMapUnits(e.X, e.Y);
+                    var mapDragPt = ScreenToMapUnits(dragStart.X, dragStart.Y);
+
+                    PointF ll;
+                    PointF ur;
+
+                    if (mapPt.X <= mapDragPt.X && mapPt.Y <= mapDragPt.Y)
+                    {
+                        ll = mapPt;
+                        ur = mapDragPt;
+                    }
+                    else
+                    {
+                        ll = mapDragPt;
+                        ur = mapPt;
+                    }
+
+                    ZoomToExtents(ll.X, ll.Y, ur.X, ur.Y);
+                }
+            }
+        }
+
+        private void OnMouseMapPositionChanged(double x, double y)
+        {
+            var handler = this.MouseMapPositionChanged;
+            if (handler != null)
+                handler(this, new MapPointEventArgs(x, y));
+        }
+
+        /// <summary>
+        /// Raised when the map cursor position has changed
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("Raised when the map position as indicated by the current mouse pointer has changed")]
+        public event EventHandler<MapPointEventArgs> MouseMapPositionChanged;
+
+        #endregion
+
+        private MapActiveTool _tool;
+
+        /// <summary>
+        /// Gets or sets the active tool
+        /// </summary>
+        [Browsable(false)]
+        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+        public MapActiveTool ActiveTool
+        {
+            get
+            {
+                return _tool;
+            }
+            set
+            {
+                if (_tool.Equals(value))
+                    return;
+
+                _tool = value;
+                switch (value)
+                {
+                    case MapActiveTool.Pan:
+                        using (var ms = new MemoryStream(Properties.Resources.grab))
+                        {
+                            this.Cursor = new Cursor(ms);
+                        }
+                        break;
+                    case MapActiveTool.ZoomIn:
+                        using (var ms = new MemoryStream(Properties.Resources.zoomin))
+                        {
+                            this.Cursor = new Cursor(ms);
+                        }
+                        break;
+                    case MapActiveTool.ZoomOut:
+                        using (var ms = new MemoryStream(Properties.Resources.zoomout))
+                        {
+                            this.Cursor = new Cursor(ms);
+                        }
+                        break;
+                    case MapActiveTool.None:
+                    case MapActiveTool.Select:
+                        {
+                            this.Cursor = Cursors.Default;
+                        }
+                        break;
+                }
+
+                //Clear to prevent stray tooltips from being rendered
+                if (value != MapActiveTool.Select &&
+                    value != MapActiveTool.Pan)
+                {
+                    _activeTooltipText = null;
+                }
+
+                if (value != MapActiveTool.None)
+                    this.DigitizingType = MapDigitizationType.None;
+
+                OnPropertyChanged("ActiveTool");
+            }
+        }
+
+        /// <summary>
+        /// Screens to map units.
+        /// </summary>
+        /// <param name="x">The x.</param>
+        /// <param name="y">The y.</param>
+        /// <returns></returns>
+        public PointF ScreenToMapUnits(double x, double y)
+        {
+            return ScreenToMapUnits(x, y, false);
+        }
+
+        private PointF ScreenToMapUnits(double x, double y, bool allowOutsideWindow)
+        {
+            if (!allowOutsideWindow)
+            {
+                if (x > this.Width - 1) x = this.Width - 1;
+                else if (x < 0) x = 0;
+
+                if (y > this.Height - 1) y = this.Height - 1;
+                else if (y < 0) y = 0;
+            }
+
+            x = _extX1 + (_extX2 - _extX1) * (x / this.Width);
+            y = _extY1 - (_extY1 - _extY2) * (y / this.Height);
+            return new PointF((float)x, (float)y);
+        }
+
+        /// <summary>
+        /// Occurs when a property value changes.
+        /// </summary>
+        [Category("MapGuide Viewer")]
+        [Description("Raised when a public property of this component has changed")]
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        /// <summary>
+        /// Called when a public property has changed
+        /// </summary>
+        /// <param name="name">The name.</param>
+        protected void OnPropertyChanged(string name)
+        {
+            var handler = this.PropertyChanged;
+            if (handler != null)
+                handler(this, new PropertyChangedEventArgs(name));
+        }
+
+        public bool HasLoadedMap { get { return _map != null; } }
+    }
+}


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Properties
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/Tools/Maestro/Maestro.MapViewer/Properties/AssemblyInfo.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Properties/AssemblyInfo.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Properties/AssemblyInfo.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Maestro.MapViewer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyProduct("Maestro.MapViewer")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a8ce632c-f122-43b9-b9f3-d00520adcb89")]

Added: trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.Designer.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,930 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.225
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Maestro.MapViewer.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Maestro.MapViewer.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap about {
+            get {
+                object obj = ResourceManager.GetObject("about", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap buffer {
+            get {
+                object obj = ResourceManager.GetObject("buffer", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap control {
+            get {
+                object obj = ResourceManager.GetObject("control", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap control_180 {
+            get {
+                object obj = ResourceManager.GetObject("control_180", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to {0} features in layer.
+        /// </summary>
+        internal static string CountFormat {
+            get {
+                return ResourceManager.GetString("CountFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Name: {1}{0}Feature Source: {2}{0}Feature Class: {3}.
+        /// </summary>
+        internal static string DefaultLayerTooltip {
+            get {
+                return ResourceManager.GetString("DefaultLayerTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Name: {1}{0}Feature Source: {2}.
+        /// </summary>
+        internal static string DrawingLayerTooltip {
+            get {
+                return ResourceManager.GetString("DrawingLayerTooltip", resourceCulture);
+            }
+        }
+        
+        internal static System.Drawing.Bitmap edit_copy {
+            get {
+                object obj = ResourceManager.GetObject("edit_copy", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap edit_cut {
+            get {
+                object obj = ResourceManager.GetObject("edit_cut", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap edit_duplicate {
+            get {
+                object obj = ResourceManager.GetObject("edit_duplicate", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap edit_paste {
+            get {
+                object obj = ResourceManager.GetObject("edit_paste", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap edit_xml {
+            get {
+                object obj = ResourceManager.GetObject("edit_xml", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap error {
+            get {
+                object obj = ResourceManager.GetObject("error", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap file_print {
+            get {
+                object obj = ResourceManager.GetObject("file_print", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap file_save {
+            get {
+                object obj = ResourceManager.GetObject("file_save", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static byte[] grab {
+            get {
+                object obj = ResourceManager.GetObject("grab", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap help {
+            get {
+                object obj = ResourceManager.GetObject("help", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap icon_etc {
+            get {
+                object obj = ResourceManager.GetObject("icon_etc", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap icon_home {
+            get {
+                object obj = ResourceManager.GetObject("icon_home", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap icon_loading {
+            get {
+                object obj = ResourceManager.GetObject("icon_loading", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap icon_pan {
+            get {
+                object obj = ResourceManager.GetObject("icon_pan", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap icon_select {
+            get {
+                object obj = ResourceManager.GetObject("icon_select", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap icon_tasks {
+            get {
+                object obj = ResourceManager.GetObject("icon_tasks", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap icon_zoomselect {
+            get {
+                object obj = ResourceManager.GetObject("icon_zoomselect", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap iconNavigator {
+            get {
+                object obj = ResourceManager.GetObject("iconNavigator", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap info {
+            get {
+                object obj = ResourceManager.GetObject("info", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap initial_center {
+            get {
+                object obj = ResourceManager.GetObject("initial_center", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap invoke_script {
+            get {
+                object obj = ResourceManager.GetObject("invoke_script", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap invoke_url {
+            get {
+                object obj = ResourceManager.GetObject("invoke_url", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap layer_shape {
+            get {
+                object obj = ResourceManager.GetObject("layer_shape", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap layer_shape_ellipse {
+            get {
+                object obj = ResourceManager.GetObject("layer_shape_ellipse", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap layer_shape_line {
+            get {
+                object obj = ResourceManager.GetObject("layer_shape_line", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap layer_shape_polygon {
+            get {
+                object obj = ResourceManager.GetObject("layer_shape_polygon", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap layer_shape_polyline {
+            get {
+                object obj = ResourceManager.GetObject("layer_shape_polyline", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap layer_small {
+            get {
+                object obj = ResourceManager.GetObject("layer_small", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap lc_broken {
+            get {
+                object obj = ResourceManager.GetObject("lc_broken", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap lc_dwf {
+            get {
+                object obj = ResourceManager.GetObject("lc_dwf", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap lc_group {
+            get {
+                object obj = ResourceManager.GetObject("lc_group", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap lc_raster {
+            get {
+                object obj = ResourceManager.GetObject("lc_raster", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap lc_select {
+            get {
+                object obj = ResourceManager.GetObject("lc_select", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap lc_theme {
+            get {
+                object obj = ResourceManager.GetObject("lc_theme", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap lc_unselect {
+            get {
+                object obj = ResourceManager.GetObject("lc_unselect", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap load_package {
+            get {
+                object obj = ResourceManager.GetObject("load_package", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap measure {
+            get {
+                object obj = ResourceManager.GetObject("measure", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap monitor_status {
+            get {
+                object obj = ResourceManager.GetObject("monitor_status", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap options {
+            get {
+                object obj = ResourceManager.GetObject("options", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap overview_map {
+            get {
+                object obj = ResourceManager.GetObject("overview_map", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap PoweredBy_en {
+            get {
+                object obj = ResourceManager.GetObject("PoweredBy_en", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap preview {
+            get {
+                object obj = ResourceManager.GetObject("preview", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap print {
+            get {
+                object obj = ResourceManager.GetObject("print", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap search {
+            get {
+                object obj = ResourceManager.GetObject("search", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap select_centre {
+            get {
+                object obj = ResourceManager.GetObject("select_centre", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap select_clear {
+            get {
+                object obj = ResourceManager.GetObject("select_clear", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap select_features {
+            get {
+                object obj = ResourceManager.GetObject("select_features", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap select_polygon {
+            get {
+                object obj = ResourceManager.GetObject("select_polygon", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap select_radius {
+            get {
+                object obj = ResourceManager.GetObject("select_radius", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap select_zoom {
+            get {
+                object obj = ResourceManager.GetObject("select_zoom", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Clear Selection.
+        /// </summary>
+        internal static string TextClearSelection {
+            get {
+                return ResourceManager.GetString("TextClearSelection", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to X: {0:0.0000000}, Y: {1:0.0000000}.
+        /// </summary>
+        internal static string TextCoordinatePosition {
+            get {
+                return ResourceManager.GetString("TextCoordinatePosition", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Copy map to clipboard.
+        /// </summary>
+        internal static string TextCopyMap {
+            get {
+                return ResourceManager.GetString("TextCopyMap", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Digitize Circle.
+        /// </summary>
+        internal static string TextDigitizeCircle {
+            get {
+                return ResourceManager.GetString("TextDigitizeCircle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Digitize Line.
+        /// </summary>
+        internal static string TextDigitizeLine {
+            get {
+                return ResourceManager.GetString("TextDigitizeLine", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Digitize Line String.
+        /// </summary>
+        internal static string TextDigitizeLineString {
+            get {
+                return ResourceManager.GetString("TextDigitizeLineString", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Digitize Point.
+        /// </summary>
+        internal static string TextDigitizePoint {
+            get {
+                return ResourceManager.GetString("TextDigitizePoint", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Digitize Polygon.
+        /// </summary>
+        internal static string TextDigitizePolygon {
+            get {
+                return ResourceManager.GetString("TextDigitizePolygon", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Digitize Rectangle.
+        /// </summary>
+        internal static string TextDigitizeRectangle {
+            get {
+                return ResourceManager.GetString("TextDigitizeRectangle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Disable Tooltips.
+        /// </summary>
+        internal static string TextDisableTooltips {
+            get {
+                return ResourceManager.GetString("TextDisableTooltips", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Enable Tooltips.
+        /// </summary>
+        internal static string TextEnableTooltips {
+            get {
+                return ResourceManager.GetString("TextEnableTooltips", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Exit.
+        /// </summary>
+        internal static string TextExitApplication {
+            get {
+                return ResourceManager.GetString("TextExitApplication", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Load Package.
+        /// </summary>
+        internal static string TextLoadPackage {
+            get {
+                return ResourceManager.GetString("TextLoadPackage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Nothing is selected.
+        /// </summary>
+        internal static string TextNoSelection {
+            get {
+                return ResourceManager.GetString("TextNoSelection", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Options Saved.
+        /// </summary>
+        internal static string TextOptionsSaved {
+            get {
+                return ResourceManager.GetString("TextOptionsSaved", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Package Loaded.
+        /// </summary>
+        internal static string TextPackageLoaded {
+            get {
+                return ResourceManager.GetString("TextPackageLoaded", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Pan.
+        /// </summary>
+        internal static string TextPan {
+            get {
+                return ResourceManager.GetString("TextPan", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Plot to DWF.
+        /// </summary>
+        internal static string TextPlotToDwf {
+            get {
+                return ResourceManager.GetString("TextPlotToDwf", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Print.
+        /// </summary>
+        internal static string TextPrint {
+            get {
+                return ResourceManager.GetString("TextPrint", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Refresh Map.
+        /// </summary>
+        internal static string TextRefreshMap {
+            get {
+                return ResourceManager.GetString("TextRefreshMap", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Scale.
+        /// </summary>
+        internal static string TextScale {
+            get {
+                return ResourceManager.GetString("TextScale", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select.
+        /// </summary>
+        internal static string TextSelect {
+            get {
+                return ResourceManager.GetString("TextSelect", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to {0} features selected.
+        /// </summary>
+        internal static string TextSelectedFeatures {
+            get {
+                return ResourceManager.GetString("TextSelectedFeatures", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select Polygon.
+        /// </summary>
+        internal static string TextSelectPolygon {
+            get {
+                return ResourceManager.GetString("TextSelectPolygon", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select Radius.
+        /// </summary>
+        internal static string TextSelectRadius {
+            get {
+                return ResourceManager.GetString("TextSelectRadius", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Task Pane.
+        /// </summary>
+        internal static string TextTaskPane {
+            get {
+                return ResourceManager.GetString("TextTaskPane", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Viewer Options.
+        /// </summary>
+        internal static string TextViewerOptions {
+            get {
+                return ResourceManager.GetString("TextViewerOptions", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Zoom Extents.
+        /// </summary>
+        internal static string TextZoomExtents {
+            get {
+                return ResourceManager.GetString("TextZoomExtents", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Zoom In.
+        /// </summary>
+        internal static string TextZoomIn {
+            get {
+                return ResourceManager.GetString("TextZoomIn", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Zoom Next.
+        /// </summary>
+        internal static string TextZoomNext {
+            get {
+                return ResourceManager.GetString("TextZoomNext", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Zoom Out.
+        /// </summary>
+        internal static string TextZoomOut {
+            get {
+                return ResourceManager.GetString("TextZoomOut", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Zoom Previous.
+        /// </summary>
+        internal static string TextZoomPrevious {
+            get {
+                return ResourceManager.GetString("TextZoomPrevious", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Zoom to Selection.
+        /// </summary>
+        internal static string TextZoomToSelection {
+            get {
+                return ResourceManager.GetString("TextZoomToSelection", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Name: {1}{0}Feature Source: {2}{0}Feature Class: {3}{0}Number of Rules: {4}.
+        /// </summary>
+        internal static string ThemedLayerTooltip {
+            get {
+                return ResourceManager.GetString("ThemedLayerTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Buffer.
+        /// </summary>
+        internal static string TitleBuffer {
+            get {
+                return ResourceManager.GetString("TitleBuffer", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Measure.
+        /// </summary>
+        internal static string TitleMeasure {
+            get {
+                return ResourceManager.GetString("TitleMeasure", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Print Settings.
+        /// </summary>
+        internal static string TitlePrintSettings {
+            get {
+                return ResourceManager.GetString("TitlePrintSettings", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Query.
+        /// </summary>
+        internal static string TitleQuery {
+            get {
+                return ResourceManager.GetString("TitleQuery", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Theme.
+        /// </summary>
+        internal static string TitleTheme {
+            get {
+                return ResourceManager.GetString("TitleTheme", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Viewer Options.
+        /// </summary>
+        internal static string TitleViewerOptions {
+            get {
+                return ResourceManager.GetString("TitleViewerOptions", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Tooltips are enabled. Click to disable.
+        /// </summary>
+        internal static string TooltipDisableTooltips {
+            get {
+                return ResourceManager.GetString("TooltipDisableTooltips", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Tooltips are disabled. Click to enable.
+        /// </summary>
+        internal static string TooltipEnableTooltips {
+            get {
+                return ResourceManager.GetString("TooltipEnableTooltips", resourceCulture);
+            }
+        }
+        
+        internal static System.Drawing.Bitmap ui_tooltip_balloon_bottom {
+            get {
+                object obj = ResourceManager.GetObject("ui_tooltip_balloon_bottom", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap view_back {
+            get {
+                object obj = ResourceManager.GetObject("view_back", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap view_forward {
+            get {
+                object obj = ResourceManager.GetObject("view_forward", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap view_log {
+            get {
+                object obj = ResourceManager.GetObject("view_log", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap view_refresh {
+            get {
+                object obj = ResourceManager.GetObject("view_refresh", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap zoom_dynamic {
+            get {
+                object obj = ResourceManager.GetObject("zoom_dynamic", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap zoom_full {
+            get {
+                object obj = ResourceManager.GetObject("zoom_full", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap zoom_in {
+            get {
+                object obj = ResourceManager.GetObject("zoom_in", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap zoom_in_fixed {
+            get {
+                object obj = ResourceManager.GetObject("zoom_in_fixed", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap zoom_out_fixed {
+            get {
+                object obj = ResourceManager.GetObject("zoom_out_fixed", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static byte[] zoomin {
+            get {
+                object obj = ResourceManager.GetObject("zoomin", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+        
+        internal static byte[] zoomout {
+            get {
+                object obj = ResourceManager.GetObject("zoomout", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.resx	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.MapViewer/Properties/Resources.resx	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,454 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="about" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\about.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="buffer" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\buffer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="control" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\control.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="control_180" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\control-180.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="CountFormat" xml:space="preserve">
+    <value>{0} features in layer</value>
+  </data>
+  <data name="DefaultLayerTooltip" xml:space="preserve">
+    <value>Name: {1}{0}Feature Source: {2}{0}Feature Class: {3}</value>
+  </data>
+  <data name="DrawingLayerTooltip" xml:space="preserve">
+    <value>Name: {1}{0}Feature Source: {2}</value>
+  </data>
+  <data name="edit_copy" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\edit-copy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="edit_cut" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\edit-cut.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="edit_duplicate" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\edit-duplicate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="edit_paste" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\edit-paste.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="edit_xml" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\edit-xml.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="error" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="file_print" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\file-print.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="file_save" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\file-save.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="help" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\help.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="iconNavigator" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\iconNavigator.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="icon_etc" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\icon_etc.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="icon_home" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\icon_home.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="icon_loading" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\icon_loading.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="icon_pan" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\icon_pan.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="icon_select" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\icon_select.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="icon_tasks" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\icon_tasks.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="icon_zoomselect" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\icon_zoomselect.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="info" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\info.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="initial_center" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\initial-center.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="invoke_script" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\invoke-script.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="invoke_url" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\invoke-url.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="layer_shape" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\layer-shape.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="layer_shape_ellipse" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\layer-shape-ellipse.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="layer_shape_line" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\layer-shape-line.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="layer_shape_polygon" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\layer-shape-polygon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="layer_shape_polyline" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\layer-shape-polyline.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="layer_small" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\layer-small.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="lc_broken" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\lc_broken.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="lc_dwf" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\lc_dwf.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="lc_group" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\lc_group.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="lc_raster" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\lc_raster.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="lc_select" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\lc_select.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="lc_theme" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\lc_theme.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="lc_unselect" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\lc_unselect.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="load_package" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\load_package.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="measure" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\measure.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="monitor_status" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\monitor_status.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="options" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\options.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="overview_map" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\overview-map.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="PoweredBy_en" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\PoweredBy_en.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="preview" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\preview.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="print" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\print.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="search" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\search.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="select_centre" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\select-centre.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="select_clear" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\select-clear.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="select_features" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\select-features.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="select_polygon" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\select-polygon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="select_radius" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\select-radius.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="select_zoom" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\select-zoom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="TextClearSelection" xml:space="preserve">
+    <value>Clear Selection</value>
+  </data>
+  <data name="TextCopyMap" xml:space="preserve">
+    <value>Copy map to clipboard</value>
+  </data>
+  <data name="TextDigitizeCircle" xml:space="preserve">
+    <value>Digitize Circle</value>
+  </data>
+  <data name="TextDigitizeLine" xml:space="preserve">
+    <value>Digitize Line</value>
+  </data>
+  <data name="TextDigitizeLineString" xml:space="preserve">
+    <value>Digitize Line String</value>
+  </data>
+  <data name="TextDigitizePoint" xml:space="preserve">
+    <value>Digitize Point</value>
+  </data>
+  <data name="TextDigitizePolygon" xml:space="preserve">
+    <value>Digitize Polygon</value>
+  </data>
+  <data name="TextDigitizeRectangle" xml:space="preserve">
+    <value>Digitize Rectangle</value>
+  </data>
+  <data name="TextDisableTooltips" xml:space="preserve">
+    <value>Disable Tooltips</value>
+  </data>
+  <data name="TextEnableTooltips" xml:space="preserve">
+    <value>Enable Tooltips</value>
+  </data>
+  <data name="TextExitApplication" xml:space="preserve">
+    <value>Exit</value>
+  </data>
+  <data name="TextLoadPackage" xml:space="preserve">
+    <value>Load Package</value>
+  </data>
+  <data name="TextNoSelection" xml:space="preserve">
+    <value>Nothing is selected</value>
+  </data>
+  <data name="TextOptionsSaved" xml:space="preserve">
+    <value>Options Saved</value>
+  </data>
+  <data name="TextPackageLoaded" xml:space="preserve">
+    <value>Package Loaded</value>
+  </data>
+  <data name="TextPan" xml:space="preserve">
+    <value>Pan</value>
+  </data>
+  <data name="TextPlotToDwf" xml:space="preserve">
+    <value>Plot to DWF</value>
+  </data>
+  <data name="TextPrint" xml:space="preserve">
+    <value>Print</value>
+  </data>
+  <data name="TextRefreshMap" xml:space="preserve">
+    <value>Refresh Map</value>
+  </data>
+  <data name="TextScale" xml:space="preserve">
+    <value>Scale</value>
+  </data>
+  <data name="TextSelect" xml:space="preserve">
+    <value>Select</value>
+  </data>
+  <data name="TextSelectPolygon" xml:space="preserve">
+    <value>Select Polygon</value>
+  </data>
+  <data name="TextSelectRadius" xml:space="preserve">
+    <value>Select Radius</value>
+  </data>
+  <data name="TextTaskPane" xml:space="preserve">
+    <value>Task Pane</value>
+  </data>
+  <data name="TextViewerOptions" xml:space="preserve">
+    <value>Viewer Options</value>
+  </data>
+  <data name="TextZoomExtents" xml:space="preserve">
+    <value>Zoom Extents</value>
+  </data>
+  <data name="TextZoomIn" xml:space="preserve">
+    <value>Zoom In</value>
+  </data>
+  <data name="TextZoomNext" xml:space="preserve">
+    <value>Zoom Next</value>
+  </data>
+  <data name="TextZoomOut" xml:space="preserve">
+    <value>Zoom Out</value>
+  </data>
+  <data name="TextZoomPrevious" xml:space="preserve">
+    <value>Zoom Previous</value>
+  </data>
+  <data name="TextZoomToSelection" xml:space="preserve">
+    <value>Zoom to Selection</value>
+  </data>
+  <data name="ThemedLayerTooltip" xml:space="preserve">
+    <value>Name: {1}{0}Feature Source: {2}{0}Feature Class: {3}{0}Number of Rules: {4}</value>
+  </data>
+  <data name="TitleBuffer" xml:space="preserve">
+    <value>Buffer</value>
+  </data>
+  <data name="TitleMeasure" xml:space="preserve">
+    <value>Measure</value>
+  </data>
+  <data name="TitlePrintSettings" xml:space="preserve">
+    <value>Print Settings</value>
+  </data>
+  <data name="TitleQuery" xml:space="preserve">
+    <value>Query</value>
+  </data>
+  <data name="TitleTheme" xml:space="preserve">
+    <value>Theme</value>
+  </data>
+  <data name="TitleViewerOptions" xml:space="preserve">
+    <value>Viewer Options</value>
+  </data>
+  <data name="TooltipDisableTooltips" xml:space="preserve">
+    <value>Tooltips are enabled. Click to disable</value>
+  </data>
+  <data name="TooltipEnableTooltips" xml:space="preserve">
+    <value>Tooltips are disabled. Click to enable</value>
+  </data>
+  <data name="ui_tooltip_balloon_bottom" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ui-tooltip-balloon-bottom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="view_back" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\view-back.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="view_forward" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\view-forward.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="view_log" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\view_log.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="view_refresh" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\view-refresh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="zoom_dynamic" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\zoom-dynamic.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="zoom_full" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\zoom-full.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="zoom_in" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\zoom-in.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="zoom_in_fixed" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\zoom-in-fixed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="zoom_out_fixed" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\zoom-out-fixed.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="grab" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\grab.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name="zoomin" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\zoomin.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name="zoomout" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\zoomout.cur;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name="TextSelectedFeatures" xml:space="preserve">
+    <value>{0} features selected</value>
+  </data>
+  <data name="TextCoordinatePosition" xml:space="preserve">
+    <value>X: {0:0.0000000}, Y: {1:0.0000000}</value>
+  </data>
+</root>
\ No newline at end of file


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/PoweredBy_en.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/PoweredBy_en.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/about.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/about.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/buffer.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/buffer.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/control-180.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/control-180.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/control.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/control.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-copy.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-copy.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-cut.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-cut.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-duplicate.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-duplicate.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-paste.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-paste.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-xml.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/edit-xml.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/error.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/error.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/file-print.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/file-print.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/file-save.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/file-save.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/grab.cur
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/grab.cur
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/help.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/help.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/iconNavigator.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/iconNavigator.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_etc.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_etc.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_home.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_home.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_loading.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_loading.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_pan.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_pan.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_select.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_select.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_tasks.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_tasks.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_zoomselect.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/icon_zoomselect.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/info.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/info.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/initial-center.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/initial-center.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/invoke-script.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/invoke-script.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/invoke-url.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/invoke-url.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-ellipse.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-ellipse.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-line.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-line.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-polygon.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-polygon.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-polyline.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape-polyline.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-shape.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-small.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/layer-small.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_broken.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_broken.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_dwf.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_dwf.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_group.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_group.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_raster.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_raster.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_select.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_select.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_theme.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_theme.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_unselect.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/lc_unselect.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/load_package.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/load_package.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/measure.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/measure.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/monitor_status.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/monitor_status.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/options.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/options.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/overview-map.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/overview-map.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/preview.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/preview.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/print.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/print.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/search.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/search.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-centre.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-centre.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-clear.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-clear.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-features.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-features.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-polygon.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-polygon.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-radius.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-radius.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-zoom.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/select-zoom.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/ui-tooltip-balloon-bottom.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/ui-tooltip-balloon-bottom.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-back.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-back.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-forward.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-forward.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-refresh.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view-refresh.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view_log.gif
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/view_log.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-dynamic.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-dynamic.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-full.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-full.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-in-fixed.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-in-fixed.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-in.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-in.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-out-fixed.png
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoom-out-fixed.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoomin.cur
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoomin.cur
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoomout.cur
===================================================================
(Binary files differ)


Property changes on: trunk/Tools/Maestro/Maestro.MapViewer/Resources/zoomout.cur
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream


Property changes on: trunk/Tools/Maestro/Maestro.TestViewer
___________________________________________________________________
Added: svn:ignore
   + bin
obj


Added: trunk/Tools/Maestro/Maestro.TestViewer/Maestro.TestViewer.csproj
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/Maestro.TestViewer.csproj	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/Maestro.TestViewer.csproj	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A1DF0D61-ADBC-4FC9-BE32-54C3C10538E2}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Maestro.TestViewer</RootNamespace>
+    <AssemblyName>Maestro.TestViewer</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\GlobalAssemblyInfo.cs">
+      <Link>GlobalAssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="..\Properties\SignedAssemblyInfo2.cs">
+      <Link>SignedAssemblyInfo2.cs</Link>
+    </Compile>
+    <Compile Include="MainForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="MainForm.Designer.cs">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="MainForm.resx">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <None Include="app.config" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Maestro.Editors\Maestro.Editors.csproj">
+      <Project>{5AD2CDBA-952E-4148-98A1-31D2E0D540D5}</Project>
+      <Name>Maestro.Editors</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Maestro.Login\Maestro.Login.csproj">
+      <Project>{07588440-5F9F-4C30-AA06-9CF30BA6DDE6}</Project>
+      <Name>Maestro.Login</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Maestro.MapViewer\Maestro.MapViewer.csproj">
+      <Project>{4F9658DE-D16F-4B40-B830-BB1E0136DBD7}</Project>
+      <Name>Maestro.MapViewer</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\OSGeo.MapGuide.ExtendedObjectModels\OSGeo.MapGuide.ExtendedObjectModels.csproj">
+      <Project>{B3A2B816-9F41-4857-A111-09D2DF2550D6}</Project>
+      <Name>OSGeo.MapGuide.ExtendedObjectModels</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\OSGeo.MapGuide.MaestroAPI.Http\OSGeo.MapGuide.MaestroAPI.Http.csproj">
+      <Project>{6EF1E775-444B-4E5F-87FB-D687C43A68D7}</Project>
+      <Name>OSGeo.MapGuide.MaestroAPI.Http</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\OSGeo.MapGuide.MaestroAPI\OSGeo.MapGuide.MaestroAPI.csproj">
+      <Project>{80FA3158-8B5F-48D1-A393-0378AFE48A7E}</Project>
+      <Name>OSGeo.MapGuide.MaestroAPI</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="..\OSGeo.MapGuide.MaestroAPI\ConnectionProviders.xml">
+      <Link>ConnectionProviders.xml</Link>
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

Added: trunk/Tools/Maestro/Maestro.TestViewer/MainForm.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/MainForm.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/MainForm.Designer.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,217 @@
+namespace Maestro.TestViewer
+{
+    partial class MainForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+            this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.openMapDefinitionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.statusStrip1 = new System.Windows.Forms.StatusStrip();
+            this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+            this.lblCoordinates = new System.Windows.Forms.ToolStripStatusLabel();
+            this.lblSelected = new System.Windows.Forms.ToolStripStatusLabel();
+            this.lblScale = new System.Windows.Forms.ToolStripStatusLabel();
+            this.mapViewer1 = new Maestro.MapViewer.MapViewer();
+            this.defaultToolbar1 = new Maestro.MapViewer.DefaultToolbar();
+            this.mapStatusTracker1 = new Maestro.MapViewer.MapStatusTracker();
+            this.legend1 = new Maestro.MapViewer.Legend();
+            this.menuStrip1.SuspendLayout();
+            this.statusStrip1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
+            this.splitContainer1.Panel1.SuspendLayout();
+            this.splitContainer1.Panel2.SuspendLayout();
+            this.splitContainer1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // menuStrip1
+            // 
+            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.fileToolStripMenuItem});
+            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+            this.menuStrip1.Name = "menuStrip1";
+            this.menuStrip1.Size = new System.Drawing.Size(655, 24);
+            this.menuStrip1.TabIndex = 0;
+            this.menuStrip1.Text = "menuStrip1";
+            // 
+            // fileToolStripMenuItem
+            // 
+            this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.openMapDefinitionToolStripMenuItem,
+            this.quitToolStripMenuItem});
+            this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+            this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
+            this.fileToolStripMenuItem.Text = "File";
+            // 
+            // openMapDefinitionToolStripMenuItem
+            // 
+            this.openMapDefinitionToolStripMenuItem.Name = "openMapDefinitionToolStripMenuItem";
+            this.openMapDefinitionToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
+            this.openMapDefinitionToolStripMenuItem.Text = "Open Map Definition";
+            this.openMapDefinitionToolStripMenuItem.Click += new System.EventHandler(this.openMapDefinitionToolStripMenuItem_Click);
+            // 
+            // quitToolStripMenuItem
+            // 
+            this.quitToolStripMenuItem.Name = "quitToolStripMenuItem";
+            this.quitToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
+            this.quitToolStripMenuItem.Text = "Quit";
+            this.quitToolStripMenuItem.Click += new System.EventHandler(this.quitToolStripMenuItem_Click);
+            // 
+            // statusStrip1
+            // 
+            this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.lblCoordinates,
+            this.lblSelected,
+            this.lblScale});
+            this.statusStrip1.Location = new System.Drawing.Point(0, 453);
+            this.statusStrip1.Name = "statusStrip1";
+            this.statusStrip1.Size = new System.Drawing.Size(655, 22);
+            this.statusStrip1.TabIndex = 2;
+            this.statusStrip1.Text = "statusStrip1";
+            // 
+            // splitContainer1
+            // 
+            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
+            this.splitContainer1.Location = new System.Drawing.Point(0, 49);
+            this.splitContainer1.Name = "splitContainer1";
+            // 
+            // splitContainer1.Panel1
+            // 
+            this.splitContainer1.Panel1.Controls.Add(this.legend1);
+            // 
+            // splitContainer1.Panel2
+            // 
+            this.splitContainer1.Panel2.Controls.Add(this.mapViewer1);
+            this.splitContainer1.Size = new System.Drawing.Size(655, 404);
+            this.splitContainer1.SplitterDistance = 217;
+            this.splitContainer1.TabIndex = 3;
+            // 
+            // lblCoordinates
+            // 
+            this.lblCoordinates.Name = "lblCoordinates";
+            this.lblCoordinates.Size = new System.Drawing.Size(0, 17);
+            // 
+            // lblSelected
+            // 
+            this.lblSelected.Name = "lblSelected";
+            this.lblSelected.Size = new System.Drawing.Size(640, 17);
+            this.lblSelected.Spring = true;
+            this.lblSelected.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // lblScale
+            // 
+            this.lblScale.Name = "lblScale";
+            this.lblScale.Size = new System.Drawing.Size(0, 17);
+            // 
+            // mapViewer1
+            // 
+            this.mapViewer1.Cursor = System.Windows.Forms.Cursors.Default;
+            this.mapViewer1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.mapViewer1.Location = new System.Drawing.Point(0, 0);
+            this.mapViewer1.Name = "mapViewer1";
+            this.mapViewer1.PointPixelBuffer = 2;
+            this.mapViewer1.SelectionColor = System.Drawing.Color.Blue;
+            this.mapViewer1.Size = new System.Drawing.Size(434, 404);
+            this.mapViewer1.TabIndex = 1;
+            this.mapViewer1.Text = "mapViewer1";
+            this.mapViewer1.ZoomInFactor = 0.5D;
+            this.mapViewer1.ZoomOutFactor = 2D;
+            // 
+            // defaultToolbar1
+            // 
+            this.defaultToolbar1.Location = new System.Drawing.Point(0, 24);
+            this.defaultToolbar1.Name = "defaultToolbar1";
+            this.defaultToolbar1.Size = new System.Drawing.Size(655, 25);
+            this.defaultToolbar1.TabIndex = 0;
+            this.defaultToolbar1.Text = "defaultToolbar1";
+            this.defaultToolbar1.Viewer = this.mapViewer1;
+            // 
+            // mapStatusTracker1
+            // 
+            this.mapStatusTracker1.CoordinatesLabel = this.lblCoordinates;
+            this.mapStatusTracker1.ScaleLabel = this.lblScale;
+            this.mapStatusTracker1.SelectedLabel = this.lblSelected;
+            this.mapStatusTracker1.Viewer = this.mapViewer1;
+            // 
+            // legend1
+            // 
+            this.legend1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.legend1.GroupContextMenu = null;
+            this.legend1.LayerContextMenu = null;
+            this.legend1.Location = new System.Drawing.Point(0, 0);
+            this.legend1.Name = "legend1";
+            this.legend1.ShowTooltips = false;
+            this.legend1.Size = new System.Drawing.Size(217, 404);
+            this.legend1.TabIndex = 0;
+            this.legend1.ThemeCompressionLimit = 25;
+            this.legend1.Viewer = this.mapViewer1;
+            // 
+            // MainForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(655, 475);
+            this.Controls.Add(this.splitContainer1);
+            this.Controls.Add(this.defaultToolbar1);
+            this.Controls.Add(this.statusStrip1);
+            this.Controls.Add(this.menuStrip1);
+            this.MainMenuStrip = this.menuStrip1;
+            this.Name = "MainForm";
+            this.Text = "Maestro Test Viewer";
+            this.menuStrip1.ResumeLayout(false);
+            this.menuStrip1.PerformLayout();
+            this.statusStrip1.ResumeLayout(false);
+            this.statusStrip1.PerformLayout();
+            this.splitContainer1.Panel1.ResumeLayout(false);
+            this.splitContainer1.Panel2.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
+            this.splitContainer1.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.MenuStrip menuStrip1;
+        private System.Windows.Forms.StatusStrip statusStrip1;
+        private System.Windows.Forms.SplitContainer splitContainer1;
+        private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem openMapDefinitionToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem quitToolStripMenuItem;
+        private System.Windows.Forms.ToolStripStatusLabel lblCoordinates;
+        private System.Windows.Forms.ToolStripStatusLabel lblSelected;
+        private System.Windows.Forms.ToolStripStatusLabel lblScale;
+        private MapViewer.MapViewer mapViewer1;
+        private MapViewer.DefaultToolbar defaultToolbar1;
+        private MapViewer.MapStatusTracker mapStatusTracker1;
+        private MapViewer.Legend legend1;
+    }
+}
+

Added: trunk/Tools/Maestro/Maestro.TestViewer/MainForm.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/MainForm.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/MainForm.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,95 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using Maestro.Editors.Common;
+using OSGeo.MapGuide.ExtendedObjectModels;
+using OSGeo.MapGuide.MaestroAPI;
+using OSGeo.MapGuide.ObjectModels.MapDefinition;
+using OSGeo.MapGuide.MaestroAPI.Services;
+using Maestro.Editors.Generic;
+
+namespace Maestro.TestViewer
+{
+    public partial class MainForm : Form
+    {
+        public MainForm()
+        {
+            InitializeComponent();
+        }
+
+        private IServerConnection _conn;
+
+        protected override void OnLoad(EventArgs e)
+        {
+            //This call is a one-time only call that will instantly register all known resource 
+            //version types and validators. This way you never have to manually reference a 
+            //ObjectModels assembly of the desired resource type you want to work with
+            ModelSetup.Initialize();
+
+            //Anytime we work with the Maestro API, we require an IServerConnection
+            //reference. The Maestro.Login.LoginDialog provides a UI to obtain such a 
+            //reference.
+
+            //If you need to obtain an IServerConnection reference programmatically and
+            //without user intervention, use the ConnectionProviderRegistry class
+            var login = new Maestro.Login.LoginDialog();
+            if (login.ShowDialog() == DialogResult.OK)
+            {
+                _conn = login.Connection;
+            }
+            else //This sample does not work without an IServerConnection
+            {
+                Application.Exit();
+            }
+        }
+
+        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            Application.Exit();
+        }
+
+        private void openMapDefinitionToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            using (var picker = new ResourcePicker(_conn.ResourceService, ResourceTypes.MapDefinition, ResourcePickerMode.OpenResource))
+            {
+                if (picker.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+                {
+                    LoadMap(picker.ResourceID);
+                }
+            }
+        }
+
+        private void LoadMap(string mdfId)
+        {
+            IMapDefinition mdf = (IMapDefinition)_conn.ResourceService.GetResource(mdfId);
+            IMappingService mapSvc = (IMappingService)_conn.GetService((int)ServiceType.Mapping);
+
+            var rtMap = mapSvc.CreateMap(mdf);
+            mapViewer1.LoadMap(rtMap);
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.TestViewer/MainForm.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/MainForm.resx	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/MainForm.resx	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>237, 17</value>
+  </metadata>
+  <metadata name="defaultToolbar1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>353, 17</value>
+  </metadata>
+  <metadata name="mapStatusTracker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>491, 17</value>
+  </metadata>
+</root>
\ No newline at end of file

Added: trunk/Tools/Maestro/Maestro.TestViewer/Program.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/Program.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/Program.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,46 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace Maestro.TestViewer
+{
+    static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new MainForm());
+        }
+
+        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
+        {
+            MessageBox.Show(e.Exception.ToString());
+        }
+    }
+}


Property changes on: trunk/Tools/Maestro/Maestro.TestViewer/Properties
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/Tools/Maestro/Maestro.TestViewer/Properties/AssemblyInfo.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/Properties/AssemblyInfo.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/Properties/AssemblyInfo.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Maestro.TestViewer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyProduct("Maestro.TestViewer")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7b4d6333-2956-4980-ab1d-979eccbbc24a")]

Added: trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.Designer.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.225
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Maestro.TestViewer.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Maestro.TestViewer.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.resx
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.resx	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/Properties/Resources.resx	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file

Added: trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.Designer.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.Designer.cs	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.Designer.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.225
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Maestro.TestViewer.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.settings
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.settings	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/Properties/Settings.settings	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

Added: trunk/Tools/Maestro/Maestro.TestViewer/app.config
===================================================================
--- trunk/Tools/Maestro/Maestro.TestViewer/app.config	                        (rev 0)
+++ trunk/Tools/Maestro/Maestro.TestViewer/app.config	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<configuration>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/MapSelection.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/MapSelection.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/MapSelection.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -303,7 +303,7 @@
                 if (layer == null)
                     throw new ArgumentNullException("layer");
 
-                if (layer.IdentityProperties.Length == 0)
+                if (layer.IdentityProperties.Length == 0 && layer.Parent.StrictSelection)
                     throw new Exception("The layer does not have a primary key, and cannot be used for selection");
 
                 m_layer = layer;

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -31,6 +31,7 @@
 using System.Diagnostics;
 using OSGeo.MapGuide.MaestroAPI.Commands;
 using OSGeo.MapGuide.MaestroAPI.Exceptions;
+using System.Drawing;
 
 namespace OSGeo.MapGuide.MaestroAPI.Mapping
 {
@@ -151,6 +152,7 @@
 
         internal RuntimeMap(IServerConnection conn)
         {
+            this.StrictSelection = true;
             _disableChangeTracking = true;
 
             this.WatermarkUsage = (int)WatermarkUsageType.Viewer;
@@ -950,22 +952,7 @@
                 if (null == _selection)
                 {
                     _selection = new MapSelection(this);
-                    var resId = this.ResourceID.Replace(".Map", ".Selection");
-                    var bLoadedSelection = false;
-                    if (this.ResourceService.ResourceExists(resId))
-                    {
-                        var dataItems = this.ResourceService.EnumerateResourceData(resId);
-                        foreach (var item in dataItems.ResourceData)
-                        {
-                            if (item.Name == "RuntimeData")
-                            {
-                                var ser = new MgBinaryDeserializer(this.ResourceService.GetResourceData(resId, "RuntimeData"), this.CurrentConnection.SiteVersion);
-                                _selection.Deserialize(ser);
-                                bLoadedSelection = true;
-                                break;
-                            }
-                        }
-                    }
+                    var bLoadedSelection = ReloadSelection();
                     
                     if (!bLoadedSelection)
                     {
@@ -976,6 +963,27 @@
             }
         }
 
+        private bool ReloadSelection()
+        {
+            var resId = this.ResourceID.Replace(".Map", ".Selection");
+            var bLoadedSelection = false;
+            if (this.ResourceService.ResourceExists(resId))
+            {
+                var dataItems = this.ResourceService.EnumerateResourceData(resId);
+                foreach (var item in dataItems.ResourceData)
+                {
+                    if (item.Name == "RuntimeData")
+                    {
+                        var ser = new MgBinaryDeserializer(this.ResourceService.GetResourceData(resId, "RuntimeData"), this.CurrentConnection.SiteVersion);
+                        _selection.Deserialize(ser);
+                        bLoadedSelection = true;
+                        break;
+                    }
+                }
+            }
+            return bLoadedSelection;
+        }
+
         /// <summary>
         /// Gets the group by its specified name
         /// </summary>
@@ -1465,19 +1473,54 @@
         /// <param name="format"></param>
         /// <param name="keepSelection"></param>
         /// <returns></returns>
+        [Obsolete("Use the version of RenderDynamicOverlay that is not marked Obsolete")]
         public System.IO.Stream RenderDynamicOverlay(string format, bool keepSelection)
         {
+            return RenderDynamicOverlay(this.Selection, format, keepSelection);
+        }
+        
+        /// <summary>
+        /// Convenience method for rendering a dynamic overlay of the current map
+        /// </summary>
+        /// <param name="sel"></param>
+        /// <param name="format"></param>
+        /// <param name="behavior"></param>
+        /// <returns></returns>
+        [Obsolete("Use the version of RenderDynamicOverlay that is not marked Obsolete")]
+        public System.IO.Stream RenderDynamicOverlay(MapSelection sel, string format, bool keepSelection)
+        {
             if (_mapSvc == null)
                 throw new NotSupportedException();
 
             return _mapSvc.RenderDynamicOverlay(
                 this,
-                this.Selection,
+                sel,
                 format,
                 keepSelection);
         }
 
         /// <summary>
+        /// Convenience method for rendering a dynamic overlay of the current map
+        /// </summary>
+        /// <param name="selection"></param>
+        /// <param name="format"></param>
+        /// <param name="selectionColor"></param>
+        /// <param name="behaviour"></param>
+        /// <returns></returns>
+        public System.IO.Stream RenderDynamicOverlay(MapSelection selection, string format, Color selectionColor, int behaviour)
+        {
+            if (_mapSvc == null)
+                throw new NotSupportedException();
+
+            return _mapSvc.RenderDynamicOverlay(
+                this,
+                selection,
+                format,
+                selectionColor,
+                behaviour);
+        }
+
+        /// <summary>
         /// Convenience method for rendering the legend for this map
         /// </summary>
         /// <param name="width"></param>
@@ -1498,6 +1541,29 @@
                 format);
         }
 
+        public string QueryMapFeatures(string wkt, int maxFeatures, bool persist, string selectionVariant, QueryMapOptions extraOptions)
+        {
+            if (_mapSvc == null)
+                throw new NotSupportedException();
+
+            var ret = _mapSvc.QueryMapFeatures(this.Name, maxFeatures, wkt, true, selectionVariant, extraOptions);
+
+            //Need to re-sync the selection as this will probably have been changed
+            ReloadSelection();
+
+            return ret;
+        }
+
+        public System.Drawing.Image GetLegendImage(string layerDefinitionID, double scale, int width, int height, string format, int geomType, int themeCategory)
+        {
+            if (_mapSvc == null)
+                throw new NotSupportedException();
+
+            return _mapSvc.GetLegendImage(scale, layerDefinitionID, themeCategory, geomType, width, height, format);
+        }
+
         #endregion
+
+        internal bool StrictSelection { get; set; }
     }
 }

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapGroup.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapGroup.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapGroup.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -210,7 +210,7 @@
         public int Type
         {
             get;
-            private set;
+            internal set;
         }
 
         /// <summary>

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapLayer.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapLayer.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMapLayer.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -27,6 +27,7 @@
 using OSGeo.MapGuide.ObjectModels.FeatureSource;
 using OSGeo.MapGuide.MaestroAPI.Feature;
 using System.Diagnostics;
+using OSGeo.MapGuide.MaestroAPI.Schema;
 
 namespace OSGeo.MapGuide.MaestroAPI.Mapping
 {
@@ -59,6 +60,19 @@
         public Type Type { get; set; }
     }
 
+    public static class Extensions
+    {
+        public static RuntimeMapGroup GetParentGroup(this RuntimeMapLayer layer)
+        {
+            Check.NotNull(layer, "layer");
+
+            if (string.IsNullOrEmpty(layer.Group))
+                return null;
+
+            return layer.Parent.Groups[layer.Group];
+        }
+    }
+
     /// <summary>
     /// Represents a runtime map layer. Use <see cref="M:OSGeo.MapGuide.MaestroAPI.Services.IMappingService.CreateMapLayer(OSGeo.MapGuide.MaestroAPI.Mapping.RuntimeMap,OSGeo.MapGuide.ObjectModels.LayerDefinition.ILayerDefinition)"/> to create
     /// instances of this class.
@@ -98,26 +112,9 @@
         /// </summary>
         public RuntimeMap Parent { get; private set; }
 
-        internal RuntimeMapLayer(RuntimeMap parent) 
+        private void Initialize(ILayerDefinition ldf)
         {
-            _scaleRanges = new double[] { 0.0, InfinityScale };
-            _type = kDynamic;
-            this.IdentityProperties = new PropertyInfo[0];
-            _objectId = Guid.NewGuid().ToString();
-            this.Parent = parent;
-            _group = string.Empty;
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RuntimeMapLayer"/> class.
-        /// </summary>
-        /// <param name="parent">The parent.</param>
-        /// <param name="ldf">The LDF.</param>
-        internal RuntimeMapLayer(RuntimeMap parent, ILayerDefinition ldf)
-            : this(parent)
-        {
             Check.NotNull(ldf, "ldf");
-
             this.LayerDefinitionID = ldf.ResourceID;
             if (ldf.SubLayer.LayerType == LayerType.Vector)
             {
@@ -128,6 +125,17 @@
                 _filter = vl.Filter;
                 InitIdentityProperties(vl);
                 _hasTooltips = !string.IsNullOrEmpty(vl.ToolTip);
+                if (vl.HasVectorScaleRanges())
+                {
+                    int vsrCount = vl.GetScaleRangeCount();
+                    _scaleRanges = new double[vsrCount * 2];
+                    for (int i = 0; i < vsrCount; i++)
+                    {
+                        var vsr = vl.GetScaleRangeAt(i);
+                        _scaleRanges[i * 2] = vsr.MinScale.HasValue ? vsr.MinScale.Value : 0;
+                        _scaleRanges[i * 2 + 1] = vsr.MaxScale.HasValue ? vsr.MaxScale.Value : InfinityScale;
+                    }
+                }
             }
             else if (ldf.SubLayer.LayerType == LayerType.Raster)
             {
@@ -135,6 +143,18 @@
                 _qualifiedClassName = rl.FeatureName;
                 _geometryPropertyName = rl.Geometry;
                 _featureSourceId = rl.ResourceId;
+
+                if (rl.GridScaleRangeCount > 0)
+                {
+                    _scaleRanges = new double[rl.GridScaleRangeCount * 2];
+                    int i = 0;
+                    foreach (var gsr in rl.GridScaleRange)
+                    {
+                        _scaleRanges[i * 2] = gsr.MinScale.HasValue ? gsr.MinScale.Value : 0;
+                        _scaleRanges[i * 2 + 1] = gsr.MaxScale.HasValue ? gsr.MaxScale.Value : InfinityScale;
+                        i++;
+                    }
+                }
             }
 
             _expandInLegend = false;
@@ -144,6 +164,29 @@
             _showInLegend = true;
             _visible = true;
 
+            EnsureOrderedMinMaxScales();
+        }
+
+        internal RuntimeMapLayer(RuntimeMap parent) 
+        {
+            _scaleRanges = new double[] { 0.0, InfinityScale };
+            _type = kDynamic;
+            this.IdentityProperties = new PropertyInfo[0];
+            _objectId = Guid.NewGuid().ToString();
+            this.Parent = parent;
+            _group = string.Empty;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RuntimeMapLayer"/> class.
+        /// </summary>
+        /// <param name="parent">The parent.</param>
+        /// <param name="ldf">The LDF.</param>
+        internal RuntimeMapLayer(RuntimeMap parent, ILayerDefinition ldf)
+            : this(parent)
+        {
+            _disableChangeTracking = true;
+            Initialize(ldf);
             _disableChangeTracking = false;
         }
 
@@ -175,72 +218,6 @@
             Check.NotNull(source, "source");
             Check.NotNull(ldf, "ldf");
             Check.Precondition(source.ResourceId == ldf.ResourceID, "source.ResourceId == ldf.ResourceID");
-
-            _disableChangeTracking = true;
-
-            this.LayerDefinitionID = source.ResourceId;
-            _expandInLegend = source.ExpandInLegend;
-            this.Name = source.Name;
-            _selectable = source.Selectable;
-            _showInLegend = source.ShowInLegend;
-            _legendLabel = source.LegendLabel;
-
-            _needsRefresh = false;
-            _displayOrder = 0;
-
-            switch (ldf.SubLayer.LayerType)
-            {
-                case LayerType.Drawing:
-                    {
-                    }
-                    break;
-                case LayerType.Raster:
-                    {
-                        IRasterLayerDefinition rdf = (IRasterLayerDefinition)ldf.SubLayer;
-                        _featureSourceId = rdf.ResourceId;
-                        _geometryPropertyName = rdf.Geometry;
-                        _qualifiedClassName = rdf.FeatureName;
-
-                        if (rdf.GridScaleRangeCount > 0)
-                        {
-                            _scaleRanges = new double[rdf.GridScaleRangeCount * 2];
-                            int i = 0;
-                            foreach (var gsr in rdf.GridScaleRange)
-                            {
-                                _scaleRanges[i * 2] = gsr.MinScale.HasValue ? gsr.MinScale.Value : 0;
-                                _scaleRanges[i * 2 + 1] = gsr.MaxScale.HasValue ? gsr.MaxScale.Value : InfinityScale;
-                                i++;
-                            }
-                        }
-                    }
-                    break;
-                case LayerType.Vector:
-                    {
-                        IVectorLayerDefinition vld = (IVectorLayerDefinition)ldf.SubLayer;
-                        _featureSourceId = vld.ResourceId;
-                        _geometryPropertyName = vld.Geometry;
-                        _qualifiedClassName = vld.FeatureName;
-                        _filter = vld.Filter;
-
-                        if (vld.HasVectorScaleRanges())
-                        {
-                            int vsrCount = vld.GetScaleRangeCount();
-                            _scaleRanges = new double[vsrCount * 2];
-                            for (int i = 0; i < vsrCount; i++)
-                            {
-                                var vsr = vld.GetScaleRangeAt(i);
-                                _scaleRanges[i * 2] = vsr.MinScale.HasValue ? vsr.MinScale.Value : 0;
-                                _scaleRanges[i * 2 + 1] = vsr.MaxScale.HasValue ? vsr.MaxScale.Value : InfinityScale;
-                            }
-                        }
-                        _hasTooltips = !string.IsNullOrEmpty(vld.ToolTip);
-                        //get identity property information
-                        InitIdentityProperties(vld);
-                    }
-                    break;
-            }
-            EnsureOrderedMinMaxScales();
-            _disableChangeTracking = false;
         }
 
         private void EnsureOrderedMinMaxScales()
@@ -954,5 +931,15 @@
             }
             return false;
         }
+
+        /// <summary>
+        /// Convenience method to get the associated class definition
+        /// </summary>
+        /// <returns></returns>
+        public ClassDefinition GetClassDefinition()
+        {
+            var tokens = this.QualifiedClassName.Split(':');
+            return this.Parent.FeatureService.GetClassDefinition(tokens[0], tokens[1]);
+        }
     }
 }

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/MgServerConnectionBase.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/MgServerConnectionBase.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/MgServerConnectionBase.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -31,6 +31,8 @@
 using OSGeo.MapGuide.MaestroAPI.Commands;
 using OSGeo.MapGuide.ObjectModels.LoadProcedure;
 using OSGeo.MapGuide.MaestroAPI.Mapping;
+using System.Drawing;
+using OSGeo.MapGuide.MaestroAPI.Services;
 
 namespace OSGeo.MapGuide.MaestroAPI
 {
@@ -168,6 +170,8 @@
         /// <returns>The selection Xml, or an empty string if there were no data.</returns>
         abstract public string QueryMapFeatures(string runtimeMapName, string wkt, bool persist, QueryMapFeaturesLayerAttributes attributes, bool raw);
 
+        public abstract string QueryMapFeatures(string runtimeMapName, int maxFeatures, string wkt, bool persist, string selectionVariant, QueryMapOptions extraOptions);
+
         /// <summary>
         /// Renders a minature bitmap of the layers style
         /// </summary>
@@ -314,6 +318,17 @@
         /// <returns></returns>
         public abstract System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection);
 
+        /// <summary>
+        /// Renders a dynamic overlay image of the map
+        /// </summary>
+        /// <param name="map"></param>
+        /// <param name="selection"></param>
+        /// <param name="format"></param>
+        /// <param name="selectionColor"></param>
+        /// <param name="behaviour"></param>
+        /// <returns></returns>
+        public abstract System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, Color selectionColor, int behaviour);
+
         #endregion
 
         #region Tile

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2012-06-01 17:26:06 UTC (rev 6727)
@@ -383,6 +383,7 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="PlatformConnectionBase.cs" />
     <Compile Include="Services\NsDoc.cs" />
+    <Compile Include="Services\QueryMapOptions.cs" />
     <Compile Include="Services\ServiceType.cs" />
     <Compile Include="SiteVersion.cs" />
     <Compile Include="Tile\BatchSettings.cs" />

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/AssemblyInfo.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/AssemblyInfo.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/AssemblyInfo.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -20,4 +20,5 @@
 [assembly: Guid("ab443f91-168a-4c13-9477-1b264241b3cd")]
 
 // This long string is the public key of the maestroapi.key token
-[assembly: InternalsVisibleTo("MaestroAPITests, PublicKey=00240000048000009400000006020000002400005253413100040000010001000f196e7ed5bff1e511efa3251b228582b26cbf78ea6d4282742d5c882db02b08ebc99922c0ddccf9ab79ee180250ac6716f986cf6fabdc1404b3dafee8873d4d6327be301f5ca52862065678cd5bc0c18ddc7ef6516723162c985a0c20eec07382a2090486f24393bf80976aa5ab57274620bafd62dfec34d5eed74bf41e72d2")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("MaestroAPITests, PublicKey=00240000048000009400000006020000002400005253413100040000010001000f196e7ed5bff1e511efa3251b228582b26cbf78ea6d4282742d5c882db02b08ebc99922c0ddccf9ab79ee180250ac6716f986cf6fabdc1404b3dafee8873d4d6327be301f5ca52862065678cd5bc0c18ddc7ef6516723162c985a0c20eec07382a2090486f24393bf80976aa5ab57274620bafd62dfec34d5eed74bf41e72d2")]
+[assembly: InternalsVisibleTo("Maestro.MapViewer, PublicKey=00240000048000009400000006020000002400005253413100040000010001000f196e7ed5bff1e511efa3251b228582b26cbf78ea6d4282742d5c882db02b08ebc99922c0ddccf9ab79ee180250ac6716f986cf6fabdc1404b3dafee8873d4d6327be301f5ca52862065678cd5bc0c18ddc7ef6516723162c985a0c20eec07382a2090486f24393bf80976aa5ab57274620bafd62dfec34d5eed74bf41e72d2")]
\ No newline at end of file

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/IMappingService.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -171,6 +171,7 @@
         /// <param name="selection"></param>
         /// <param name="format"></param>
         /// <returns></returns>
+        [Obsolete("Use the version of RenderDynamicOverlay that is not marked Obsolete")]
         System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format);
 
         /// <summary>
@@ -181,9 +182,22 @@
         /// <param name="format"></param>
         /// <param name="keepSelection"></param>
         /// <returns></returns>
+        [Obsolete("Use the version of RenderDynamicOverlay that is not marked Obsolete")]
         System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection);
 
         /// <summary>
+        /// Renders a dynamic overlay image of the map
+        /// </summary>
+        /// <param name="map"></param>
+        /// <param name="selection"></param>
+        /// <param name="format"></param>
+        /// <param name="selectionColor"></param>
+        /// <param name="behaviour"></param>
+        /// <returns></returns>
+        /// <exception cref="T:System.NotSupportedException">Thrown if the service is too old to be able to support this API</exception>
+        System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, Color selectionColor, int behaviour);
+
+        /// <summary>
         /// Renders the runtime map.
         /// </summary>
         /// <param name="resourceId">The resource id.</param>
@@ -310,6 +324,7 @@
         /// <param name="attributes">The type of layer to include in the query</param>
         /// <param name="raw">True if the result should contain the tooltip and link info</param>
         /// <returns>The selection Xml, or an empty string if there were no data.</returns>
+        [Obsolete("Use the version of QueryMapFeatures that isn't marked Obsolete")]
         string QueryMapFeatures(string runtimeMapName, string wkt, bool persist, QueryMapFeaturesLayerAttributes attributes, bool raw);
 
         /// <summary>
@@ -319,6 +334,19 @@
         /// <param name="wkt">The WKT of the geometry to query with (always uses intersection)</param>
         /// <param name="persist">True if the selection should be saved in the runtime map, false otherwise.</param>
         /// <returns>The selection Xml, or an empty string if there were no data.</returns>
+        [Obsolete("Use the version of QueryMapFeatures that isn't marked Obsolete")]
         string QueryMapFeatures(string runtimeMapName, string wkt, bool persist);
+
+        /// <summary>
+        /// Identifies features that meet the specified spatial selection criteria. These features can be persisted as selected features in a map. QueryMapFeatures returns an XML document describing the set of selected features. If a single feature is selected, the XML contains the tooltip, hyperlink, and properties of the feature.
+        /// </summary>
+        /// <param name="runtimeMapName"></param>
+        /// <param name="maxFeatures"></param>
+        /// <param name="wkt"></param>
+        /// <param name="persist"></param>
+        /// <param name="selectionVariant"></param>
+        /// <param name="extraOptions"></param>
+        /// <returns></returns>
+        string QueryMapFeatures(string runtimeMapName, int maxFeatures, string wkt, bool persist, string selectionVariant, QueryMapOptions extraOptions);
     }
 }

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/QueryMapOptions.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/QueryMapOptions.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Services/QueryMapOptions.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -0,0 +1,51 @@
+#region Disclaimer / License
+// Copyright (C) 2012, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+// 
+#endregion
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OSGeo.MapGuide.MaestroAPI.Services
+{
+    /// <summary>
+    /// Additional options for a QueryMapFeatures operation
+    /// </summary>
+    public class QueryMapOptions
+    {
+        /// <summary>
+        /// An array of layer names to restrict the selection to
+        /// </summary>
+        public string[] LayerNames { get; set; }
+
+        /// <summary>
+        /// Bitmask specifying the attributes a layer must have to be considered in the selection process. The following attributes are supported:
+        /// 1 - Layer is visible
+        /// 2 - Layer is selectable
+        /// 4 - Layer has a tooltip defined
+        /// Combinations of one or more attributes are allowed.
+        /// </summary>
+        public QueryMapFeaturesLayerAttributes LayerAttributeFilter { get; set; }
+
+        /// <summary>
+        /// XML filter describing a set of previously selected features. This paramter is useful for obtaining the attribute values of a previously selected feature. 
+        /// </summary>
+        public string FeatureFilter { get; set; }
+    }
+}

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/HttpServerConnection.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -921,6 +921,18 @@
                 OnResourceAdded(newpath);
 		}
 
+        public override System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, Color selectionColor, int behavior)
+        {
+            //This API was introduced in MGOS 2.1 so this won't work with older versions
+            if (this.SiteVersion < new Version(2, 1, 0))
+                throw new NotSupportedException();
+
+            System.IO.MemoryStream ms = new System.IO.MemoryStream();
+            var req = m_reqBuilder.GetDynamicMapOverlayImage(map.Name, (selection == null ? string.Empty : selection.ToXml()), format, selectionColor, behavior);
+
+            return this.OpenRead(req);
+        }
+
         public override System.IO.Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection)
         {
             System.IO.MemoryStream ms = new System.IO.MemoryStream();
@@ -1749,6 +1761,24 @@
             }
         }
 
+        public override string QueryMapFeatures(string runtimeMapName, int maxFeatures, string wkt, bool persist, string selectionVariant, QueryMapOptions extraOptions)
+        {
+            //The request may execeed the url limit of the server, when large geometries
+            System.IO.MemoryStream ms = new System.IO.MemoryStream();
+            System.Net.WebRequest req = m_reqBuilder.QueryMapFeatures(runtimeMapName, maxFeatures, wkt, persist, selectionVariant, extraOptions, ms);
+            req.Timeout = 200 * 1000;
+            ms.Position = 0;
+
+            using (System.IO.Stream rs = req.GetRequestStream())
+            {
+                Utility.CopyStream(ms, rs);
+                rs.Flush();
+            }
+
+            using (var sr = new StreamReader(req.GetResponse().GetResponseStream()))
+                return sr.ReadToEnd();
+        }
+
         public override string QueryMapFeatures(string runtimeMapName, string wkt, bool persist, QueryMapFeaturesLayerAttributes attributes, bool raw)
         {
             //The request may execeed the url limit of the server, when large geometries

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/RequestBuilder.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/RequestBuilder.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/RequestBuilder.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -22,6 +22,7 @@
 using System.Collections.Specialized;
 using OSGeo.MapGuide.ObjectModels.Common;
 using System.Globalization;
+using System.Drawing;
 
 namespace OSGeo.MapGuide.MaestroAPI
 {
@@ -1003,6 +1004,39 @@
 			return req;
 		}
 
+        internal System.Net.WebRequest QueryMapFeatures(string runtimeMapName, int maxFeatures, string wkt, bool persist, string selectionVariant, Services.QueryMapOptions extraOptions, System.IO.Stream outStream)
+        {
+            NameValueCollection param = new NameValueCollection();
+            param.Add("OPERATION", "QUERYMAPFEATURES");
+            param.Add("VERSION", "1.0.0");
+            param.Add("PERSIST", persist ? "1" : "0");
+            param.Add("MAPNAME", runtimeMapName);
+            param.Add("SESSION", m_sessionID);
+            param.Add("GEOMETRY", wkt);
+            param.Add("SELECTIONVARIANT", selectionVariant);
+            param.Add("MAXFEATURES", maxFeatures.ToString(CultureInfo.InvariantCulture));
+            if (extraOptions != null)
+            {
+                param.Add("LAYERATTRIBUTEFILTER", ((int)extraOptions.LayerAttributeFilter).ToString());
+                if (!string.IsNullOrEmpty(extraOptions.FeatureFilter))
+                    param.Add("FEATUREFILTER", extraOptions.FeatureFilter);
+                if (extraOptions.LayerNames != null && extraOptions.LayerNames.Length > 0)
+                    param.Add("LAYERNAMES", string.Join(",", extraOptions.LayerNames));
+            }
+            param.Add("FORMAT", "text/xml");
+            param.Add("CLIENTAGENT", m_userAgent);
+
+            if (m_locale != null)
+                param.Add("LOCALE", m_locale);
+
+            string boundary;
+            System.Net.WebRequest req = PrepareFormContent(outStream, out boundary);
+            EncodeFormParameters(boundary, param, outStream);
+            req.ContentLength = outStream.Length;
+
+            return req;
+        }
+
 		public string EnumerateApplicationTemplates()
 		{
 			NameValueCollection param = new NameValueCollection();
@@ -1518,7 +1552,28 @@
 
         public string GetClassDefinition(string resourceId, string schemaName, string className)
         {
+            //BOGUS: GETCLASSDEFINITION is FUBAR (#2015)
+            //
+            //Fortunately, we can workaround this via DESCRIBEFEATURESCHEMA with CLASSNAMES hint.
+            //This should still tap into FDO RFC23 enhancements server-side where applicable
+
             NameValueCollection param = new NameValueCollection();
+            param.Add("OPERATION", "DESCRIBEFEATURESCHEMA");
+            param.Add("VERSION", "1.0.0");
+            param.Add("SESSION", m_sessionID);
+            param.Add("FORMAT", "text/xml");
+            param.Add("CLIENTAGENT", m_userAgent);
+
+            if (m_locale != null)
+                param.Add("LOCALE", m_locale);
+
+            param.Add("RESOURCEID", resourceId);
+            if (!string.IsNullOrEmpty(schemaName))
+                param.Add("SCHEMA", schemaName);
+            param.Add("CLASSNAMES", className);
+
+            /*
+            NameValueCollection param = new NameValueCollection();
             param.Add("OPERATION", "GETCLASSDEFINITION");
             param.Add("VERSION", "1.0.0");
             param.Add("SESSION", m_sessionID);
@@ -1532,7 +1587,7 @@
             if (!string.IsNullOrEmpty(schemaName))
                 param.Add("SCHEMA", schemaName);
             param.Add("CLASSNAME", className);
-
+            */
             return m_hosturi + "?" + EncodeParameters(param);
         }
 
@@ -1550,6 +1605,26 @@
             return m_hosturi + "?" + EncodeParameters(param);
         }
 
+        internal string GetDynamicMapOverlayImage(string mapname, string selectionXml, string format, Color selectionColor, int behavior)
+        {
+            NameValueCollection param = new NameValueCollection();
+            param.Add("OPERATION", "GETDYNAMICMAPOVERLAYIMAGE");
+            param.Add("VERSION", "2.1.0");
+            param.Add("SESSION", m_sessionID);
+            param.Add("MAPNAME", mapname);
+            param.Add("CLIENTAGENT", m_userAgent);
+            param.Add("SELECTIONCOLOR", Utility.SerializeHTMLColorRGBA(selectionColor, true));
+            param.Add("BEHAVIOR", behavior.ToString(CultureInfo.InvariantCulture));
+
+            if (format != null && format.Length != 0)
+                param.Add("FORMAT", format);
+
+            if (!string.IsNullOrEmpty(selectionXml))
+                param.Add("SELECTION", selectionXml);
+
+            return m_hosturi + "?" + EncodeParameters(param);
+        }
+
         internal System.Net.WebRequest GetDynamicMapOverlayImage(string mapname, string selectionXml, string format, System.IO.Stream outStream)
         {
             NameValueCollection param = new NameValueCollection();

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs	2012-06-01 09:04:06 UTC (rev 6726)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeConnection.cs	2012-06-01 17:26:06 UTC (rev 6727)
@@ -181,9 +181,12 @@
             }
         }
 
-        private void LogMethodCall(string method, bool success, params string[] values)
+        private void LogMethodCall(string method, bool success, params object[] values)
         {
-            OnRequestDispatched(method + "(" + string.Join(", ", values) + ") " + ((success) ? "Success" : "Failure"));
+            string[] strValues = new string[values.Length];
+            for (int i = 0; i < values.Length; i++)
+                strValues[i] = values[i].ToString();
+            OnRequestDispatched(method + "(" + string.Join(", ", strValues) + ") " + ((success) ? "Success" : "Failure"));
         }
 
 		public override ResourceList GetRepositoryResources(string startingpoint, string type, int depth, bool computeChildren)
@@ -608,6 +611,28 @@
             return result;
         }
 
+        public override Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, Color selectionColor, int behaviour)
+        {
+            MgRenderingService rnd = this.Connection.CreateService(MgServiceType.RenderingService) as MgRenderingService;
+            MgResourceService res = this.Connection.CreateService(MgServiceType.ResourceService) as MgResourceService;
+
+            MgMap mmap = new MgMap();
+            mmap.Open(res, map.Name);
+            MgSelection sel = new MgSelection(mmap);
+            if (selection != null)
+                sel.FromXml(selection.ToXml());
+
+            var rndOpts = new MgRenderingOptions(format, behaviour, new MgColor(selectionColor));
+
+            LogMethodCall("MgRenderingService::RenderDynamicOverlay", true, "MgMap", "MgSelection", "MgRenderingOptions");
+
+            GetByteReaderMethod fetch = () =>
+            {
+                return rnd.RenderDynamicOverlay(mmap, sel, rndOpts);
+            };
+            return new MgReadOnlyStream(fetch);
+        }
+
         public override Stream RenderDynamicOverlay(RuntimeMap map, MapSelection selection, string format, bool keepSelection)
         {
             MgRenderingService rnd = this.Connection.CreateService(MgServiceType.RenderingService) as MgRenderingService;
@@ -1228,7 +1253,7 @@
             return res;
         }
 
-        public override string QueryMapFeatures(string runtimeMapName, string wkt, bool persist, QueryMapFeaturesLayerAttributes attributes, bool raw)
+        public override string QueryMapFeatures(string runtimeMapName, int maxFeatures, string wkt, bool persist, string selectionVariant, QueryMapOptions extraOptions)
         {
             MgRenderingService rs = this.Connection.CreateService(MgServiceType.RenderingService) as MgRenderingService;
             MgResourceService res = this.Connection.CreateService(MgServiceType.ResourceService) as MgResourceService;
@@ -1237,26 +1262,73 @@
             map.Open(res, mapname);
 
             MgWktReaderWriter r = new MgWktReaderWriter();
-            MgFeatureInformation info = rs.QueryFeatures(map, null, r.Read(wkt), (int)MgFeatureSpatialOperations.Intersects, "", -1, (int)attributes);
+            MgStringCollection layerNames = null;
+            string featureFilter = "";
+            int layerAttributeFilter = 0;
+            int op = MgFeatureSpatialOperations.Intersects;
+            if (selectionVariant == "TOUCHES")
+                op = MgFeatureSpatialOperations.Touches;
+            else if (selectionVariant == "INTERSECTS")
+                op = MgFeatureSpatialOperations.Intersects;
+            else if (selectionVariant == "WITHIN")
+                op = MgFeatureSpatialOperations.Within;
+            else if (selectionVariant == "ENVELOPEINTERSECTS")
+                op = MgFeatureSpatialOperations.EnvelopeIntersects;
+            else
+                throw new ArgumentException("Unknown or unsupported selection variant: " + selectionVariant);
 
-            using (var ms = new MemoryStream())
+            if (extraOptions != null)
             {
-                using (var stream = Utility.MgStreamToNetStream(info, info.GetType().GetMethod("ToXml"), null))
+                if (!string.IsNullOrEmpty(extraOptions.FeatureFilter))
+                    featureFilter = extraOptions.FeatureFilter;
+                if (extraOptions.LayerNames != null && extraOptions.LayerNames.Length > 0)
                 {
-                    MaestroAPI.Utility.CopyStream(stream, ms);
-                    ms.Position = 0L;
+                    layerNames = new MgStringCollection();
+                    foreach (var name in extraOptions.LayerNames)
+                        layerNames.Add(name);
+                }
+                layerAttributeFilter = (int)extraOptions.LayerAttributeFilter;
+            }
 
-                    string xml = System.Text.Encoding.UTF8.GetString(ms.ToArray()).Trim();
+            MgFeatureInformation info = rs.QueryFeatures(map, layerNames, r.Read(wkt), op, featureFilter, maxFeatures, layerAttributeFilter);
 
-                    if (persist)
-                    {
-                        MgSelection sel = new MgSelection(map, xml);
-                        sel.Save(res, mapname);
-                    }
+            string xml = "";
+            GetByteReaderMethod fetch = () => { return info.ToXml(); };
+            using (var sr = new StreamReader(new MgReadOnlyStream(fetch)))
+            {
+                xml = sr.ReadToEnd();
+            }
+            MgSelection sel = new MgSelection(map, xml);
+            sel.Save(res, mapname);
 
-                    return xml;
-                }
+            LogMethodCall("QueryMapFeatures", true, runtimeMapName, wkt, persist, selectionVariant, extraOptions == null ? "null" : "QueryMapOptions");
+
+            return xml;
+        }
+
+        public override string QueryMapFeatures(string runtimeMapName, string wkt, bool persist, QueryMapFeaturesLayerAttributes attributes, bool raw)
+        {
+            MgRenderingService rs = this.Connection.CreateService(MgServiceType.RenderingService) as MgRenderingService;
+            MgResourceService res = this.Connection.CreateService(MgServiceType.ResourceService) as MgResourceService;
+            MgMap map = new MgMap();
+            string mapname = runtimeMapName.IndexOf(":") > 0 ? new ResourceIdentifier(runtimeMapName).Path : runtimeMapName;
+            map.Open(res, mapname);
+
+            MgWktReaderWriter r = new MgWktReaderWriter();
+            MgFeatureInformation info = rs.QueryFeatures(map, null, r.Read(wkt), (int)MgFeatureSpatialOperations.Intersects, "", -1, (int)attributes);
+
+            string xml = "";
+            GetByteReaderMethod fetch = () => { return info.ToXml(); };
+            using (var sr = new StreamReader(new MgReadOnlyStream(fetch)))
+            {
+                xml = sr.ReadToEnd();
             }
+            MgSelection sel = new MgSelection(map, xml);
+            sel.Save(res, mapname);
+
+            LogMethodCall("QueryMapFeatures", true, runtimeMapName, wkt, persist, (int)attributes, raw);
+
+            return xml;
         }
 
         internal void InsertFeatures(MgResourceIdentifier fsId, string className, MgPropertyCollection props)



More information about the mapguide-commits mailing list