#region Disclaimer / License // Copyright (C) 2010, Jackie Ng // http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@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.Resource; using OSGeo.MapGuide.ObjectModels.Common; using System.Drawing; using System.ComponentModel; using OSGeo.MapGuide.MaestroAPI; using OSGeo.MapGuide.ObjectModels.WatermarkDefinition; namespace OSGeo.MapGuide.ObjectModels.MapDefinition { /// <summary> /// Represents the base interface of map definitions and their runtime forms /// </summary> public interface IMapDefinitionBase { /// <summary> /// Gets the name. /// </summary> /// <value>The name.</value> string Name { get; } /// <summary> /// Gets the coordinate system. Layers whose coordinate system does /// not match will be re-projecte to this coordinate system when rendering /// </summary> /// <value>The coordinate system.</value> string CoordinateSystem { get; } /// <summary> /// Gets or sets the color of the background. /// </summary> /// <value>The color of the background.</value> Color BackgroundColor { get; set; } } /// <summary> /// Represents a Map Definition /// </summary> public interface IMapDefinition : IResource, IMapDefinitionBase, INotifyPropertyChanged { /// <summary> /// If true, the first layer added to this map definition will automatically set the extents /// based on that layer's added extents. Default is false /// </summary> bool SetExtentsFromFirstAddedLayer { get; set; } /// <summary> /// Gets or sets the name. /// </summary> /// <value>The name.</value> string Name { get; set; } /// <summary> /// Gets or sets the coordinate system. Layers whose coordinate system does /// not match will be re-projected to this coordinate system when rendering /// </summary> /// <value>The coordinate system.</value> string CoordinateSystem { get; set; } /// <summary> /// Gets or sets the extents. /// </summary> /// <value>The extents.</value> IEnvelope Extents { get; set; } /// <summary> /// Sets the extents. /// </summary> /// <param name="minx">The minx.</param> /// <param name="miny">The miny.</param> /// <param name="maxx">The maxx.</param> /// <param name="maxy">The maxy.</param> void SetExtents(double minx, double miny, double maxx, double maxy); /// <summary> /// Gets or sets the metadata. /// </summary> /// <value>The metadata.</value> string Metadata { get; set; } /// <summary> /// Returns the base map section of this map definition. Ensure <see cref="InitBaseMap"/> /// is called first before accessing this property /// </summary> IBaseMapDefinition BaseMap { get; } /// <summary> /// Initializes the base map section of this map definition. Subsequent calls /// do nothing, unless you have cleared the section via <see cref="RemoveBaseMap"/> /// </summary> void InitBaseMap(); /// <summary> /// Clears the base map section of this map definition. If you want to rebuild /// this section, ensure <see cref="InitBaseMap"/> is called /// </summary> void RemoveBaseMap(); /// <summary> /// Gets the map layers. /// </summary> /// <value>The map layers.</value> IEnumerable<IMapLayer> MapLayer { get; } /// <summary> /// Adds a layer to this map. If this is the first layer to be added, the coordinate system /// of this map and its extents will be set to the coordinate system and extents of this layer /// if this has not been set already. /// </summary> /// <param name="groupName"></param> /// <param name="layerName"></param> /// <param name="resourceId"></param> /// <returns></returns> IMapLayer AddLayer(string groupName, string layerName, string resourceId); /// <summary> /// Adds a layer to this map. If this is the first layer to be added, the coordinate system /// of this map and its extents will be set to the coordinate system and extents of this layer /// if this has not been set already. /// </summary> /// <param name="layerToInsertAbove">The layer to insert above in the draw order</param> /// <param name="groupName">The name of the group this layer belongs to. If null or empty, this layer will not belong to any group</param> /// <param name="layerName">The name of this layer. This must be unique</param> /// <param name="resourceId">The layer definition id</param> /// <returns>The added layer</returns> IMapLayer AddLayer(IMapLayer layerToInsertAbove, string groupName, string layerName, string resourceId); /// <summary> /// Removes the layer. /// </summary> /// <param name="layer">The layer.</param> void RemoveLayer(IMapLayer layer); /// <summary> /// Gets the index of the specified layer /// </summary> /// <param name="layer">The layer.</param> /// <returns></returns> int GetIndex(IMapLayer layer); /// <summary> /// Moves the layer up the draw order /// </summary> /// <param name="layer">The layer.</param> /// <returns></returns> int MoveUp(IMapLayer layer); /// <summary> /// Moves the layer down the draw order. /// </summary> /// <param name="layer">The layer.</param> /// <returns></returns> int MoveDown(IMapLayer layer); /// <summary> /// Gets the map layer groups. /// </summary> /// <value>The map layer groups.</value> IEnumerable<IMapLayerGroup> MapLayerGroup { get; } /// <summary> /// Adds the group. /// </summary> /// <param name="groupName">Name of the group.</param> /// <returns></returns> IMapLayerGroup AddGroup(string groupName); /// <summary> /// Removes the group /// </summary> /// <param name="group"></param> void RemoveGroup(IMapLayerGroup group); /// <summary> /// Gets the index of the specified group /// </summary> /// <param name="group"></param> /// <returns></returns> int GetIndex(IMapLayerGroup group); /// <summary> /// Moves the specified layer to the top of the draw order /// </summary> /// <param name="layer"></param> void SetTopDrawOrder(IMapLayer layer); /// <summary> /// Moves the specified layer to the bottom of the draw order /// </summary> /// <param name="layer"></param> void SetBottomDrawOrder(IMapLayer layer); /// <summary> /// Inserts the layer at the specified index /// </summary> /// <param name="idx"></param> /// <param name="layer"></param> void InsertLayer(int idx, IMapLayer layer); /// <summary> /// Moves a Map Group down the presentation order /// </summary> /// <param name="group"></param> int MoveDownGroup(IMapLayerGroup group); /// <summary> /// Moves a Map Group up the presentation order /// </summary> /// <param name="group"></param> int MoveUpGroup(IMapLayerGroup group); } /// <summary> /// Represents a Map Definition with support for watermarks. Corresponds to schema version 2.3.0 /// </summary> public interface IMapDefinition2 : IMapDefinition, IWatermarkCollection { } /// <summary> /// Extension methdo class /// </summary> public static class BaseMapDefinitionExtensions { /// <summary> /// Gets the minimum finite display scale /// </summary> /// <param name="map"></param> /// <returns></returns> public static double GetMinScale(this IBaseMapDefinition map) { Check.NotNull(map, "map"); if (map.ScaleCount == 0) return 0.0; var scales = new List<double>(map.FiniteDisplayScale); scales.Sort(); return scales[0]; } /// <summary> /// Gets the maximum finite display scale /// </summary> /// <param name="map"></param> /// <returns></returns> public static double GetMaxScale(this IBaseMapDefinition map) { Check.NotNull(map, "map"); if (map.ScaleCount == 0) return 0.0; var scales = new List<double>(map.FiniteDisplayScale); scales.Sort(); return scales[scales.Count - 1]; } /// <summary> /// Gets the parent group for the specified layer /// </summary> /// <param name="map"></param> /// <param name="layer"></param> /// <returns></returns> public static IBaseMapGroup GetGroupForLayer(this IBaseMapDefinition map, IBaseMapLayer layer) { Check.NotNull(map, "map"); foreach (var group in map.BaseMapLayerGroup) { foreach (var tl in group.BaseMapLayer) { if (tl == layer) return group; } } return null; } /// <summary> /// Gets whether this base map group has tiled layers /// </summary> /// <param name="grp"></param> /// <returns></returns> public static bool HasLayers(this IBaseMapGroup grp) { Check.NotNull(grp, "grp"); return new List<IBaseMapLayer>(grp.BaseMapLayer).Count > 0; } /// <summary> /// Gets whether this base map has tiled layers /// </summary> /// <param name="map"></param> /// <returns></returns> public static bool HasLayers(this IBaseMapDefinition map) { Check.NotNull(map, "map"); if (!map.HasGroups()) return false; foreach (var group in map.BaseMapLayerGroup) { if (group.HasLayers()) return true; } return false; } /// <summary> /// Gets whether this base map has groups /// </summary> /// <param name="map"></param> /// <returns></returns> public static bool HasGroups(this IBaseMapDefinition map) { Check.NotNull(map, "map"); return new List<IBaseMapGroup>(map.BaseMapLayerGroup).Count > 0; } /// <summary> /// Gets the first base map group /// </summary> /// <param name="map"></param> /// <returns></returns> public static IBaseMapGroup GetFirstGroup(this IBaseMapDefinition map) { Check.NotNull(map, "map"); var list = new List<IBaseMapGroup>(map.BaseMapLayerGroup); if (list.Count > 0) return list[0]; return null; } /// <summary> /// Gets whether a tiled layer of the specified name exists. /// </summary> /// <param name="map"></param> /// <param name="layerName"></param> /// <returns></returns> public static bool LayerExists(this IBaseMapDefinition map, string layerName) { Check.NotNull(map, "map"); Check.NotEmpty(layerName, "layerName"); foreach (var group in map.BaseMapLayerGroup) { foreach (var layer in group.BaseMapLayer) { if (layerName.Equals(layer.Name)) return true; } } return false; } /// <summary> /// Gets the base map group of the specified name /// </summary> /// <param name="map"></param> /// <param name="groupName"></param> /// <returns></returns> public static IBaseMapGroup GetGroup(this IBaseMapDefinition map, string groupName) { Check.NotNull(map, "map"); Check.NotEmpty(groupName, "groupName"); foreach (var group in map.BaseMapLayerGroup) { if (groupName.Equals(group.Name)) return group; } return null; } /// <summary> /// Gets whether the specified base map group exists /// </summary> /// <param name="map"></param> /// <param name="groupName"></param> /// <returns></returns> public static bool GroupExists(this IBaseMapDefinition map, string groupName) { Check.NotNull(map, "map"); Check.NotEmpty(groupName, "groupName"); foreach (var group in map.BaseMapLayerGroup) { if (groupName.Equals(group.Name)) return true; } return false; } /// <summary> /// Gets the tiled layers for the specified base map group /// </summary> /// <param name="map"></param> /// <param name="groupName"></param> /// <returns></returns> public static IEnumerable<IBaseMapLayer> GetLayersForGroup(this IBaseMapDefinition map, string groupName) { Check.NotNull(map, "map"); Check.NotEmpty(groupName, "groupName"); foreach (var group in map.BaseMapLayerGroup) { if (groupName.Equals(group.Name)) { return group.BaseMapLayer; } } return new IBaseMapLayer[0]; } } /// <summary> /// Extension method class /// </summary> public static class MapDefinitionExtensions { /// <summary> /// Updates the group name references of all layers belonging to a particular group /// </summary> /// <param name="map">The map.</param> /// <param name="oldGroupName">Old name of the group.</param> /// <param name="newGroupName">New name of the group.</param> public static void UpdateDynamicGroupName(this IMapDefinition map, string oldGroupName, string newGroupName) { Check.NotNull(map, "map"); Check.NotEmpty(oldGroupName, "oldGroupName"); Check.NotEmpty(newGroupName, "newGroupName"); var layers = map.GetLayersForGroup(oldGroupName); foreach (var l in layers) { l.Group = newGroupName; } } /// <summary> /// Removes a layer group and all layers associated with this group /// </summary> /// <param name="map"></param> /// <param name="groupName"></param> /// <returns>The number of layers removed. Returns 0 if the group is empty or does not exist</returns> public static int RemoveLayerGroupAndChildLayers(this IMapDefinition map, string groupName) { Check.NotNull(map, "map"); Check.NotEmpty(groupName, "groupName"); var affectedParentGroups = new Dictionary<string, List<IMapLayerGroup>>(); IMapLayerGroup group = null; foreach (var grp in map.MapLayerGroup) { if (grp.Name == groupName) group = grp; string parentGroupName = grp.Group; if (!string.IsNullOrEmpty(parentGroupName)) { if (!affectedParentGroups.ContainsKey(parentGroupName)) affectedParentGroups[parentGroupName] = new List<IMapLayerGroup>(); affectedParentGroups[parentGroupName].Add(grp); } } if (group != null) { List<IMapLayer> layers = new List<IMapLayer>(map.GetLayersForGroup(groupName)); int removed = 0; //Remove layers first foreach (var l in layers) { map.RemoveLayer(l); removed++; } //Then the group map.RemoveGroup(group); //Then see if any child groups are under this group and remove them too if (affectedParentGroups.ContainsKey(group.Name)) { for (int i = 0; i < affectedParentGroups[group.Name].Count; i++) { var removeMe = affectedParentGroups[group.Name][i]; removed += map.RemoveLayerGroupAndChildLayers(removeMe.Name); } } return removed; } return 0; } /// <summary> /// Get a layer by its name /// </summary> /// <param name="map"></param> /// <param name="name"></param> /// <returns></returns> public static IMapLayer GetLayerByName(this IMapDefinition map, string name) { Check.NotNull(map, "map"); Check.NotEmpty(name, "name"); foreach (var layer in map.MapLayer) { if (name.Equals(layer.Name)) return layer; } return null; } /// <summary> /// Gets a group by its name /// </summary> /// <param name="map"></param> /// <param name="name"></param> /// <returns></returns> public static IMapLayerGroup GetGroupByName(this IMapDefinition map, string name) { Check.NotNull(map, "map"); foreach (var group in map.MapLayerGroup) { if (name.Equals(group.Name)) return group; } return null; } /// <summary> /// Gets the number of layers (non-tiled) on this map /// </summary> /// <param name="map"></param> /// <returns></returns> public static int GetLayerCount(this IMapDefinition map) { Check.NotNull(map, "map"); return new List<IMapLayer>(map.MapLayer).Count; } /// <summary> /// Gets the number of groups (non-tiled) on this map /// </summary> /// <param name="map"></param> /// <returns></returns> public static int GetGroupCount(this IMapDefinition map) { Check.NotNull(map, "map"); return new List<IMapLayerGroup>(map.MapLayerGroup).Count; } /// <summary> /// Gets all the layers that belong to the specified group /// </summary> /// <param name="map"></param> /// <param name="name"></param> /// <returns></returns> public static IEnumerable<IMapLayer> GetLayersForGroup(this IMapDefinition map, string name) { Check.NotNull(map, "map"); foreach (var layer in map.MapLayer) { if (name.Equals(layer.Group)) yield return layer; } } /// <summary> /// Gets all that layers that do not belong to a group /// </summary> /// <param name="map"></param> /// <returns></returns> public static IEnumerable<IMapLayer> GetLayersWithoutGroups(this IMapDefinition map) { Check.NotNull(map, "map"); foreach (var layer in map.MapLayer) { if (string.IsNullOrEmpty(layer.Group)) yield return layer; } } } /// <summary> /// Represents the tiled map portion of the Map Definition /// </summary> public interface IBaseMapDefinition { /// <summary> /// Gets the finite display scales /// </summary> IEnumerable<double> FiniteDisplayScale { get; } /// <summary> /// Adds the finite display scale. /// </summary> /// <param name="value">The value.</param> void AddFiniteDisplayScale(double value); /// <summary> /// Removes the finite display scale. /// </summary> /// <param name="value">The value.</param> void RemoveFiniteDisplayScale(double value); /// <summary> /// Gets the scale count. /// </summary> /// <value>The scale count.</value> int ScaleCount { get; } /// <summary> /// Removes the scale at the specified index /// </summary> /// <param name="index">The index.</param> void RemoveScaleAt(int index); /// <summary> /// Gets the scale at the specified index /// </summary> /// <param name="index">The index.</param> /// <returns></returns> double GetScaleAt(int index); /// <summary> /// Gets the base map layer groups. /// </summary> /// <value>The base map layer groups.</value> IEnumerable<IBaseMapGroup> BaseMapLayerGroup { get; } /// <summary> /// Gets the group count. /// </summary> /// <value>The group count.</value> int GroupCount { get; } /// <summary> /// Gets the group at the specified index /// </summary> /// <param name="index">The index.</param> /// <returns></returns> IBaseMapGroup GetGroupAt(int index); /// <summary> /// Adds the base layer group. /// </summary> /// <param name="name">The name.</param> /// <returns></returns> IBaseMapGroup AddBaseLayerGroup(string name); /// <summary> /// Removes the base layer group. /// </summary> /// <param name="group">The group.</param> void RemoveBaseLayerGroup(IBaseMapGroup group); /// <summary> /// Removes all scales. /// </summary> void RemoveAllScales(); } /// <summary> /// Base legend element /// </summary> public interface IMapLegendElementBase : INotifyPropertyChanged { /// <summary> /// Gets or sets the name. /// </summary> /// <value>The name.</value> string Name { get; set; } /// <summary> /// Gets or sets a value indicating whether [show in legend]. /// </summary> /// <value><c>true</c> if [show in legend]; otherwise, <c>false</c>.</value> bool ShowInLegend { get; set; } /// <summary> /// Gets or sets the legend label. /// </summary> /// <value>The legend label.</value> string LegendLabel { get; set; } /// <summary> /// Gets or sets a value indicating whether [expand in legend]. /// </summary> /// <value><c>true</c> if [expand in legend]; otherwise, <c>false</c>.</value> bool ExpandInLegend { get; set; } } /// <summary> /// Base layer interface /// </summary> public interface IBaseMapLayer : IMapLegendElementBase { /// <summary> /// Gets or sets the resource id. /// </summary> /// <value>The resource id.</value> string ResourceId { get; set; } /// <summary> /// Gets or sets a value indicating whether this <see cref="IBaseMapLayer"/> is selectable. /// </summary> /// <value><c>true</c> if selectable; otherwise, <c>false</c>.</value> bool Selectable { get; set; } } /// <summary> /// Tiled map group /// </summary> public interface IBaseMapGroup : IMapLegendElementBase { /// <summary> /// Gets or sets a value indicating whether this <see cref="IBaseMapGroup"/> is visible. /// </summary> /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value> bool Visible { get; set; } /// <summary> /// Gets the base map layers. /// </summary> /// <value>The base map layers.</value> IEnumerable<IBaseMapLayer> BaseMapLayer { get; } /// <summary> /// Adds the layer. /// </summary> /// <param name="layerName">Name of the layer.</param> /// <param name="resourceId">The resource id.</param> /// <returns></returns> IBaseMapLayer AddLayer(string layerName, string resourceId); /// <summary> /// Removes the base map layer. /// </summary> /// <param name="layer">The layer.</param> void RemoveBaseMapLayer(IBaseMapLayer layer); /// <summary> /// Insert the base map layer at the specified index /// </summary> /// <param name="index"></param> /// <param name="layer"></param> void InsertLayer(int index, IBaseMapLayer layer); /// <summary> /// Gets the index of the specified layer /// </summary> /// <param name="layer"></param> /// <returns></returns> int GetIndex(IBaseMapLayer layer); /// <summary> /// Moves the specified layer up. /// </summary> /// <param name="layer">The layer.</param> /// <returns></returns> int MoveUp(IBaseMapLayer layer); /// <summary> /// Moves the specified layer down. /// </summary> /// <param name="layer">The layer.</param> /// <returns></returns> int MoveDown(IBaseMapLayer layer); } /// <summary> /// A dynamic map layer /// </summary> public interface IMapLayer : IBaseMapLayer { /// <summary> /// Gets or sets a value indicating whether this <see cref="IMapLayer"/> is visible. /// </summary> /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value> bool Visible { get; set; } /// <summary> /// Gets or sets the group. /// </summary> /// <value>The group.</value> string Group { get; set; } } /// <summary> /// A dynamic map layer group /// </summary> public interface IMapLayerGroup : IMapLegendElementBase { /// <summary> /// Gets or sets a value indicating whether this <see cref="IMapLayerGroup"/> is visible. /// </summary> /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value> bool Visible { get; set; } /// <summary> /// Gets or sets the group name. If null, it means this layer doesn't belong to any group /// </summary> /// <value>The group.</value> string Group { get; set; } /// <summary> /// Gets the parent map definition /// </summary> /// <value>The parent map definition.</value> IMapDefinition Parent { get; } } }