Index: src/Common/SharpMap/Map/Map.cs =================================================================== diff -u -r0351ce136be0583e51b4022a9dca9e7ec547e908 -r5fc71a385897af92ccb092f2f969b5709afab85a --- src/Common/SharpMap/Map/Map.cs (.../Map.cs) (revision 0351ce136be0583e51b4022a9dca9e7ec547e908) +++ src/Common/SharpMap/Map/Map.cs (.../Map.cs) (revision 5fc71a385897af92ccb092f2f969b5709afab85a) @@ -79,32 +79,42 @@ /// System.Drawing.Image imgMap = myMap.GetMap(); //Renders the map /// /// - [Entity(FireOnCollectionChange=false)] + [Entity(FireOnCollectionChange = false)] //[Serializable] public class Map : IDisposable, INotifyCollectionChange, IMap { - private static readonly ILog log = LogManager.GetLogger(typeof(Map)); + /// + /// When layer render time is less than this - image will not be cached, increase this parameter when you get memory leaks. + /// + public const int ThresholdToClearLayerImageInMillis = 100; - //used in zoomtoextends to have default 10 percent margin - private const int defaultExtendsMarginPercentage = 10; - /// /// Used for converting numbers to/from strings /// public static readonly NumberFormatInfo numberFormat_EnUS = new CultureInfo("en-US", false).NumberFormat; + public static bool UseParallelRendering = true; + + //used in zoomtoextends to have default 10 percent margin + private const int defaultExtendsMarginPercentage = 10; + private static readonly ILog log = LogManager.GetLogger(typeof(Map)); + private IEventedList layers; private double worldHeight; private double worldLeft; private double worldTop; + private bool showGrid; + + private VectorLayer gridLayer; + + private bool rendering; + /// /// Initializes a new map /// - public Map() : this(new Size(100, 100)) - { - } + public Map() : this(new Size(100, 100)) {} /// /// Initializes a new map @@ -131,72 +141,7 @@ UpdateDimensions(); } - private void UpdateDimensions() - { - pixelSize = zoom/size.Width; - pixelHeight = pixelSize*pixelAspectRatio; - worldHeight = pixelSize*size.Height; - worldLeft = center.X - zoom*0.5; - worldTop = center.Y + worldHeight*0.5*pixelAspectRatio; - } - /// - /// Disposes the map object - /// - public virtual void Dispose() - { - foreach (Layer layer in layers) - { - var disposable = layer as IDisposable; - if (disposable != null) - { - disposable.Dispose(); - } - layer.ClearImage(); - } - } - - #region Events - - /// - /// Event fired when the zoomlevel or the center point has been changed - /// - public virtual event MapViewChangedHandler MapViewOnChange; - - public virtual event MapLayerRenderedEventHandler MapLayerRendered; - - /// - /// Event fired when all layers have been rendered - /// - public virtual event MapRenderedEventHandler MapRendered; - - public virtual event MapRenderedEventHandler MapRendering; - - #endregion - - public virtual Image Image - { - get { return image; } - } - - public virtual void ClearImage() - { - if (image != null) - { - ResourceMonitor.OnResourceDeallocated(this, image); - image.Dispose(); - image = null; - } - - foreach(var layer in Layers) - { - layer.ClearImage(); - } - } - - public static bool UseParallelRendering = true; - - /// /// True if map needs to be rendered. Map will check this flag while it will render itself. /// If flag is set to true - Render() will be called before Image is drawn on Map. /// @@ -205,28 +150,16 @@ [NoNotifyPropertyChange] public virtual bool RenderRequired { get; protected set; } - private void SetRenderRequiredForAllLayers() + public virtual Image Image { - if (Layers == null) + get { - return; + return image; } - - foreach (var layer in Layers) - { - layer.RenderRequired = true; - } - - if (ShowGrid) - { - GetGridLayer().RenderRequired = true; - } } public virtual bool IsDisposing { get; protected set; } - private bool showGrid; - /// /// Gets or sets a flag indicating if we should draw grid (usually latitude / longitude projected to the current map coordinate system). /// @@ -255,66 +188,117 @@ } } - private void RemoveGrid() + public bool ReplacingLayer { get; private set; } + + /// + /// Returns the (first) layer on which is present. + /// + /// The feature to search for. + /// search only visible layers + /// The layer that contains the . Null if not layer can be found. + public virtual ILayer GetLayerByFeature(IFeature feature, bool visibleOnly) { - if (gridLayer == null) + var allLayers = visibleOnly ? GetAllVisibleLayers(true) : GetAllLayers(true); + return allLayers.Where(l => l.DataSource != null).FirstOrDefault(layer => layer.DataSource.Contains(feature)); + } + + public static IEnumerable GetLayers(IEnumerable layers, bool includeGroupLayers, bool includeInvisibleLayers) + { + foreach (var layer in layers) { - return; - } + if (layer.Visible || includeInvisibleLayers) + { + var groupLayer = layer as GroupLayer; + if (groupLayer != null) + { + if (includeGroupLayers) + { + yield return layer; + } - gridLayer = null; + var childLayers = GetLayers(groupLayer.Layers, includeGroupLayers, includeInvisibleLayers); + foreach (var childLayer in childLayers) + { + if (childLayer.Visible || includeInvisibleLayers) + { + yield return childLayer; + } + } + } + else + { + yield return layer; + } + } + } } - VectorLayer gridLayer; - - private void BuildGrid() + public virtual bool GetDataMinMaxForThemeGroup(string themeGroup, string attributeName, out double min, out double max) { - var gridLines = new List(); - - if (CoordinateSystemFactory == null) + if (String.IsNullOrEmpty(themeGroup)) { - log.DebugFormat("Showing map grid is only supported when map has coordinate system defined"); - return; // can only draw if coordinate system factory is available + throw new ArgumentException("expected non-empty themegroup", "themeGroup"); } - - for (var i = -180; i <= 180; i += 10) - { - var coordinates = new ICoordinate[179]; - for (var j = -89; j <= 89; j++) - { - coordinates[j + 89] = new Coordinate(i, j); - } + min = Double.MaxValue; + max = Double.MinValue; + var layersForThemeGroup = GetLayersForThemeGroup(themeGroup, attributeName).ToList(); - gridLines.Add(new Feature { Geometry = new LineString(coordinates) }); + if (!layersForThemeGroup.Any()) + { + return false; //no layers, or no visible layers: no update possible } - for (var i = -90; i <= 90; i += 10) + + foreach (var sameRangeLayer in layersForThemeGroup) { - var coordinates = new ICoordinate[361]; + min = Math.Min(sameRangeLayer.MinDataValue, min); + max = Math.Max(sameRangeLayer.MaxDataValue, max); + } + return true; + } - for (var j = -180; j <= 180; j++) + public virtual void OnThemeGroupDataChanged(string themeGroup, string attributeName) + { + foreach (var layer in GetLayersForThemeGroup(themeGroup, attributeName)) + { + layer.ThemeIsDirty = true; + } + } + + public override string ToString() + { + return (!String.IsNullOrEmpty(Name)) ? Name : base.ToString(); + } + + /// + /// Disposes the map object + /// + public virtual void Dispose() + { + foreach (Layer layer in layers) + { + var disposable = layer as IDisposable; + if (disposable != null) { - coordinates[j + 180] = new Coordinate(j, i); + disposable.Dispose(); } - - gridLines.Add(new Feature { Geometry = new LineString(coordinates) }); + layer.ClearImage(); } + } - var src = CoordinateSystemFactory.CreateFromEPSG(4326 /* WGS84 */); - var dst = CoordinateSystem; - - var transformation = dst == null ? null : CoordinateSystemFactory.CreateTransformation(src, dst); - - gridLayer = new VectorLayer + public virtual void ClearImage() + { + if (image != null) { - DataSource = new FeatureCollection { Features = gridLines, CoordinateSystem = src }, CoordinateTransformation = transformation, - ShowInTreeView = false, - ShowInLegend = false, - Selectable = false, - Map = this - }; + ResourceMonitor.OnResourceDeallocated(this, image); + image.Dispose(); + image = null; + } - gridLayer.Style.Line.Color = Color.FromArgb(50, 100, 100, 100); + foreach (var layer in Layers) + { + layer.ClearImage(); + } } /// @@ -342,7 +326,7 @@ image = null; } - if(image == null) + if (image == null) { image = new Bitmap(Size.Width, Size.Height, PixelFormat.Format32bppPArgb); ResourceMonitor.OnResourceAllocated(this, image); @@ -371,7 +355,10 @@ var gridVectorLayer = GetGridLayer(); if (gridVectorLayer != null) { - allLayers = allLayers.Concat(new[] {gridVectorLayer}).ToArray(); + allLayers = allLayers.Concat(new[] + { + gridVectorLayer + }).ToArray(); } // merge all layer bitmaps @@ -380,7 +367,7 @@ foreach (var layer in allLayers) { - if (!(layer.MaxVisible >= Zoom) || !(layer.MinVisible < Zoom)) + if (!(layer.MaxVisible >= Zoom) || !(layer.MinVisible < Zoom)) { continue; } @@ -391,14 +378,18 @@ } if (layer.Image == null) + { continue; - + } + if (Math.Abs(layer.Opacity - 1.0) > 0.0000001) { GraphicsUtils.DrawImageTransparent(g, layer.Image, layer.Opacity); } else + { g.DrawImage(layer.Image, 0, 0); + } if (MapLayerRendered != null) { @@ -437,35 +428,6 @@ } /// - /// When layer render time is less than this - image will not be cached, increase this parameter when you get memory leaks. - /// - public const int ThresholdToClearLayerImageInMillis = 100; - - /// - /// Clears layer image it if takes very little time to render it. - /// - /// - private void ClearLayerImages(ILayer layer) - { - if (layer.LastRenderDuration < ThresholdToClearLayerImageInMillis) - { - layer.ClearImage(); - } - - // will make sure that only those child layers where render duration is very fast will dispose their images - var groupLayer = layer as IGroupLayer; - if (layer.Image != null && groupLayer != null) - { - foreach (var childLayer in groupLayer.Layers) - { - ClearLayerImages(childLayer); - } - } - } - - private bool rendering; - - /// /// Returns an enumerable for all layers containing the search parameter in the LayerName property /// /// Search parameter @@ -490,19 +452,7 @@ /// Returns the (first) layer on which is present. /// /// The feature to search for. - /// search only visible layers /// The layer that contains the . Null if not layer can be found. - public virtual ILayer GetLayerByFeature(IFeature feature, bool visibleOnly) - { - var allLayers = visibleOnly ? GetAllVisibleLayers(true) : GetAllLayers(true); - return allLayers.Where(l => l.DataSource != null).FirstOrDefault(layer => layer.DataSource.Contains(feature)); - } - - /// - /// Returns the (first) layer on which is present. - /// - /// The feature to search for. - /// The layer that contains the . Null if not layer can be found. public virtual ILayer GetLayerByFeature(IFeature feature) { return GetLayerByFeature(feature, false); @@ -521,7 +471,10 @@ public virtual void DoWithLayerRecursive(ILayer layer, Action action) { - if (layer == null || action == null) return; + if (layer == null || action == null) + { + return; + } action(layer); @@ -534,38 +487,7 @@ } } } - - public static IEnumerable GetLayers(IEnumerable layers, bool includeGroupLayers, bool includeInvisibleLayers) - { - foreach (var layer in layers) - { - if (layer.Visible || includeInvisibleLayers) - { - var groupLayer = layer as GroupLayer; - if (groupLayer != null) - { - if (includeGroupLayers) - { - yield return layer; - } - var childLayers = GetLayers(groupLayer.Layers, includeGroupLayers, includeInvisibleLayers); - foreach (var childLayer in childLayers) - { - if (childLayer.Visible || includeInvisibleLayers) - { - yield return childLayer; - } - } - } - else - { - yield return layer; - } - } - } - } - public virtual IEnumerable GetAllLayers(bool includeGroupLayers) { return GetLayers(Layers, includeGroupLayers, true); @@ -584,15 +506,17 @@ { IEnvelope boundingBox = GetExtents(); if (boundingBox == null || boundingBox.IsNull) + { return; + } boundingBox = (IEnvelope) boundingBox.Clone(); // beware of true 1d networks if ((boundingBox.Width < 1.0e-6) && (boundingBox.Height < 1.0e-6)) { return; } - - AddMargin(boundingBox,defaultExtendsMarginPercentage); + + AddMargin(boundingBox, defaultExtendsMarginPercentage); ZoomToFit(boundingBox); } @@ -602,7 +526,10 @@ /// public virtual void BringToFront(ILayer layer) { - if (layer == null) return; + if (layer == null) + { + return; + } var groupLayer = layer as IGroupLayer; if (groupLayer != null) @@ -632,7 +559,10 @@ /// public virtual void SendToBack(ILayer layer) { - if (layer == null) return; + if (layer == null) + { + return; + } var groupLayer = layer as IGroupLayer; if (groupLayer != null) @@ -658,14 +588,20 @@ public virtual void SendBackward(ILayer layer) { - if (layer == null) return; + if (layer == null) + { + return; + } var nextLayer = GetLayers(layers, false, true) .Where(l => l.RenderOrder >= layer.RenderOrder) .OrderBy(l => l.RenderOrder) .FirstOrDefault(l => l != layer); - if (nextLayer == null) return; + if (nextLayer == null) + { + return; + } if (nextLayer.RenderOrder != layer.RenderOrder) { @@ -680,14 +616,20 @@ public virtual void BringForward(ILayer layer) { - if (layer == null) return; + if (layer == null) + { + return; + } var previousLayer = GetLayers(layers, false, true) .Where(l => l.RenderOrder <= layer.RenderOrder) .OrderBy(l => l.RenderOrder) .LastOrDefault(l => l != layer); - if (previousLayer == null) return; + if (previousLayer == null) + { + return; + } previousLayer.RenderOrder++; layer.RenderOrder--; @@ -697,28 +639,6 @@ } /// - /// Expands the given boundingBox by percentage. - /// - /// Boundingbox to expand - /// Percentage by which boundingBox is expanded - private static void AddMargin(IEnvelope boundingBox,double percentage) - { - double minX = 0.0; - double minY = 0.0; - if (boundingBox.Width < 1.0e-6) - { - minX = 1.0; - } - if (boundingBox.Height < 1.0e-6) - { - minY = 1.0; - } - - var factor = percentage/200;//factor is used left and right so divide by 200 (iso 100) - boundingBox.ExpandBy(minX + boundingBox.Width * factor, minY + boundingBox.Height * factor); - } - - /// /// Zooms the map to fit a bounding box /// /// @@ -744,8 +664,8 @@ /// Add a default margin? public virtual void ZoomToFit(IEnvelope bbox, bool addMargin) { - if (bbox == null || bbox.Width == 0 || bbox.Height == 0 || - Double.IsInfinity(bbox.Width) || Double.IsInfinity(bbox.Height) || + if (bbox == null || bbox.Width == 0 || bbox.Height == 0 || + Double.IsInfinity(bbox.Width) || Double.IsInfinity(bbox.Height) || Double.IsNaN(bbox.Width) || Double.IsNaN(bbox.Height)) { return; @@ -764,20 +684,19 @@ //if the map height is smaller than the given bbox height scale to the height if (Envelope.Height < bbox.Height) { - zoom *= bbox.Height / MapHeight; + zoom *= bbox.Height/MapHeight; //zoom *= bbox.Height / Envelope.Height; --> Significance decrease for large center coordinates (TOOLS-7678) } - + center = bbox.Centre; - + UpdateDimensions(); - if(GetExtents() == null || GetExtents().IsNull) + if (GetExtents() == null || GetExtents().IsNull) { desiredEnvelope = Envelope; } - if (MapViewOnChange != null) { MapViewOnChange(); @@ -807,6 +726,253 @@ return Transform.MapToWorld(p, this); } + public virtual object Clone() + { + var clone = new Map(Size) + { + name = name, + Center = new Coordinate(Center), + minimumZoom = minimumZoom, + maximumZoom = maximumZoom, + Zoom = Zoom, + SrsWkt = SrsWkt, + showGrid = ShowGrid, + desiredEnvelope = desiredEnvelope + }; + + foreach (ILayer layer in Layers) + { + clone.Layers.Add((ILayer) layer.Clone()); + } + + return clone; + } + + public void ReplaceLayer(ILayer sourceLayer, ILayer targetLayer) + { + ReplacingLayer = true; + sourceLayer.ThemeGroup = sourceLayer.Name; + sourceLayer.ShowInTreeView = false; + targetLayer.ThemeGroup = sourceLayer.ThemeGroup; + targetLayer.Theme = sourceLayer.Theme != null ? (ITheme) sourceLayer.Theme.Clone() : null; + + var allLayers = GetAllLayers(true).ToList(); + + if (!allLayers.Contains(sourceLayer)) + { + return; + } + + var layerIndex = Layers.IndexOf(sourceLayer); + + if (layerIndex >= 0) + { + Layers.Remove(sourceLayer); + Layers.Insert(layerIndex, targetLayer); + targetLayer.Map = this; + } + else + { + var groupLayer = allLayers.OfType().FirstOrDefault(gl => gl.Layers.Contains(sourceLayer)); + if (groupLayer != null) + { + var subIndex = groupLayer.Layers.IndexOf(sourceLayer); + var groupLayersReadonly = groupLayer.LayersReadOnly; + groupLayer.LayersReadOnly = false; + groupLayer.Layers.Remove(sourceLayer); + groupLayer.Layers.Insert(subIndex, targetLayer); + targetLayer.Map = this; + groupLayer.LayersReadOnly = groupLayersReadonly; + } + } + + ReplacingLayer = false; + } + + private void UpdateDimensions() + { + pixelSize = zoom/size.Width; + pixelHeight = pixelSize*pixelAspectRatio; + worldHeight = pixelSize*size.Height; + worldLeft = center.X - zoom*0.5; + worldTop = center.Y + worldHeight*0.5*pixelAspectRatio; + } + + private void SetRenderRequiredForAllLayers() + { + if (Layers == null) + { + return; + } + + foreach (var layer in Layers) + { + layer.RenderRequired = true; + } + + if (ShowGrid) + { + GetGridLayer().RenderRequired = true; + } + } + + private void RemoveGrid() + { + if (gridLayer == null) + { + return; + } + + gridLayer = null; + } + + private void BuildGrid() + { + var gridLines = new List(); + + if (CoordinateSystemFactory == null) + { + log.DebugFormat("Showing map grid is only supported when map has coordinate system defined"); + return; // can only draw if coordinate system factory is available + } + + for (var i = -180; i <= 180; i += 10) + { + var coordinates = new ICoordinate[179]; + + for (var j = -89; j <= 89; j++) + { + coordinates[j + 89] = new Coordinate(i, j); + } + + gridLines.Add(new Feature + { + Geometry = new LineString(coordinates) + }); + } + for (var i = -90; i <= 90; i += 10) + { + var coordinates = new ICoordinate[361]; + + for (var j = -180; j <= 180; j++) + { + coordinates[j + 180] = new Coordinate(j, i); + } + + gridLines.Add(new Feature + { + Geometry = new LineString(coordinates) + }); + } + + var src = CoordinateSystemFactory.CreateFromEPSG(4326 /* WGS84 */); + var dst = CoordinateSystem; + + var transformation = dst == null ? null : CoordinateSystemFactory.CreateTransformation(src, dst); + + gridLayer = new VectorLayer + { + DataSource = new FeatureCollection + { + Features = gridLines, CoordinateSystem = src + }, + CoordinateTransformation = transformation, + ShowInTreeView = false, + ShowInLegend = false, + Selectable = false, + Map = this + }; + + gridLayer.Style.Line.Color = Color.FromArgb(50, 100, 100, 100); + } + + /// + /// Clears layer image it if takes very little time to render it. + /// + /// + private void ClearLayerImages(ILayer layer) + { + if (layer.LastRenderDuration < ThresholdToClearLayerImageInMillis) + { + layer.ClearImage(); + } + + // will make sure that only those child layers where render duration is very fast will dispose their images + var groupLayer = layer as IGroupLayer; + if (layer.Image != null && groupLayer != null) + { + foreach (var childLayer in groupLayer.Layers) + { + ClearLayerImages(childLayer); + } + } + } + + /// + /// Expands the given boundingBox by percentage. + /// + /// Boundingbox to expand + /// Percentage by which boundingBox is expanded + private static void AddMargin(IEnvelope boundingBox, double percentage) + { + double minX = 0.0; + double minY = 0.0; + if (boundingBox.Width < 1.0e-6) + { + minX = 1.0; + } + if (boundingBox.Height < 1.0e-6) + { + minY = 1.0; + } + + var factor = percentage/200; //factor is used left and right so divide by 200 (iso 100) + boundingBox.ExpandBy(minX + boundingBox.Width*factor, minY + boundingBox.Height*factor); + } + + private int GetNewRenderNumber() + { + var allMapLayers = GetLayers(layers, false, true).ToList(); + return allMapLayers.Any() ? allMapLayers.Max(l => l.RenderOrder) + 1 : 0; + } + + private void ResetRenderOrder(int offset) + { + var allMapLayers = GetLayers(layers, false, true).OrderBy(l => l.RenderOrder).ToList(); + var count = offset; + + foreach (var layer in allMapLayers) + { + layer.RenderOrder = count++; + } + } + + private IEnumerable GetLayersForThemeGroup(string themeGroup, string attributeName) + { + var layersWithSameRange = GetAllVisibleLayers(true) + .Where(l => l.ThemeGroup == themeGroup && + l.ThemeAttributeName == attributeName); + return layersWithSameRange; + } + + #region Events + + /// + /// Event fired when the zoomlevel or the center point has been changed + /// + public virtual event MapViewChangedHandler MapViewOnChange; + + public virtual event MapLayerRenderedEventHandler MapLayerRendered; + + /// + /// Event fired when all layers have been rendered + /// + public virtual event MapRenderedEventHandler MapRendered; + + public virtual event MapRenderedEventHandler MapRendering; + + #endregion + #region Properties /// @@ -817,16 +983,18 @@ get { return new Envelope( - Center.X - Zoom*.5, - Center.X + Zoom*.5, - Center.Y - MapHeight*.5, - Center.Y + MapHeight*.5); + Center.X - Zoom*.5, + Center.X + Zoom*.5, + Center.Y - MapHeight*.5, + Center.Y + MapHeight*.5); } } + [NonSerialized] + private Matrix mapTransform; - [NonSerialized] private Matrix mapTransform; - [NonSerialized] private Matrix mapTransformInverted; + [NonSerialized] + private Matrix mapTransformInverted; /// /// Using the you can alter the coordinate system of the map rendering. @@ -842,7 +1010,10 @@ /// public virtual Matrix MapTransform { - get { return mapTransform; } + get + { + return mapTransform; + } set { mapTransform = value; @@ -852,7 +1023,9 @@ mapTransformInverted.Invert(); } else + { mapTransformInverted.Reset(); + } SetRenderRequiredForAllLayers(); } @@ -867,7 +1040,10 @@ /// public virtual string SrsWkt { - get { return srsWkt; } + get + { + return srsWkt; + } set { srsWkt = value; @@ -878,7 +1054,10 @@ private void CreateCoordinateSystemFromWkt(string value) { - if (createCoordinateSystemFromWkt) return; + if (createCoordinateSystemFromWkt) + { + return; + } createCoordinateSystemFromWkt = true; @@ -952,16 +1131,23 @@ { foreach (var layer in GetAllVisibleLayers(true).Where(l => l.DataSource != null).ToArray()) { - if (layer.CoordinateSystem == null || layer.Envelope == null) continue; - + if (layer.CoordinateSystem == null || layer.Envelope == null) + { + continue; + } + var downLeftCorner = new Coordinate(layer.Envelope.MinX, layer.Envelope.MinY, 0); var upperRightCorner = new Coordinate(layer.Envelope.MaxX, layer.Envelope.MaxY, 0); var transform = CoordinateSystemFactory.CreateTransformation(layer.CoordinateSystem, targetCS); if (!CoordinateSystemValidator.CanConvertByTransformation( - new[] {downLeftCorner, upperRightCorner}, transform)) + new[] + { + downLeftCorner, + upperRightCorner + }, transform)) { throw new CoordinateTransformException(layer.Name, layer.CoordinateSystem, targetCS); } @@ -977,8 +1163,8 @@ else { layer.CoordinateTransformation = (layer.CoordinateSystem == null) - ? null - : CoordinateSystemFactory.CreateTransformation(layer.CoordinateSystem, CoordinateSystem); + ? null + : CoordinateSystemFactory.CreateTransformation(layer.CoordinateSystem, CoordinateSystem); } } @@ -989,7 +1175,10 @@ /// public virtual int SRID { - get { return srid; } + get + { + return srid; + } set { srid = value; @@ -1063,7 +1252,7 @@ private void OnLayersCollectionChanged(NotifyCollectionChangingEventArgs e) { var layer1 = e.Item as ILayer; - + if (layer1 != null) { switch (e.Action) @@ -1079,13 +1268,17 @@ UpdateLayerCoordinateTransformation(layer1); layer1.RenderRequired = true; if (!String.IsNullOrEmpty(layer1.ThemeGroup)) + { OnThemeGroupDataChanged(layer1.ThemeGroup, layer1.ThemeAttributeName); + } SetRenderOrderAfterInsert(layer1); break; case NotifyCollectionChangeAction.Remove: RenderRequired = true; if (!String.IsNullOrEmpty(layer1.ThemeGroup)) + { OnThemeGroupDataChanged(layer1.ThemeGroup, layer1.ThemeAttributeName); + } SetRenderOrderAfterRemove(layer1); break; } @@ -1099,7 +1292,10 @@ var newLayers = layer is GroupLayer ? GetLayers(((GroupLayer) layer).Layers, false, true).ToList() - : new List {layer}; + : new List + { + layer + }; var firstNewLayer = newLayers.FirstOrDefault(); if (firstNewLayer == null) @@ -1108,13 +1304,13 @@ } // Calculate the first render order based on actual map layers structure (1 based) - var startRenderOrder = allLayers.IndexOf(firstNewLayer)+1; - + var startRenderOrder = allLayers.IndexOf(firstNewLayer) + 1; + // Shift render orders for layers we inserting in front allLayers.Where(l => l.RenderOrder >= startRenderOrder) - .ToList() - .ForEach(l => l.RenderOrder += newLayers.Count); - + .ToList() + .ForEach(l => l.RenderOrder += newLayers.Count); + // Assign to new layers, again based on map layer structure (1 based) newLayers.ForEach(l => l.RenderOrder = allLayers.IndexOf(l) + 1); } @@ -1126,7 +1322,10 @@ var oldLayers = layer is GroupLayer ? GetLayers(((GroupLayer) layer).Layers, false, true).ToList() - : new List {layer}; + : new List + { + layer + }; if (!oldLayers.Any()) { @@ -1135,8 +1334,8 @@ // Shift render orders for succeeding layers allLayers.Where(l => l.RenderOrder >= oldLayers.Max(l1 => l1.RenderOrder)) - .ToList() - .ForEach(l => l.RenderOrder -= oldLayers.Count); + .ToList() + .ForEach(l => l.RenderOrder -= oldLayers.Count); } /// @@ -1146,9 +1345,14 @@ private void CheckMapExtends(ILayer layer) { if (!layer.Visible || layers == null) + { return; // don't bother + } - var allVisibleLayersWereEmpty = GetAllVisibleLayers(false).Except(new[] { layer }).All(l => l.Envelope != null && l.Envelope.IsNull || !l.Visible); + var allVisibleLayersWereEmpty = GetAllVisibleLayers(false).Except(new[] + { + layer + }).All(l => l.Envelope != null && l.Envelope.IsNull || !l.Visible); if (!allVisibleLayersWereEmpty) { @@ -1170,7 +1374,10 @@ /// public virtual Color BackColor { - get { return backColor; } + get + { + return backColor; + } set { backColor = value; @@ -1188,7 +1395,10 @@ /// public virtual ICoordinate Center { - get { return center; } + get + { + return center; + } set { center = value; @@ -1215,7 +1425,10 @@ /// public virtual double Zoom { - get { return zoom; } + get + { + return zoom; + } set { double oldZoom = zoom; @@ -1233,11 +1446,11 @@ { clippedZoom = value; } - - desiredEnvelope.Zoom(100 * (clippedZoom / oldZoom)); //adjust desiredEnvelope - - ZoomToFit(desiredEnvelope,false); + desiredEnvelope.Zoom(100*(clippedZoom/oldZoom)); //adjust desiredEnvelope + + ZoomToFit(desiredEnvelope, false); + zoom = clippedZoom; //using intermediate value because desired.Zoom(100*) causes minor rounding issues in ZoomToFit } } @@ -1294,25 +1507,37 @@ public virtual double WorldHeight { - get { return worldHeight; } + get + { + return worldHeight; + } } public virtual double WorldLeft { - get { return worldLeft; } + get + { + return worldLeft; + } } public virtual double WorldTop { - get { return worldTop; } + get + { + return worldTop; + } } /// /// Returns the size of a pixel in world coordinate units /// public virtual double PixelSize { - get { return pixelSize; } + get + { + return pixelSize; + } } /// @@ -1321,7 +1546,10 @@ /// The value returned is the same as . public virtual double PixelWidth { - get { return pixelSize; } + get + { + return pixelSize; + } } /// @@ -1330,7 +1558,10 @@ /// The value returned is the same as unless is different from 1. public virtual double PixelHeight { - get { return pixelHeight; } + get + { + return pixelHeight; + } } private double pixelAspectRatio = 1.0; @@ -1342,7 +1573,10 @@ /// Throws an argument exception when value is 0 or less. public virtual double PixelAspectRatio { - get { return pixelAspectRatio; } + get + { + return pixelAspectRatio; + } set { if (pixelAspectRatio <= 0) @@ -1361,7 +1595,10 @@ /// public virtual double MapHeight { - get { return ( Zoom * Size.Height ) / Size.Width * PixelAspectRatio; } + get + { + return (Zoom*Size.Height)/Size.Width*PixelAspectRatio; + } } private Size size; @@ -1371,7 +1608,10 @@ /// public virtual Size Size { - get { return size; } + get + { + return size; + } set { size = value; @@ -1386,7 +1626,10 @@ /// public virtual double MinimumZoom { - get { return minimumZoom; } + get + { + return minimumZoom; + } set { if (value < 0) @@ -1400,7 +1643,7 @@ private double maximumZoom; private string name; - + private Image image; private double pixelSize; private double pixelHeight; @@ -1411,7 +1654,10 @@ /// public virtual double MaximumZoom { - get { return maximumZoom; } + get + { + return maximumZoom; + } set { if (value <= 0) @@ -1425,8 +1671,14 @@ public virtual string Name { - get { return name; } - set { name = value; } + get + { + return name; + } + set + { + name = value; + } } #endregion @@ -1435,133 +1687,18 @@ public virtual event NotifyCollectionChangedEventHandler CollectionChanged; public virtual event NotifyCollectionChangingEventHandler CollectionChanging; - + bool INotifyCollectionChange.HasParentIsCheckedInItems { get; set; } bool INotifyCollectionChange.SkipChildItemEventBubbling { get; set; } public virtual bool HasDefaultEnvelopeSet { - get { return desiredEnvelope.Equals(new Envelope(-500, 500, -500, 500)); } - } - - #endregion - - public virtual object Clone() - { - var clone = new Map(Size) - { - name = name, - Center = new Coordinate(Center), - minimumZoom = minimumZoom, - maximumZoom = maximumZoom, - Zoom = Zoom, - SrsWkt = SrsWkt, - showGrid = ShowGrid, - desiredEnvelope = desiredEnvelope - }; - - foreach(ILayer layer in Layers) + get { - clone.Layers.Add((ILayer) layer.Clone()); + return desiredEnvelope.Equals(new Envelope(-500, 500, -500, 500)); } - - return clone; } - public override string ToString() - { - return (!String.IsNullOrEmpty(Name)) ? Name : base.ToString(); - } - - private int GetNewRenderNumber() - { - var allMapLayers = GetLayers(layers, false, true).ToList(); - return allMapLayers.Any() ? allMapLayers.Max(l => l.RenderOrder) + 1 : 0; - } - - private void ResetRenderOrder(int offset) - { - var allMapLayers = GetLayers(layers, false, true).OrderBy(l => l.RenderOrder).ToList(); - var count = offset; - - foreach (var layer in allMapLayers) - { - layer.RenderOrder = count++; - } - } - - public virtual bool GetDataMinMaxForThemeGroup(string themeGroup, string attributeName, out double min, out double max) - { - if (String.IsNullOrEmpty(themeGroup)) - throw new ArgumentException("expected non-empty themegroup", "themeGroup"); - - min = Double.MaxValue; - max = Double.MinValue; - var layersForThemeGroup = GetLayersForThemeGroup(themeGroup, attributeName).ToList(); - - if (!layersForThemeGroup.Any()) - return false; //no layers, or no visible layers: no update possible - - foreach (var sameRangeLayer in layersForThemeGroup) - { - min = Math.Min(sameRangeLayer.MinDataValue, min); - max = Math.Max(sameRangeLayer.MaxDataValue, max); - } - return true; - } - - public virtual void OnThemeGroupDataChanged(string themeGroup, string attributeName) - { - foreach (var layer in GetLayersForThemeGroup(themeGroup, attributeName)) - layer.ThemeIsDirty = true; - } - - private IEnumerable GetLayersForThemeGroup(string themeGroup, string attributeName) - { - var layersWithSameRange = GetAllVisibleLayers(true) - .Where(l => l.ThemeGroup == themeGroup && - l.ThemeAttributeName == attributeName); - return layersWithSameRange; - } - - public bool ReplacingLayer { get; private set; } - - public void ReplaceLayer(ILayer sourceLayer, ILayer targetLayer) - { - ReplacingLayer = true; - sourceLayer.ThemeGroup = sourceLayer.Name; - sourceLayer.ShowInTreeView = false; - targetLayer.ThemeGroup = sourceLayer.ThemeGroup; - targetLayer.Theme = sourceLayer.Theme != null ? (ITheme)sourceLayer.Theme.Clone() : null; - - var allLayers = GetAllLayers(true).ToList(); - - if (!allLayers.Contains(sourceLayer)) return; - - var layerIndex = Layers.IndexOf(sourceLayer); - - if (layerIndex >= 0) - { - Layers.Remove(sourceLayer); - Layers.Insert(layerIndex, targetLayer); - targetLayer.Map = this; - } - else - { - var groupLayer = allLayers.OfType().FirstOrDefault(gl => gl.Layers.Contains(sourceLayer)); - if (groupLayer != null) - { - var subIndex = groupLayer.Layers.IndexOf(sourceLayer); - var groupLayersReadonly = groupLayer.LayersReadOnly; - groupLayer.LayersReadOnly = false; - groupLayer.Layers.Remove(sourceLayer); - groupLayer.Layers.Insert(subIndex, targetLayer); - targetLayer.Map = this; - groupLayer.LayersReadOnly = groupLayersReadonly; - } - } - - ReplacingLayer = false; - } + #endregion } } \ No newline at end of file