[mapguide-commits] r6228 - in trunk/Tools/Maestro: MaestroAPITests
OSGeo.MapGuide.MaestroAPI OSGeo.MapGuide.MaestroAPI/Exceptions
OSGeo.MapGuide.MaestroAPI/Mapping
OSGeo.MapGuide.MaestroAPI/Properties
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Nov 16 08:48:35 EST 2011
Author: jng
Date: 2011-11-16 05:48:35 -0800 (Wed, 16 Nov 2011)
New Revision: 6228
Added:
trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Exceptions/DuplicateKeyException.cs
trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs
Modified:
trunk/Tools/Maestro/MaestroAPITests/RuntimeMapTests.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/OSGeo.MapGuide.MaestroAPI.csproj
trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs
trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx
Log:
#1852: Have runtime layers and groups as specialized collections. This provides the intuitive API that we had in Maestro 2.1. New unit tests have been added to verify that all add/insertion operations produce the correct draw orders. A whole load of existing RuntimeMap methods have been flagged with the Obsolete attribute and will be slated for removal with the next post-4.0 release.
Also, the RuntimeMap now has a CurrentConnection property, just like it did in 2.1
Modified: trunk/Tools/Maestro/MaestroAPITests/RuntimeMapTests.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/RuntimeMapTests.cs 2011-11-16 01:45:28 UTC (rev 6227)
+++ trunk/Tools/Maestro/MaestroAPITests/RuntimeMapTests.cs 2011-11-16 13:48:35 UTC (rev 6228)
@@ -38,6 +38,7 @@
using OSGeo.MapGuide.MaestroAPI.CoordinateSystem;
using System.Drawing;
using OSGeo.MapGuide.ExtendedObjectModels;
+ using OSGeo.MapGuide.ObjectModels.LayerDefinition;
[SetUpFixture]
public class TestBootstrap
@@ -143,8 +144,8 @@
private bool Matches(RuntimeMap map, IMapDefinition mdf)
{
if (map.MapDefinition != mdf.ResourceID) return false;
- if (map.Groups.Length != mdf.GetGroupCount()) return false;
- if (map.Layers.Length != mdf.GetLayerCount()) return false;
+ if (map.Groups.Count != mdf.GetGroupCount()) return false;
+ if (map.Layers.Count != mdf.GetLayerCount()) return false;
foreach (var layer in map.Layers)
{
@@ -614,6 +615,252 @@
RenderLegendAndVerifyConvenience(map, 200, 600, "TestLegend12kConvenience_RailReAdded.png", "PNG");
}
+ public virtual void TestMapManipulation2()
+ {
+ //This is mainly to exercise Insert() and to verify that draw orders come back as expected
+
+ var resSvc = _conn.ResourceService;
+ var mapSvc = _conn.GetService((int)ServiceType.Mapping) as IMappingService;
+ Assert.NotNull(mapSvc);
+
+ var mdf = resSvc.GetResource("Library://UnitTests/Maps/Sheboygan.MapDefinition") as IMapDefinition;
+ Assert.NotNull(mdf);
+
+ //FIXME: We have a problem. Can we calculate this value without MgCoordinateSystem and just using the WKT?
+ //The answer to this will answer whether we can actually support the Rendering Service API over http
+ //using pure client-side runtime maps
+ //
+ //The hard-coded value here was the output of MgCoordinateSystem.ConvertCoordinateSystemUnitsToMeters(1.0)
+ //for this particular map.
+ double metersPerUnit = 111319.490793274;
+ var cs = CoordinateSystemBase.Create(mdf.CoordinateSystem);
+ metersPerUnit = cs.MetersPerUnitX;
+ Trace.TraceInformation("Using MPU of: {0}", metersPerUnit);
+
+ //Empty the layer/group list because we will add them individually
+ var removeLayers = new List<IMapLayer>(mdf.MapLayer);
+ foreach (var removeMe in removeLayers)
+ mdf.RemoveLayer(removeMe);
+
+ var removeGroups = new List<IMapLayerGroup>(mdf.MapLayerGroup);
+ foreach (var removeMe in removeGroups)
+ mdf.RemoveGroup(removeMe);
+
+ //Now create our runtime map
+ var mid = "Session:" + _conn.SessionID + "//TestMapManipulation2.Map";
+ var map = mapSvc.CreateMap(mid, mdf, metersPerUnit);
+ map.ViewScale = 12000;
+ map.DisplayWidth = 1024;
+ map.DisplayHeight = 1024;
+ map.DisplayDpi = 96;
+
+ Assert.AreEqual(0, map.Layers.Count);
+ Assert.AreEqual(0, map.Groups.Count);
+
+ map.Groups.Add(new RuntimeMapGroup(map, "Group1"));
+ map.Groups.Add(new RuntimeMapGroup(map, "Group2"));
+ Assert.AreEqual(2, map.Groups.Count);
+
+ Assert.NotNull(map.Groups["Group1"]);
+ Assert.NotNull(map.Groups["Group2"]);
+ Assert.Null(map.Groups["Group3"]);
+
+ var layer = new RuntimeMapLayer(map, (ILayerDefinition)resSvc.GetResource("Library://UnitTests/Layers/HydrographicPolygons.LayerDefinition"));
+ layer.Group = "Group1";
+
+ map.Layers.Insert(0, layer);
+ Assert.AreEqual(1, map.Layers.Count);
+ Assert.NotNull(map.Layers["HydrographicPolygons"]);
+ Assert.True(map.Layers["HydrographicPolygons"] == map.Layers[0]);
+ Assert.NotNull(map.Layers.GetByObjectId(layer.ObjectId));
+
+ var layer2 = new RuntimeMapLayer(map, (ILayerDefinition)resSvc.GetResource("Library://UnitTests/Layers/Parcels.LayerDefinition"));
+ map.Layers.Insert(0, layer2);
+ layer2.Group = "Group1"; //Intentional
+
+ Assert.AreEqual(2, map.Layers.Count);
+ Assert.True(layer2 == map.Layers[0]);
+ Assert.False(layer2 == map.Layers[1]);
+ Assert.NotNull(map.Layers["HydrographicPolygons"]);
+ Assert.NotNull(map.Layers["Parcels"]);
+ Assert.True(map.Layers["Parcels"] == map.Layers[0]);
+ Assert.True(map.Layers["HydrographicPolygons"] == map.Layers[1]);
+ Assert.NotNull(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer2.ObjectId));
+ //The important one
+ Assert.True(map.Layers[0].DisplayOrder < map.Layers[1].DisplayOrder);
+
+ var layer3 = new RuntimeMapLayer(map, (ILayerDefinition)resSvc.GetResource("Library://UnitTests/Layers/Rail.LayerDefinition"));
+ layer3.Group = "Group2";
+ map.Layers.Insert(0, layer3);
+ Assert.AreEqual(3, map.Layers.Count);
+ Assert.True(layer3 == map.Layers[0]);
+ Assert.False(layer3 == map.Layers[1]);
+ Assert.False(layer3 == map.Layers[2]);
+ Assert.NotNull(map.Layers["HydrographicPolygons"]);
+ Assert.NotNull(map.Layers["Parcels"]);
+ Assert.NotNull(map.Layers["Rail"]);
+ Assert.True(map.Layers["Rail"] == map.Layers[0]);
+ Assert.True(map.Layers["Parcels"] == map.Layers[1]);
+ Assert.True(map.Layers["HydrographicPolygons"] == map.Layers[2]);
+ //The important one
+ Assert.True(map.Layers[0].DisplayOrder < map.Layers[1].DisplayOrder);
+ Assert.True(map.Layers[0].DisplayOrder < map.Layers[2].DisplayOrder);
+ Assert.True(map.Layers[1].DisplayOrder < map.Layers[2].DisplayOrder);
+ Assert.NotNull(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer2.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer3.ObjectId));
+
+ Assert.AreEqual(2, map.GetLayersOfGroup("Group1").Length);
+ Assert.AreEqual(1, map.GetLayersOfGroup("Group2").Length);
+
+ //Group1 has 2 layers
+ map.Groups.Remove("Group1");
+ Assert.AreEqual(1, map.Layers.Count);
+ Assert.Null(map.Groups["Group1"]);
+ Assert.True(map.Groups["Group2"] == map.Groups[0]);
+ Assert.Null(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.Null(map.Layers.GetByObjectId(layer2.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer3.ObjectId));
+
+ //Removing layer doesn't affect its group. It will still be there
+ map.Layers.Remove(layer3.Name);
+ Assert.AreEqual(0, map.Layers.Count);
+ Assert.AreEqual(1, map.Groups.Count);
+ Assert.NotNull(map.Groups["Group2"]);
+ Assert.Null(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.Null(map.Layers.GetByObjectId(layer2.ObjectId));
+ Assert.Null(map.Layers.GetByObjectId(layer3.ObjectId));
+
+ map.Groups.Remove("Group2");
+ Assert.AreEqual(0, map.Layers.Count);
+ Assert.AreEqual(0, map.Groups.Count);
+ }
+
+ public virtual void TestMapManipulation3()
+ {
+ //Pretty much the same as TestMapManipulation2() but with Add() instead of Insert()
+ //Add() puts the item at the end of the collection, so draw orders should reflect
+ //that
+
+ var resSvc = _conn.ResourceService;
+ var mapSvc = _conn.GetService((int)ServiceType.Mapping) as IMappingService;
+ Assert.NotNull(mapSvc);
+
+ var mdf = resSvc.GetResource("Library://UnitTests/Maps/Sheboygan.MapDefinition") as IMapDefinition;
+ Assert.NotNull(mdf);
+
+ //FIXME: We have a problem. Can we calculate this value without MgCoordinateSystem and just using the WKT?
+ //The answer to this will answer whether we can actually support the Rendering Service API over http
+ //using pure client-side runtime maps
+ //
+ //The hard-coded value here was the output of MgCoordinateSystem.ConvertCoordinateSystemUnitsToMeters(1.0)
+ //for this particular map.
+ double metersPerUnit = 111319.490793274;
+ var cs = CoordinateSystemBase.Create(mdf.CoordinateSystem);
+ metersPerUnit = cs.MetersPerUnitX;
+ Trace.TraceInformation("Using MPU of: {0}", metersPerUnit);
+
+ //Empty the layer/group list because we will add them individually
+ var removeLayers = new List<IMapLayer>(mdf.MapLayer);
+ foreach (var removeMe in removeLayers)
+ mdf.RemoveLayer(removeMe);
+
+ var removeGroups = new List<IMapLayerGroup>(mdf.MapLayerGroup);
+ foreach (var removeMe in removeGroups)
+ mdf.RemoveGroup(removeMe);
+
+ //Now create our runtime map
+ var mid = "Session:" + _conn.SessionID + "//TestMapManipulation2.Map";
+ var map = mapSvc.CreateMap(mid, mdf, metersPerUnit);
+ map.ViewScale = 12000;
+ map.DisplayWidth = 1024;
+ map.DisplayHeight = 1024;
+ map.DisplayDpi = 96;
+
+ Assert.AreEqual(0, map.Layers.Count);
+ Assert.AreEqual(0, map.Groups.Count);
+
+ map.Groups.Add(new RuntimeMapGroup(map, "Group1"));
+ map.Groups.Add(new RuntimeMapGroup(map, "Group2"));
+ Assert.AreEqual(2, map.Groups.Count);
+
+ Assert.NotNull(map.Groups["Group1"]);
+ Assert.NotNull(map.Groups["Group2"]);
+ Assert.Null(map.Groups["Group3"]);
+
+ var layer = new RuntimeMapLayer(map, (ILayerDefinition)resSvc.GetResource("Library://UnitTests/Layers/HydrographicPolygons.LayerDefinition"));
+ layer.Group = "Group1";
+
+ map.Layers.Add(layer);
+ Assert.AreEqual(1, map.Layers.Count);
+ Assert.NotNull(map.Layers["HydrographicPolygons"]);
+ Assert.True(map.Layers["HydrographicPolygons"] == map.Layers[0]);
+ Assert.NotNull(map.Layers.GetByObjectId(layer.ObjectId));
+
+ var layer2 = new RuntimeMapLayer(map, (ILayerDefinition)resSvc.GetResource("Library://UnitTests/Layers/Parcels.LayerDefinition"));
+ map.Layers.Add(layer2);
+ layer2.Group = "Group1"; //Intentional
+
+ Assert.AreEqual(2, map.Layers.Count);
+ Assert.False(layer2 == map.Layers[0]);
+ Assert.True(layer2 == map.Layers[1]);
+ Assert.NotNull(map.Layers["HydrographicPolygons"]);
+ Assert.NotNull(map.Layers["Parcels"]);
+ Assert.True(map.Layers["HydrographicPolygons"] == map.Layers[0]);
+ Assert.True(map.Layers["Parcels"] == map.Layers[1]);
+ Assert.NotNull(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer2.ObjectId));
+ //The important one
+ Assert.True(map.Layers[0].DisplayOrder < map.Layers[1].DisplayOrder);
+
+ var layer3 = new RuntimeMapLayer(map, (ILayerDefinition)resSvc.GetResource("Library://UnitTests/Layers/Rail.LayerDefinition"));
+ layer3.Group = "Group2";
+ map.Layers.Add(layer3);
+ Assert.AreEqual(3, map.Layers.Count);
+ Assert.False(layer3 == map.Layers[0]);
+ Assert.False(layer3 == map.Layers[1]);
+ Assert.True(layer3 == map.Layers[2]);
+ Assert.NotNull(map.Layers["HydrographicPolygons"]);
+ Assert.NotNull(map.Layers["Parcels"]);
+ Assert.NotNull(map.Layers["Rail"]);
+ Assert.True(map.Layers["HydrographicPolygons"] == map.Layers[0]);
+ Assert.True(map.Layers["Parcels"] == map.Layers[1]);
+ Assert.True(map.Layers["Rail"] == map.Layers[2]);
+ //The important one
+ Assert.True(map.Layers[0].DisplayOrder < map.Layers[1].DisplayOrder);
+ Assert.True(map.Layers[0].DisplayOrder < map.Layers[2].DisplayOrder);
+ Assert.True(map.Layers[1].DisplayOrder < map.Layers[2].DisplayOrder);
+ Assert.NotNull(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer2.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer3.ObjectId));
+
+ Assert.AreEqual(2, map.GetLayersOfGroup("Group1").Length);
+ Assert.AreEqual(1, map.GetLayersOfGroup("Group2").Length);
+
+ //Group1 has 2 layers
+ map.Groups.Remove("Group1");
+ Assert.AreEqual(1, map.Layers.Count);
+ Assert.Null(map.Groups["Group1"]);
+ Assert.True(map.Groups["Group2"] == map.Groups[0]);
+ Assert.Null(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.Null(map.Layers.GetByObjectId(layer2.ObjectId));
+ Assert.NotNull(map.Layers.GetByObjectId(layer3.ObjectId));
+
+ //Removing layer doesn't affect its group. It will still be there
+ map.Layers.Remove(layer3.Name);
+ Assert.AreEqual(0, map.Layers.Count);
+ Assert.AreEqual(1, map.Groups.Count);
+ Assert.NotNull(map.Groups["Group2"]);
+ Assert.Null(map.Layers.GetByObjectId(layer.ObjectId));
+ Assert.Null(map.Layers.GetByObjectId(layer2.ObjectId));
+ Assert.Null(map.Layers.GetByObjectId(layer3.ObjectId));
+
+ map.Groups.Remove("Group2");
+ Assert.AreEqual(0, map.Layers.Count);
+ Assert.AreEqual(0, map.Groups.Count);
+ }
+
public virtual void TestResourceEvents()
{
bool deleteCalled = false;
@@ -748,6 +995,18 @@
}
[Test]
+ public override void TestMapManipulation2()
+ {
+ base.TestMapManipulation2();
+ }
+
+ [Test]
+ public override void TestMapManipulation3()
+ {
+ base.TestMapManipulation3();
+ }
+
+ [Test]
public override void TestLargeMapCreatePerformance()
{
base.TestLargeMapCreatePerformance();
@@ -802,6 +1061,18 @@
}
[Test]
+ public override void TestMapManipulation2()
+ {
+ base.TestMapManipulation2();
+ }
+
+ [Test]
+ public override void TestMapManipulation3()
+ {
+ base.TestMapManipulation3();
+ }
+
+ [Test]
public override void TestLargeMapCreatePerformance()
{
base.TestLargeMapCreatePerformance();
Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Exceptions/DuplicateKeyException.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Exceptions/DuplicateKeyException.cs (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Exceptions/DuplicateKeyException.cs 2011-11-16 13:48:35 UTC (rev 6228)
@@ -0,0 +1,71 @@
+#region Disclaimer / License
+// Copyright (C) 2011, 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;
+
+namespace OSGeo.MapGuide.MaestroAPI.Exceptions
+{
+ /// <summary>
+ /// Raised when an item with an pre-existing key is being added to a collection
+ /// </summary>
+ [global::System.Serializable]
+ public class DuplicateKeyException : Exception
+ {
+ //
+ // For guidelines regarding the creation of new exception types, see
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
+ // and
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
+ //
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DuplicateKeyException"/> class.
+ /// </summary>
+ public DuplicateKeyException() { }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DuplicateKeyException"/> class.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ public DuplicateKeyException(string message) : base(message) { }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DuplicateKeyException"/> class.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <param name="inner">The inner.</param>
+ public DuplicateKeyException(string message, Exception inner) : base(message, inner) { }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DuplicateKeyException"/> class.
+ /// </summary>
+ /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="info"/> parameter is null.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.Runtime.Serialization.SerializationException">
+ /// The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0).
+ /// </exception>
+ protected DuplicateKeyException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context)
+ : base(info, context) { }
+ }
+}
Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/Collections.cs 2011-11-16 13:48:35 UTC (rev 6228)
@@ -0,0 +1,557 @@
+#region Disclaimer / License
+// Copyright (C) 2011, 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 OSGeo.MapGuide.MaestroAPI.Exceptions;
+
+namespace OSGeo.MapGuide.MaestroAPI.Mapping
+{
+ /// <summary>
+ /// A generic key/value collection
+ /// </summary>
+ /// <typeparam name="TKey">The type of the key.</typeparam>
+ /// <typeparam name="TVal">The type of the value.</typeparam>
+ public abstract class KeyValueCollection<TKey, TVal> : IList<TVal> where TVal : class
+ {
+ /// <summary>
+ /// The internal list of value
+ /// </summary>
+ protected List<TVal> _values;
+ /// <summary>
+ /// The internal dictionary of values keyed by its key
+ /// </summary>
+ protected Dictionary<TKey, TVal> _valuesByKey;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="KeyValueCollection<TKey, TVal>"/> class.
+ /// </summary>
+ protected KeyValueCollection()
+ {
+ _values = new List<TVal>();
+ _valuesByKey = new Dictionary<TKey, TVal>();
+ }
+
+ /// <summary>
+ /// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </summary>
+ /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
+ /// <returns>
+ /// The index of <paramref name="item"/> if found in the list; otherwise, -1.
+ /// </returns>
+ public int IndexOf(TVal item)
+ {
+ return _values.IndexOf(item);
+ }
+
+ /// <summary>
+ /// Inserts an item to the <see cref="T:System.Collections.Generic.IList`1"/> at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ /// <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.NotSupportedException">
+ /// The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public virtual void Insert(int index, TVal item)
+ {
+ var key = SelectKey(item);
+ if (_valuesByKey.ContainsKey(key))
+ throw new DuplicateKeyException(string.Format(Properties.Resources.DuplicateKeyExceptionMessage, key));
+
+ OnBeforeItemAdded(item);
+ _values.Insert(index, item);
+ _valuesByKey.Add(key, item);
+ OnItemAdded(item);
+ }
+
+ /// <summary>
+ /// Removes the <see cref="T:System.Collections.Generic.IList`1"/> item at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index of the item to remove.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.NotSupportedException">
+ /// The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public void RemoveAt(int index)
+ {
+ var item = this[index];
+ OnBeforeItemRemove(item);
+ _values.RemoveAt(index);
+
+ if (item != null)
+ {
+ var key = SelectKey(item);
+ _valuesByKey.Remove(key);
+
+ OnItemRemoved(item);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the element at the specified index.
+ /// </summary>
+ /// <returns>
+ /// The element at the specified index.
+ /// </returns>
+ ///
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.NotSupportedException">
+ /// The property is set and the <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public virtual TVal this[int index]
+ {
+ get
+ {
+ return _values[index];
+ }
+ set
+ {
+ if (_values[index] != null)
+ RemoveAt(index);
+ _values[index] = value;
+ }
+ }
+
+ /// <summary>
+ /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
+ /// <exception cref="T:System.NotSupportedException">
+ /// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </exception>
+ public virtual void Add(TVal item)
+ {
+ var key = SelectKey(item);
+ if (_valuesByKey.ContainsKey(key))
+ throw new DuplicateKeyException(string.Format(Properties.Resources.DuplicateKeyExceptionMessage, key));
+
+ OnBeforeItemAdded(item);
+ _values.Add(item);
+ _valuesByKey.Add(key, item);
+ OnItemAdded(item);
+ }
+
+ /// <summary>
+ /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <exception cref="T:System.NotSupportedException">
+ /// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </exception>
+ public virtual void Clear()
+ {
+ //We don't call Clear() directly because we need to propagate removal of each
+ //item back to the map
+ var items = new List<TVal>(this);
+ foreach (var item in items)
+ {
+ Remove(item);
+ }
+ //This shouldn't happen
+ if (_values.Count > 0)
+ {
+ System.Diagnostics.Trace.TraceWarning("Expected empty values collection!");
+ _values.Clear();
+ }
+ if (_valuesByKey.Count > 0)
+ {
+ System.Diagnostics.Trace.TraceWarning("Expected empty values collection!");
+ _valuesByKey.Clear();
+ }
+ }
+
+ /// <summary>
+ /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
+ /// </summary>
+ /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
+ /// <returns>
+ /// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
+ /// </returns>
+ public bool Contains(TVal item)
+ {
+ return _values.Contains(item);
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
+ /// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// <paramref name="array"/> is null.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="arrayIndex"/> is less than 0.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.ArgumentException">
+ /// <paramref name="array"/> is multidimensional.
+ /// -or-
+ /// <paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.
+ /// -or-
+ /// The number of elements in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.
+ /// -or-
+ /// Type <paramref name="T"/> cannot be cast automatically to the type of the destination <paramref name="array"/>.
+ /// </exception>
+ public void CopyTo(TVal[] array, int arrayIndex)
+ {
+ _values.CopyTo(array, arrayIndex);
+ }
+
+ /// <summary>
+ /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <returns>
+ /// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </returns>
+ public int Count
+ {
+ get { return _values.Count; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </summary>
+ /// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
+ /// </returns>
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </summary>
+ /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
+ /// <returns>
+ /// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
+ /// </returns>
+ /// <exception cref="T:System.NotSupportedException">
+ /// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
+ /// </exception>
+ public bool Remove(TVal item)
+ {
+ OnBeforeItemRemove(item);
+ var ret = _values.Remove(item);
+ if (ret)
+ {
+ var key = SelectKey(item);
+ _valuesByKey.Remove(key);
+
+ OnItemRemoved(item);
+ return ret;
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through the collection.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
+ /// </returns>
+ public IEnumerator<TVal> GetEnumerator()
+ {
+ return _values.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through a collection.
+ /// </summary>
+ /// <returns>
+ /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
+ /// </returns>
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return _values.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Gets or sets the element at the specified index.
+ /// </summary>
+ /// <returns>
+ /// The element at the specified index.
+ /// </returns>
+ ///
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.NotSupportedException">
+ /// The property is set and the <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public TVal this[TKey key]
+ {
+ get { return _valuesByKey.ContainsKey(key) ? _valuesByKey[key] : null; }
+ set { _valuesByKey[key] = value; }
+ }
+
+ /// <summary>
+ /// Called before an item is added
+ /// </summary>
+ /// <param name="item">The item.</param>
+ protected virtual void OnBeforeItemAdded(TVal item) { }
+
+ /// <summary>
+ /// Called before an item is removed
+ /// </summary>
+ /// <param name="item">The item.</param>
+ protected virtual void OnBeforeItemRemove(TVal item) { }
+
+ /// <summary>
+ /// Called after an item has been added
+ /// </summary>
+ /// <param name="item">The item.</param>
+ protected abstract void OnItemAdded(TVal item);
+
+ /// <summary>
+ /// Called after an item has been removed. Note this is only called if the remove
+ /// operation removed the item in question
+ /// </summary>
+ /// <param name="value">The value.</param>
+ protected abstract void OnItemRemoved(TVal value);
+
+ /// <summary>
+ /// Selects the key given the value.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns></returns>
+ protected abstract TKey SelectKey(TVal value);
+ }
+
+ /// <summary>
+ /// A collection of runtime map layers
+ /// </summary>
+ public class RuntimeMapLayerCollection : KeyValueCollection<string, RuntimeMapLayer>
+ {
+ private RuntimeMap _parent;
+
+ private Dictionary<string, RuntimeMapLayer> _layerIdMap;
+
+ internal RuntimeMapLayerCollection(RuntimeMap parent)
+ {
+ _parent = parent;
+ _layerIdMap = new Dictionary<string, RuntimeMapLayer>();
+ }
+
+ /// <summary>
+ /// Adds the specified layer.
+ /// </summary>
+ /// <param name="layer">The layer.</param>
+ public override void Add(RuntimeMapLayer layer)
+ {
+ //calculate and set the zorder for the new layer
+ RuntimeMapLayer prevLayer = (this.Count == 0) ? null : this[this.Count - 1];
+ double zOrder = prevLayer == null ? RuntimeMap.Z_ORDER_TOP : prevLayer.DisplayOrder + RuntimeMap.Z_ORDER_INCREMENT;
+ layer.DisplayOrder = zOrder;
+
+ base.Add(layer);
+ }
+
+ /// <summary>
+ /// Inserts an item to the <see cref="T:System.Collections.Generic.IList`1"/> at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+ /// <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.NotSupportedException">
+ /// The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public override void Insert(int index, RuntimeMapLayer item)
+ {
+ CalculateDisplayOrder(index, item);
+ base.Insert(index, item);
+ }
+
+ /// <summary>
+ /// Called when [before item added].
+ /// </summary>
+ /// <param name="layer">The layer.</param>
+ protected override void OnBeforeItemAdded(RuntimeMapLayer layer)
+ {
+ if (_layerIdMap.ContainsKey(layer.ObjectId))
+ throw new DuplicateKeyException(string.Format(Properties.Resources.DuplicateKeyExceptionMessage, layer.ObjectId));
+ }
+
+ /// <summary>
+ /// Called when [item added].
+ /// </summary>
+ /// <param name="layer">The layer.</param>
+ protected override void OnItemAdded(RuntimeMapLayer layer)
+ {
+ _layerIdMap[layer.ObjectId] = layer;
+ _parent.OnLayerAdded(layer);
+ }
+
+ /// <summary>
+ /// Called when [item removed].
+ /// </summary>
+ /// <param name="layer">The layer.</param>
+ protected override void OnItemRemoved(RuntimeMapLayer layer)
+ {
+ if (_layerIdMap.ContainsKey(layer.ObjectId))
+ _layerIdMap.Remove(layer.ObjectId);
+ _parent.OnLayerRemoved(layer);
+ }
+
+ /// <summary>
+ /// Selects the key given the value.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns></returns>
+ protected override string SelectKey(RuntimeMapLayer value)
+ {
+ return value.Name;
+ }
+
+ internal RuntimeMapLayer GetByObjectId(string id)
+ {
+ return _layerIdMap.ContainsKey(id) ? _layerIdMap[id] : null;
+ }
+
+ /// <summary>
+ /// Gets or sets the element at the specified index.
+ /// </summary>
+ /// <returns>
+ /// The element at the specified index.
+ /// </returns>
+ ///
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.
+ /// </exception>
+ ///
+ /// <exception cref="T:System.NotSupportedException">
+ /// The property is set and the <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
+ /// </exception>
+ public override RuntimeMapLayer this[int index]
+ {
+ get
+ {
+ return base[index];
+ }
+ set
+ {
+ CalculateDisplayOrder(index, value);
+ base[index] = value;
+ }
+ }
+
+ /// <summary>
+ /// Removes the specified layer by its name.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ public void Remove(string name)
+ {
+ var layer = this[name];
+ if (layer != null)
+ Remove(layer);
+ }
+
+ private void CalculateDisplayOrder(int index, RuntimeMapLayer value)
+ {
+ //calculate zorder for the new layer
+ double zOrderLow, zOrderHigh;
+ RuntimeMapLayer layer;
+ if (index == 0)
+ {
+ zOrderLow = 0;
+ layer = base.Count > 0 ? base[index] : null;
+ if (layer != null)
+ zOrderHigh = layer.DisplayOrder;
+ else
+ zOrderHigh = 2.0 * RuntimeMap.Z_ORDER_INCREMENT;
+ }
+ else
+ {
+ layer = base[index - 1];
+ zOrderLow = layer.DisplayOrder;
+ layer = base.Count > index ? base[index] : null;
+ zOrderHigh = layer != null ? layer.DisplayOrder : zOrderLow + 2.0 * RuntimeMap.Z_ORDER_INCREMENT;
+ }
+ value.DisplayOrder = (zOrderLow + (zOrderHigh - zOrderLow) / 2.0);
+ }
+ }
+
+ /// <summary>
+ /// A collection of runtime map groups
+ /// </summary>
+ public class RuntimeMapGroupCollection : KeyValueCollection<string, RuntimeMapGroup>
+ {
+ private RuntimeMap _parent;
+
+ internal RuntimeMapGroupCollection(RuntimeMap parent)
+ {
+ _parent = parent;
+ }
+
+ /// <summary>
+ /// Called after an item has been added
+ /// </summary>
+ /// <param name="item">The item.</param>
+ protected override void OnItemAdded(RuntimeMapGroup item)
+ {
+ _parent.OnGroupAdded(item);
+ }
+
+ /// <summary>
+ /// Called after an item has been removed. Note this is only called if the remove
+ /// operation removed the item in question
+ /// </summary>
+ /// <param name="value">The value.</param>
+ protected override void OnItemRemoved(RuntimeMapGroup value)
+ {
+ _parent.OnGroupRemoved(value);
+ }
+
+ /// <summary>
+ /// Selects the key given the value.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns></returns>
+ protected override string SelectKey(RuntimeMapGroup value)
+ {
+ return value.Name;
+ }
+
+ /// <summary>
+ /// Removes the specified group by its name.
+ /// </summary>
+ /// <param name="groupName">Name of the group.</param>
+ public void Remove(string groupName)
+ {
+ var group = this[groupName];
+ if (group != null)
+ Remove(group);
+ }
+ }
+}
Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/MapSelection.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/MapSelection.cs 2011-11-16 01:45:28 UTC (rev 6227)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/MapSelection.cs 2011-11-16 13:48:35 UTC (rev 6228)
@@ -120,7 +120,7 @@
if (n.Attributes["id"] != null)
{
string guid = n.Attributes["id"].Value;
- var l = _map.GetLayerByObjectId(guid);
+ var l = _map.Layers.GetByObjectId(guid);
if (l != null)
{
foreach (System.Xml.XmlNode c in n.SelectNodes("Class"))
Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs 2011-11-16 01:45:28 UTC (rev 6227)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Mapping/RuntimeMap.cs 2011-11-16 13:48:35 UTC (rev 6228)
@@ -30,6 +30,7 @@
using OSGeo.MapGuide.ObjectModels.LayerDefinition;
using System.Diagnostics;
using OSGeo.MapGuide.MaestroAPI.Commands;
+using OSGeo.MapGuide.MaestroAPI.Exceptions;
namespace OSGeo.MapGuide.MaestroAPI.Mapping
{
@@ -120,28 +121,15 @@
/// </example>
public class RuntimeMap : MapObservable
{
- internal IFeatureService FeatureService { get; set; }
+ internal IFeatureService FeatureService { get { return this.CurrentConnection.FeatureService; } }
- internal IResourceService ResourceService { get; set; }
+ internal IResourceService ResourceService { get { return this.CurrentConnection.ResourceService; } }
+ public IServerConnection CurrentConnection { get; private set; }
+
internal Version SiteVersion { get; private set; }
/// <summary>
- /// The layer collection
- /// </summary>
- protected List<RuntimeMapLayer> _layers;
-
- /// <summary>
- /// The group collection
- /// </summary>
- protected List<RuntimeMapGroup> _groups;
-
- /// <summary>
- /// The id to layer lookup dictionary
- /// </summary>
- protected Dictionary<string, RuntimeMapLayer> _layerIdMap;
-
- /// <summary>
/// The mapping service
/// </summary>
protected IMappingService _mapSvc;
@@ -169,8 +157,7 @@
this.ObjectId = Guid.NewGuid().ToString();
m_changeList = new Dictionary<string, ChangeList>();
_finiteDisplayScales = new double[0];
- this.ResourceService = conn.ResourceService;
- this.FeatureService = conn.FeatureService;
+ this.CurrentConnection = conn;
if (Array.IndexOf(conn.Capabilities.SupportedServices, (int)ServiceType.Mapping) >= 0)
{
_mapSvc = (IMappingService)conn.GetService((int)ServiceType.Mapping);
@@ -179,9 +166,8 @@
{
_getRes = (IGetResourceContents)conn.CreateCommand((int)CommandType.GetResourceContents);
}
- _layers = new List<RuntimeMapLayer>();
- _groups = new List<RuntimeMapGroup>();
- _layerIdMap = new Dictionary<string, RuntimeMapLayer>();
+ this.Layers = new RuntimeMapLayerCollection(this);
+ this.Groups = new RuntimeMapGroupCollection(this);
this.Selection = new MapSelection(this);
}
@@ -276,20 +262,18 @@
Trace.TraceInformation("[RuntimeMap.ctor]: {0} layers pre-cached", layerDefinitionCache.Count);
}
- int dispIndex = 0;
//Load map layers
foreach (var layer in mdf.MapLayer)
{
var rtl = new RuntimeMapLayer(this, layer, GetLayerDefinition(layer.ResourceId));
- rtl.DisplayOrder = (++dispIndex) * Z_ORDER_INCREMENT;
- AddLayerInternal(rtl);
+ this.Layers.Add(rtl);
}
//Load map groups
foreach (var group in mdf.MapLayerGroup)
{
var grp = new RuntimeMapGroup(this, group);
- _groups.Add(grp);
+ this.Groups.Add(grp);
}
//If base map specified load layers and groups there
@@ -304,12 +288,11 @@
{
var rtl = new RuntimeMapLayer(this, layer, GetLayerDefinition(layer.ResourceId)) { Visible = true };
rtl.Type = RuntimeMapLayer.kBaseMap;
- rtl.DisplayOrder = (++dispIndex) * Z_ORDER_INCREMENT;
- AddLayerInternal(rtl);
+ this.Layers.Add(rtl);
}
}
var rtg = new RuntimeMapGroup(this, group);
- _groups.Add(rtg);
+ this.Groups.Add(rtg);
}
//Init finite display scales
@@ -755,12 +738,12 @@
/// <param name="s"></param>
protected void SerializeLayerData(MgBinarySerializer s)
{
- s.Write((int)_groups.Count);
- foreach (var g in _groups)
+ s.Write((int)this.Groups.Count);
+ foreach (var g in this.Groups)
g.Serialize(s);
- s.Write(_layers.Count);
- foreach (var t in _layers)
+ s.Write(this.Layers.Count);
+ foreach (var t in this.Layers)
t.Serialize(s);
}
@@ -897,25 +880,24 @@
{
int groupCount = d.ReadInt32();
- _groups.Clear();
+ this.Groups.Clear();
for (int i = 0; i < groupCount; i++)
{
RuntimeMapGroup g = new RuntimeMapGroup();
g.Deserialize(d);
- _groups.Add(g);
+ this.Groups.Add(g);
}
int mapLayerCount = d.ReadInt32();
- _layers.Clear();
- _layerIdMap.Clear();
+ this.Layers.Clear();
while (mapLayerCount-- > 0)
{
RuntimeMapLayer t = new RuntimeMapLayer(this);
t.Deserialize(d);
- AddLayerInternal(t);
+ this.Layers.Add(t);
}
}
@@ -934,15 +916,11 @@
/// </summary>
/// <param name="name">The name.</param>
/// <returns></returns>
+ [Obsolete("Use the indexer of the Groups property instead")]
public RuntimeMapGroup GetGroupByName(string name)
{
Check.NotNull(name, "name");
- foreach (var group in _groups)
- {
- if (name.Equals(group.Name))
- return group;
- }
- return null;
+ return this.Groups[name];
}
/// <summary>
@@ -950,30 +928,28 @@
/// </summary>
/// <param name="id">The id.</param>
/// <returns></returns>
+ [Obsolete("Use the Layers property instead")]
public RuntimeMapLayer GetLayerByObjectId(string id)
{
- if (_layerIdMap.ContainsKey(id))
- return _layerIdMap[id];
-
- return null;
+ return this.Layers.GetByObjectId(id);
}
/// <summary>
- /// Gets an array of all layers in this map
+ /// The collection of layers in this map
/// </summary>
- /// <value>The layers.</value>
- public RuntimeMapLayer[] Layers
+ public RuntimeMapLayerCollection Layers
{
- get { return _layers.ToArray(); }
+ get;
+ private set;
}
/// <summary>
- /// Gets an array of all groups in this map
+ /// The collection of groups in this map
/// </summary>
- /// <value>The groups.</value>
- public RuntimeMapGroup[] Groups
+ public RuntimeMapGroupCollection Groups
{
- get { return _groups.ToArray(); }
+ get;
+ private set;
}
/// <summary>
@@ -986,106 +962,43 @@
/// </summary>
/// <param name="layer"></param>
/// <returns></returns>
- public void AddLayer(RuntimeMapLayer layer)
+ [Obsolete("Use the Layers property instead")]
+ internal void AddLayer(RuntimeMapLayer layer)
{
- if (_layerIdMap.ContainsKey(layer.ObjectId))
- return;
-
- AddLayerInternal(layer);
+ this.Layers.Add(layer);
}
/// <summary>
- /// Adds the layer.
- /// </summary>
- /// <param name="layer">The layer.</param>
- internal void AddLayerInternal(RuntimeMapLayer layer)
- {
- RuntimeMapLayer prevLayer = (_layers.Count == 0 ? null : _layers[_layers.Count - 1]);
- double zOrder = prevLayer == null ? Z_ORDER_TOP : prevLayer.DisplayOrder + Z_ORDER_INCREMENT;
- layer.DisplayOrder = zOrder;
-
- _layers.Add(layer);
- _layerIdMap[layer.ObjectId] = layer;
-
- OnLayerAdded(layer);
- }
-
- /// <summary>
/// Inserts the specified layer at the specified index. Does nothing
/// if the layer instance is already in the map.
/// </summary>
/// <param name="index"></param>
/// <param name="layer"></param>
+ [Obsolete("Use the Layers property instead")]
public void InsertLayer(int index, RuntimeMapLayer layer)
{
- if (index >= _layers.Count || index < 0)
- throw new ArgumentOutOfRangeException("index");
-
- AddLayerInternal(layer, index);
+ this.Layers.Insert(index, layer);
}
/// <summary>
- /// Adds the layer
- /// </summary>
- /// <param name="value"></param>
- /// <param name="index"></param>
- internal void AddLayerInternal(RuntimeMapLayer value, int index)
- {
- //calculate zorder for the new layer
- double zOrderLow, zOrderHigh;
- RuntimeMapLayer layer;
- if(index == 0)
- {
- zOrderLow = 0;
- layer = _layers.Count > 0 ? _layers[index] : null;
- if (layer != null)
- zOrderHigh = layer.DisplayOrder;
- else
- zOrderHigh = 2.0 * Z_ORDER_INCREMENT;
- }
- else
- {
- layer = _layers[index - 1];
- zOrderLow = layer.DisplayOrder;
- layer = _layers.Count > index ? _layers[index] : null;
- zOrderHigh = layer != null ? layer.DisplayOrder : zOrderLow + 2.0 * Z_ORDER_INCREMENT;
- }
- value.DisplayOrder = (zOrderLow + (zOrderHigh - zOrderLow) / 2.0);
-
- _layers.Insert(index, value);
- _layerIdMap[value.ObjectId] = value;
-
- OnLayerAdded(value);
- }
-
- /// <summary>
/// Sets the layer to the specified index
/// </summary>
/// <param name="index">The index.</param>
/// <param name="layer">The layer.</param>
+ [Obsolete("Use the Layers property instead")]
public void SetLayerIndex(int index, RuntimeMapLayer layer)
{
- if (index >= _layers.Count || index < 0)
- throw new ArgumentOutOfRangeException("index");
-
- int idx = IndexOfLayer(layer);
- if (idx >= 0)
- {
- RemoveLayerAt(idx);
- AddLayerInternal(layer, index);
- }
+ this.Layers[index] = layer;
}
/// <summary>
/// Removes the layer at the specified index
/// </summary>
/// <param name="index">The index.</param>
+ [Obsolete("Use the Layers property instead")]
public void RemoveLayerAt(int index)
{
- if (index >= _layers.Count || index < 0)
- throw new ArgumentOutOfRangeException("index");
-
- RemoveLayerInternal(index);
+ this.Layers.RemoveAt(index);
}
/// <summary>
@@ -1093,9 +1006,10 @@
/// </summary>
/// <param name="layer"></param>
/// <returns></returns>
+ [Obsolete("Use the Layers property instead")]
public int IndexOfLayer(RuntimeMapLayer layer)
{
- return _layers.IndexOf(layer);
+ return this.Layers.IndexOf(layer);
}
/// <summary>
@@ -1103,16 +1017,13 @@
/// </summary>
/// <param name="layerName"></param>
/// <returns></returns>
+ [Obsolete("Use the Layers property instead")]
public int IndexOfLayer(string layerName)
{
Check.NotEmpty(layerName, "layerName");
- for (int i = 0; i < _layers.Count; i++)
- {
- if (layerName.Equals(_layers[i].Name))
- return i;
- }
- return -1;
+ var layer = this.Layers[layerName];
+ return this.Layers.IndexOf(layer);
}
/// <summary>
@@ -1154,68 +1065,35 @@
/// </summary>
/// <param name="name">The name.</param>
/// <returns></returns>
- public RuntimeMapGroup AddGroup(string name)
+ internal RuntimeMapGroup AddGroup(string name)
{
var group = new RuntimeMapGroup(this, name);
- AddGroupInternal(group);
+ this.Groups.Add(group);
return group;
}
- internal void AddGroupInternal(RuntimeMapGroup group)
- {
- _groups.Add(group);
- OnGroupAdded(group);
- }
-
/// <summary>
- /// Removes the layer
- /// </summary>
- /// <param name="layer">The layer.</param>
- internal void RemoveLayerInternal(RuntimeMapLayer layer)
- {
- if (_layers.Remove(layer))
- {
- OnLayerRemoved(layer);
- }
- }
-
- private void RemoveLayerInternal(int index)
- {
- if (index >= 0 && index < _layers.Count)
- {
- var layer = _layers[index];
- _layers.RemoveAt(index);
- OnLayerRemoved(layer);
- }
- }
-
- /// <summary>
/// Removes the specified layer.
/// </summary>
/// <param name="layer">The layer.</param>
+ [Obsolete("Use the Layers property instead")]
public void RemoveLayer(RuntimeMapLayer layer)
{
Check.NotNull(layer, "layer");
- RemoveLayerInternal(layer);
+ this.Layers.Remove(layer);
}
/// <summary>
/// Removes the specified group.
/// </summary>
/// <param name="group">The group.</param>
+ [Obsolete("Use the Groups property instead")]
public void RemoveGroup(RuntimeMapGroup group)
{
Check.NotNull(group, "group");
- RemoveGroupInternal(group);
+ this.Groups.Remove(group);
}
- internal void RemoveGroupInternal(RuntimeMapGroup group)
- {
- if (_groups.Remove(group))
- {
- OnGroupRemoved(group);
- }
- }
/// <summary>
/// Gets the layers of the specified group
@@ -1226,7 +1104,7 @@
{
Check.NotEmpty(groupName, "groupName");
List<RuntimeMapLayer> layers = new List<RuntimeMapLayer>();
- foreach (var lyr in _layers)
+ foreach (var lyr in this.Layers)
{
if (groupName.Equals(lyr.Group))
layers.Add(lyr);
@@ -1318,15 +1196,11 @@
/// </summary>
/// <param name="name">The name.</param>
/// <returns></returns>
+ [Obsolete("Use the indexer of the Layer property instead")]
public RuntimeMapLayer GetLayerByName(string name)
{
Check.NotEmpty(name, "name");
- foreach (var layer in _layers)
- {
- if (name.Equals(layer.Name))
- return layer;
- }
- return null;
+ return this.Layers[name];
}
#region change tracking
@@ -1364,13 +1238,13 @@
/// Called when a group is removed
/// </summary>
/// <param name="group"></param>
- protected void OnGroupRemoved(RuntimeMapGroup group)
+ internal void OnGroupRemoved(RuntimeMapGroup group)
{
//???
var layers = GetLayersOfGroup(group.Name);
foreach (var lyr in layers)
{
- RemoveLayerInternal(lyr);
+ this.Layers.Remove(lyr);
}
TrackChange(group.ObjectId, false, Change.ChangeType.removed, string.Empty);
@@ -1380,7 +1254,7 @@
/// Called when a group is added
/// </summary>
/// <param name="group"></param>
- protected void OnGroupAdded(RuntimeMapGroup group)
+ internal void OnGroupAdded(RuntimeMapGroup group)
{
//???
@@ -1412,9 +1286,6 @@
internal void OnLayerRemoved(RuntimeMapLayer layer)
{
//???
- if (_layerIdMap.ContainsKey(layer.ObjectId))
- _layerIdMap.Remove(layer.ObjectId);
-
TrackChange(layer.ObjectId, true, Change.ChangeType.removed, string.Empty);
}
@@ -1523,7 +1394,5 @@
}
#endregion
-
-
}
}
Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj 2011-11-16 01:45:28 UTC (rev 6227)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj 2011-11-16 13:48:35 UTC (rev 6228)
@@ -193,6 +193,7 @@
<Compile Include="CrossConnection\NsDoc.cs" />
<Compile Include="CrossConnection\ResourceRebaser.cs" />
<Compile Include="Exceptions\CustomPropertyNotFoundException.cs" />
+ <Compile Include="Exceptions\DuplicateKeyException.cs" />
<Compile Include="Exceptions\ExpressionException.cs" />
<Compile Include="Exceptions\MaestroException.cs" />
<Compile Include="Exceptions\NestedExceptionMessageProcessor.cs" />
@@ -216,6 +217,7 @@
<Compile Include="Feature\ReaderBase.cs" />
<Compile Include="Feature\RecordBase.cs" />
<Compile Include="IO\NsDoc.cs" />
+ <Compile Include="Mapping\Collections.cs" />
<Compile Include="Mapping\NsDoc.cs" />
<Compile Include="NsDoc.cs" />
<Compile Include="ObjectModels\CommonTypes.cs" />
Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs 2011-11-16 01:45:28 UTC (rev 6227)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.Designer.cs 2011-11-16 13:48:35 UTC (rev 6228)
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:2.0.50727.4959
+// Runtime Version:2.0.50727.5448
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -314,6 +314,15 @@
}
/// <summary>
+ /// Looks up a localized string similar to An item with the key value ({0}) already exists in the collection.
+ /// </summary>
+ internal static string DuplicateKeyExceptionMessage {
+ get {
+ return ResourceManager.GetString("DuplicateKeyExceptionMessage", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Bad Document: Expected attributes at the root level node.
/// </summary>
internal static string ERR_BAD_DOCUMENT_NO_ROOT_ATTRIBUTES {
Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx 2011-11-16 01:45:28 UTC (rev 6227)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Properties/Resources.resx 2011-11-16 13:48:35 UTC (rev 6228)
@@ -536,4 +536,7 @@
<data name="DowngradedResource" xml:space="preserve">
<value>Resource {0} downgraded to version {1}</value>
</data>
+ <data name="DuplicateKeyExceptionMessage" xml:space="preserve">
+ <value>An item with the key value ({0}) already exists in the collection</value>
+ </data>
</root>
\ No newline at end of file
More information about the mapguide-commits
mailing list