// Copyright 2005, 2006 - Morten Nielsen (www.iter.dk)
//
// This file is part of SharpMap.
// SharpMap 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 of the License, or
// (at your option) any later version.
//
// SharpMap 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 SharpMap; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using DelftTools.Utils.Aop;
using GeoAPI.Geometries;
using SharpMap.Styles.Shapes;
namespace SharpMap.Styles
{
///
/// Defines a style used for rendering vector data
///
[Entity(FireOnCollectionChange = false)]
public class VectorStyle : Style, IDisposable
{
///
/// Initializes a new VectorStyle and sets the default values
///
///
/// Default style values when initialized:
/// *LineStyle: 1px solid black
/// *FillStyle: Solid black
/// *Outline: No Outline
/// *Symbol: null-reference
///
public VectorStyle() :
this(
new SolidBrush(Color.AntiqueWhite),
(Pen) Pens.Black.Clone(),
true,
(Pen) Pens.BlueViolet.Clone(),
1f,
typeof(ILineString),
ShapeType.Ellipse,
16) {}
///
/// Non default constructor to enable fast creation of correct vectorStyle without first generating invalid
/// default style and symbol.
///
///
///
///
///
///
///
///
///
public VectorStyle(Brush fill, Pen outline, bool enableOutline, Pen line, float symbolScale,
Type geometryType, ShapeType shapeType, int shapeSize)
{
this.fill = fill;
this.outline = outline;
this.enableOutline = enableOutline;
this.line = line;
this.symbolScale = symbolScale;
this.geometryType = geometryType;
this.shapeType = shapeType;
this.shapeSize = shapeSize;
UpdateSymbols();
}
///
/// In order to support proper serialization the outside world needs to know if the Symbol was set
/// by an external source.
///
///
[NoNotifyPropertyChange]
public bool HasCustomSymbol { get; private set; }
public override object Clone()
{
var vectorStyle = new VectorStyle
{
shapeType = shapeType,
shapeSize = shapeSize,
line = Line == null ? null : (Pen) Line.Clone(),
outline = Outline == null ? null : (Pen) Outline.Clone(),
fill = Fill == null ? null : (Brush) Fill.Clone(),
enableOutline = EnableOutline,
geometryType = GeometryType,
HasCustomSymbol = HasCustomSymbol,
symbolScale = symbolScale
};
if ((HasCustomSymbol) && (null != symbol))
{
vectorStyle.Symbol = (Bitmap) symbol.Clone();
}
else
{
vectorStyle.UpdateSymbols();
}
return vectorStyle;
}
public void Dispose()
{
if (Line != null)
{
Line.Dispose();
}
if (Outline != null)
{
Outline.Dispose();
}
if (Fill != null)
{
Fill.Dispose();
}
if (Symbol != null)
{
Symbol.Dispose();
}
}
///
/// This function updates the Symbol property with a bitmap generated by using the shape type, size, fillcolor, bordercolor etc.
///
private void UpdateSymbols()
{
var shape = new Shape
{
Width = shapeSize,
Height = shapeSize,
ColorFillSolid = (fill is SolidBrush) ? ((SolidBrush) fill).Color : Color.Transparent,
BorderShow = EnableOutline,
BorderWidth = outline.Width,
BorderColor = outline.Color
};
((IShape) shape).ShapeType = Shape;
var bitmap = new Bitmap(shapeSize, shapeSize);
var g = Graphics.FromImage(bitmap);
g.Clear(Color.Transparent);
shape.Paint(g);
symbol = bitmap;
//update LegendSymbol
var legendSymbolBitmap = new Bitmap(16, 16);
g = Graphics.FromImage(legendSymbolBitmap);
g.Clear(Color.Transparent);
if (GeometryType == typeof(IPoint))
{
g.CompositingMode = CompositingMode.SourceOver;
g.DrawImage(Symbol, 0, 0, legendSymbolBitmap.Width, legendSymbolBitmap.Height);
}
else if ((GeometryType == typeof(IPolygon)) || (GeometryType == typeof(IMultiPolygon)))
{
g.FillRectangle(Fill, 2, 3, 12, 10);
g.DrawRectangle(Outline, 2, 3, 12, 10);
}
else if ((GeometryType == typeof(ILineString)) || (GeometryType == typeof(IMultiLineString)))
{
g.DrawLine(Outline, 2, 8, 14, 8);
g.DrawLine(Line, 2, 8, 14, 8);
}
else
{
g.FillRectangle(Fill, 2, 3, 12, 10);
g.DrawRectangle(Outline, 2, 3, 12, 10);
}
legendSymbol = legendSymbolBitmap;
HasCustomSymbol = false;
}
#region Privates
private Pen line;
private Pen outline;
private bool enableOutline;
private Brush fill;
private Bitmap symbol;
private Bitmap legendSymbol;
private Type geometryType;
private int shapeSize = 18;
#endregion
#region Properties
///
/// Linestyle for line geometries
///
public virtual Pen Line
{
get
{
return line;
}
set
{
line = value;
if (!HasCustomSymbol)
{
UpdateSymbols();
}
}
}
///
/// Outline style for line and polygon geometries
///
public virtual Pen Outline
{
get
{
return outline;
}
set
{
outline = value;
if (!HasCustomSymbol)
{
UpdateSymbols();
}
}
}
///
/// Specified whether the objects are rendered with or without outlining
///
public virtual bool EnableOutline
{
get
{
return enableOutline;
}
set
{
enableOutline = value;
if (!HasCustomSymbol)
{
UpdateSymbols();
}
}
}
///
/// Fillstyle for Polygon geometries
///
public virtual Brush Fill
{
get
{
return fill;
}
set
{
fill = value;
if (!HasCustomSymbol)
{
UpdateSymbols();
}
}
}
public virtual Bitmap LegendSymbol
{
get
{
return legendSymbol;
}
}
public virtual Type GeometryType
{
get
{
return geometryType;
}
set
{
geometryType = value;
if (!HasCustomSymbol)
{
UpdateSymbols();
}
}
}
///
/// Symbol used for rendering points
///
public virtual Bitmap Symbol
{
get
{
return symbol;
}
set
{
symbol = value;
HasCustomSymbol = true;
if (value != null)
{
//set the legendSymbol with the custom image
Bitmap legendSymbolBitmap = new Bitmap(16, 16);
Graphics g = Graphics.FromImage(legendSymbolBitmap);
g.Clear(Color.Transparent);
g.CompositingMode = CompositingMode.SourceOver;
g.DrawImage(Symbol, 0, 0, legendSymbolBitmap.Width, legendSymbolBitmap.Height);
legendSymbol = legendSymbolBitmap;
}
}
}
private float symbolScale;
///
/// Scale of the symbol (defaults to 1)
///
///
/// Setting the symbolscale to '2.0' doubles the size of the symbol, where a scale of 0.5 makes the scale half the size of the original image
///
public virtual float SymbolScale
{
get
{
return symbolScale;
}
set
{
symbolScale = value;
}
}
///
/// Gets or sets the offset in pixels of the symbol.
///
///
/// The symbol offset is scaled with the property and refers to the offset af =1.0.
///
public virtual PointF SymbolOffset { get; set; }
///
/// Defines the shapesize for symbol
///
public virtual int ShapeSize
{
get
{
return shapeSize;
}
set
{
shapeSize = value;
if (!HasCustomSymbol)
{
UpdateSymbols();
}
}
}
private ShapeType shapeType = ShapeType.Diamond; // default
///
/// Defines shape for symbol
///
public ShapeType Shape
{
get
{
return shapeType;
}
set
{
shapeType = value;
UpdateSymbols();
}
}
///
/// Gets or sets the rotation of the symbol in degrees (clockwise is positive)
///
public virtual float SymbolRotation { get; set; }
#endregion
}
}