using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using FastReport.Utils;
using FastReport.Map.Import.Shp;
using FastReport.Map.Import.Osm;
using System.Windows.Forms;
namespace FastReport.Map
{
///
/// Represents a map object.
///
public partial class MapObject : ReportComponentBase, IParent
{
#region Fields
private float scale;
private float zoom;
private float minZoom;
private float maxZoom;
private float offsetX;
private float offsetY;
private LayerCollection layers;
private ColorScale colorScale;
private Padding padding;
private bool mercatorProjection;
#endregion // Fields
#region Properties
///
/// Gets or sets the path to folder containing shapefiles.
///
///
/// This property is used by the map editor when selecting a shapefile.
///
public static string ShapefileFolder;
///
/// Gets or sets the map zoom.
///
[DefaultValue(1.0f)]
[Category("Appearance")]
public float Zoom
{
get { return zoom; }
set
{
if (value < MinZoom)
value = MinZoom;
if (value > MaxZoom)
value = MaxZoom;
zoom = value;
}
}
///
/// Gets or sets minimum zoom value.
///
[DefaultValue(1.0f)]
[Category("Appearance")]
public float MinZoom
{
get { return minZoom; }
set { minZoom = value; }
}
///
/// Gets or sets maximum zoom value.
///
[DefaultValue(50f)]
[Category("Appearance")]
public float MaxZoom
{
get { return maxZoom; }
set { maxZoom = value; }
}
///
/// Gets or sets the X offset of the map.
///
[DefaultValue(0f)]
[Category("Layout")]
public float OffsetX
{
get { return offsetX; }
set { offsetX = value; }
}
///
/// Gets or sets the Y offset of the map.
///
[DefaultValue(0f)]
[Category("Layout")]
public float OffsetY
{
get { return offsetY; }
set { offsetY = value; }
}
///
/// Gets or sets the value indicating that mercator projection must be used to view the map.
///
[DefaultValue(true)]
[Category("Appearance")]
public bool MercatorProjection
{
get { return mercatorProjection; }
set { mercatorProjection = value; }
}
///
/// Gets the color scale settings.
///
[Category("Appearance")]
public ColorScale ColorScale
{
get { return colorScale; }
}
///
/// Gets or sets a collection of map layers.
///
[Browsable(false)]
public LayerCollection Layers
{
get { return layers; }
set { layers = value; }
}
///
/// Gets or sets padding within the map.
///
[Category("Layout")]
public Padding Padding
{
get { return padding; }
set { padding = value; }
}
internal float ScaleG
{
get { return scale * Zoom; }
}
internal float OffsetXG
{
get { return -((Width * Zoom - Width) / 2) + offsetX * Zoom; }
}
internal float OffsetYG
{
get { return -((Height * Zoom - Height) / 2) + offsetY * Zoom; }
}
internal bool IsEmpty
{
get { return Layers.Count == 0; }
}
#endregion // Properties
#region Private Methods
private void DrawLayers(FRPaintEventArgs e)
{
IGraphics g = e.Graphics;
RectangleF drawRect = new RectangleF(
(AbsLeft + Padding.Left) * e.ScaleX,
(AbsTop + Padding.Top) * e.ScaleY,
(Width - Padding.Horizontal) * e.ScaleX,
(Height - Padding.Vertical) * e.ScaleY);
IGraphicsState state = g.Save();
try
{
g.SetClip(drawRect);
foreach (MapLayer layer in layers)
{
layer.SetPrinting(IsPrinting);
layer.Draw(e);
}
}
finally
{
g.Restore(state);
}
}
private void DrawScales(FRPaintEventArgs e)
{
ColorScale.Data = null;
// find the layer which ColorRanges is set to show in the color scale
foreach (MapLayer layer in Layers)
{
if (layer.ColorRanges.ShowInColorScale)
{
ColorScale.Data = layer.ColorRanges;
break;
}
}
if (ColorScale.Visible)
ColorScale.Draw(e, this);
}
internal void DrawMap(FRPaintEventArgs e)
{
if (IsEmpty)
return;
SmoothingMode saveMode = e.Graphics.SmoothingMode;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
MapLayer layer = Layers[0];
double layerWidth = layer.Box.MaxX - layer.Box.MinX;
double layerHeight = MercatorProjection ?
CoordinateConverter.ConvertMercator(layer.Box.MaxY) - CoordinateConverter.ConvertMercator(layer.Box.MinY) :
layer.Box.MaxY - layer.Box.MinY;
float scaleX = (Width - Padding.Horizontal) / (float)layerWidth;
float scaleY = (Height - Padding.Vertical) / (float)layerHeight;
scale = scaleX < scaleY ? scaleX : scaleY;
DrawLayers(e);
e.Graphics.SmoothingMode = saveMode;
DrawScales(e);
}
private void ZoomIn()
{
Zoom *= 1.2f;
}
private void ZoomOut()
{
Zoom /= 1.2f;
}
#endregion // Private Methods
#region IParent Members
///
public bool CanContain(Base child)
{
return child is MapLayer;
}
///
public void GetChildObjects(ObjectCollection list)
{
foreach (MapLayer layer in layers)
{
list.Add(layer);
}
}
///
public void AddChild(Base child)
{
if (child is MapLayer)
layers.Add(child as MapLayer);
}
///
public void RemoveChild(Base child)
{
if (child is MapLayer)
layers.Remove(child as MapLayer);
}
///
public int GetChildOrder(Base child)
{
if (child is MapLayer)
return layers.IndexOf(child as MapLayer);
return 0;
}
///
public void SetChildOrder(Base child, int order)
{
int oldOrder = child.ZOrder;
if (oldOrder != -1 && order != -1 && order != oldOrder)
{
if (child is MapLayer)
{
if (order > layers.Count)
{
order = layers.Count;
}
if (order >= oldOrder)
{
order--;
}
layers.Remove(child as MapLayer);
layers.Insert(order, child as MapLayer);
}
}
}
///
public void UpdateLayout(float dx, float dy)
{
// do nothing
}
#endregion // IParent Members
#region Report Engine
///
public override void SaveState()
{
base.SaveState();
foreach (MapLayer layer in Layers)
{
layer.SaveState();
}
}
///
public override void RestoreState()
{
base.RestoreState();
foreach (MapLayer layer in Layers)
{
layer.RestoreState();
}
}
///
public override void GetData()
{
base.GetData();
foreach (MapLayer layer in Layers)
{
layer.GetData();
}
}
///
public override void InitializeComponent()
{
base.InitializeComponent();
foreach (MapLayer layer in Layers)
{
layer.InitializeComponent();
}
}
///
public override void FinalizeComponent()
{
base.FinalizeComponent();
foreach (MapLayer layer in Layers)
{
layer.FinalizeComponent();
}
}
#endregion // Report Engine
#region Public Methods
///
public override void Assign(Base source)
{
base.Assign(source);
MapObject src = source as MapObject;
MinZoom = src.MinZoom;
MaxZoom = src.MaxZoom;
Zoom = src.Zoom;
OffsetX = src.OffsetX;
OffsetY = src.OffsetY;
Padding = src.Padding;
MercatorProjection = src.MercatorProjection;
ColorScale.Assign(src.ColorScale);
}
///
public override void Serialize(FRWriter writer)
{
MapObject c = writer.DiffObject as MapObject;
base.Serialize(writer);
if (MinZoom != c.MinZoom)
writer.WriteFloat("MinZoom", MinZoom);
if (MaxZoom != c.MaxZoom)
writer.WriteFloat("MaxZoom", MaxZoom);
if (Zoom != c.Zoom)
writer.WriteFloat("Zoom", Zoom);
if (OffsetX != c.OffsetX)
writer.WriteFloat("OffsetX", OffsetX);
if (OffsetY != c.OffsetY)
writer.WriteFloat("OffsetY", OffsetY);
if (Padding != c.Padding)
writer.WriteValue("Padding", Padding);
if (MercatorProjection != c.MercatorProjection)
writer.WriteBool("MercatorProjection", MercatorProjection);
ColorScale.Serialize(writer, "ColorScale", c.ColorScale);
}
///
/// Loads a map from file.
///
/// Name of file that contains a map.
public void Load(string filename)
{
string extension = Path.GetExtension(filename).ToLower();
if (extension == ".shp")
{
using (ShpMapImport import = new ShpMapImport())
{
import.ImportMap(this, null, filename);
if (Layers.Count > 0)
Layers[Layers.Count - 1].Simplify(0.03);
CreateUniqueNames();
}
}
else if (extension == ".osm")
{
mercatorProjection = false;
using (OsmMapImport import = new OsmMapImport())
{
import.ImportMap(this, null, filename);
if (Layers.Count > 0)
Layers[Layers.Count - 1].Simplify(0.03);
CreateUniqueNames();
}
}
}
///
/// Creates unique names for all contained objects such as layers, shapes, etc.
///
public void CreateUniqueNames()
{
if (Report != null)
{
FastNameCreator nameCreator = new FastNameCreator(Report.AllNamedObjects);
foreach (MapLayer layer in layers)
{
if (String.IsNullOrEmpty(layer.Name))
nameCreator.CreateUniqueName(layer);
layer.CreateUniqueNames();
}
}
}
#endregion // Public Methods
///
/// Initializes a new instance of the class.
///
public MapObject()
{
layers = new LayerCollection(this);
zoom = 1;
minZoom = 1;
maxZoom = 50;
padding = new Padding();
colorScale = new ColorScale();
colorScale.Dock = ScaleDock.BottomLeft;
mercatorProjection = true;
Fill = new SolidFill(Color.Gainsboro);
SetFlags(Flags.InterceptsPreviewMouseEvents, true);
FlagProvidesHyperlinkValue = true;
}
}
}