using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml;
using Svg.Transforms;
namespace Svg
{
///
/// The base class of which all SVG elements are derived from.
///
public abstract class SvgElement : ISvgElement, ISvgTransformable, ICloneable
{
internal SvgElement _parent;
private string _elementName;
private SvgAttributeCollection _attributes;
private EventHandlerList _eventHandlers;
private SvgElementCollection _children;
private static readonly object _loadEventKey = new object();
private Matrix _graphicsMatrix;
///
/// Gets the name of the element.
///
protected internal string ElementName
{
get { return this._elementName; }
internal set { this._elementName = value; }
}
///
/// Gets or sets the content of the element.
///
public virtual string Content
{
get;
set;
}
///
/// Gets an of all events belonging to the element.
///
protected virtual EventHandlerList Events
{
get { return this._eventHandlers; }
}
///
/// Occurs when the element is loaded.
///
public event EventHandler Load
{
add { this.Events.AddHandler(_loadEventKey, value); }
remove { this.Events.RemoveHandler(_loadEventKey, value); }
}
///
/// Gets a collection of all child .
///
public virtual SvgElementCollection Children
{
get { return this._children; }
}
///
/// Gets a value to determine whether the element has children.
///
public virtual bool HasChildren()
{
return (this.Children.Count > 0);
}
///
/// Gets the parent .
///
/// An if one exists; otherwise null.
public virtual SvgElement Parent
{
get { return this._parent; }
}
///
/// Gets the owner .
///
public virtual SvgDocument OwnerDocument
{
get
{
if (Parent == null)
{
if (this is SvgDocument)
{
return (SvgDocument)this;
}
else
{
return null;
}
}
else
{
return Parent.OwnerDocument;
}
}
}
///
/// Gets a collection of element attributes.
///
protected internal virtual SvgAttributeCollection Attributes
{
get
{
if (this._attributes == null)
{
this._attributes = new SvgAttributeCollection(this);
}
return this._attributes;
}
}
///
/// Applies the required transforms to .
///
/// The to be transformed.
protected internal virtual void PushTransforms(SvgRenderer renderer)
{
_graphicsMatrix = renderer.Transform;
// Return if there are no transforms
if (this.Transforms == null || this.Transforms.Count == 0)
{
return;
}
Matrix transformMatrix = renderer.Transform;
foreach (SvgTransform transformation in this.Transforms)
{
transformMatrix.Multiply(transformation.Matrix);
}
renderer.Transform = transformMatrix;
}
///
/// Removes any previously applied transforms from the specified .
///
/// The that should have transforms removed.
protected internal virtual void PopTransforms(SvgRenderer renderer)
{
renderer.Transform = _graphicsMatrix;
_graphicsMatrix = null;
}
///
/// Applies the required transforms to .
///
/// The to be transformed.
void ISvgTransformable.PushTransforms(SvgRenderer renderer)
{
this.PushTransforms(renderer);
}
///
/// Removes any previously applied transforms from the specified .
///
/// The that should have transforms removed.
void ISvgTransformable.PopTransforms(SvgRenderer renderer)
{
this.PopTransforms(renderer);
}
///
/// Gets or sets the element transforms.
///
/// The transforms.
[SvgAttribute("transform")]
public SvgTransformCollection Transforms
{
get { return this.Attributes.GetAttribute("Transforms"); }
set { this.Attributes["Transforms"] = value; }
}
///
/// Gets or sets the ID of the element.
///
/// The ID is already used within the .
[SvgAttribute("id")]
public string ID
{
get { return this.Attributes.GetAttribute("ID"); }
set
{
// Don't do anything if it hasn't changed
if (string.Compare(this.ID, value) == 0)
{
return;
}
if (this.OwnerDocument != null)
{
this.OwnerDocument.IdManager.Remove(this);
}
this.Attributes["ID"] = value;
if (this.OwnerDocument != null)
{
this.OwnerDocument.IdManager.Add(this);
}
}
}
protected virtual void AddElement(SvgElement child, int index)
{
}
internal void OnElementAdded(SvgElement child, int index)
{
this.AddElement(child, index);
}
protected virtual void RemoveElement(SvgElement child)
{
}
internal void OnElementRemoved(SvgElement child)
{
this.RemoveElement(child);
}
///
/// Initializes a new instance of the class.
///
internal SvgElement()
{
this._children = new SvgElementCollection(this);
this._eventHandlers = new EventHandlerList();
this._elementName = string.Empty;
}
///
/// Renders this element to the .
///
/// The that the element should use to render itself.
public void RenderElement(SvgRenderer renderer)
{
this.Render(renderer);
}
public void WriteElement(XmlTextWriter writer)
{
this.Write(writer);
}
protected virtual void WriteStartElement(XmlTextWriter writer)
{
if (this.ElementName != String.Empty)
{
writer.WriteStartElement(this.ElementName);
}
this.WriteAttributes(writer);
}
protected virtual void WriteEndElement(XmlTextWriter writer)
{
if (this.ElementName != String.Empty)
{
writer.WriteEndElement();
}
}
protected virtual void WriteAttributes(XmlTextWriter writer)
{
}
protected virtual void Write(XmlTextWriter writer)
{
if (this.ElementName != String.Empty)
{
this.WriteStartElement(writer);
this.WriteChildren(writer);
this.WriteEndElement(writer);
}
}
protected virtual void WriteChildren(XmlTextWriter writer)
{
foreach (SvgElement child in this.Children)
{
child.Write(writer);
}
}
///
/// Renders the and contents to the specified object.
///
/// The object to render to.
protected virtual void Render(SvgRenderer renderer)
{
this.PushTransforms(renderer);
this.RenderChildren(renderer);
this.PopTransforms(renderer);
}
///
/// Renders the children of this .
///
/// The to render the child s to.
protected virtual void RenderChildren(SvgRenderer renderer)
{
foreach (SvgElement element in this.Children)
{
element.Render(renderer);
}
}
///
/// Renders the and contents to the specified object.
///
/// The object to render to.
void ISvgElement.Render(SvgRenderer renderer)
{
this.Render(renderer);
}
///
/// Creates a new object that is a copy of the current instance.
///
///
/// A new object that is a copy of this instance.
///
public virtual object Clone()
{
return this.MemberwiseClone();
}
}
internal interface ISvgElement
{
void Render(SvgRenderer renderer);
}
}