From 28b654f0158cdb4a5cb0c5cc890f451679185693 Mon Sep 17 00:00:00 2001 From: Tebjan Halm Date: Wed, 31 Jul 2013 00:06:07 +0200 Subject: [PATCH] added more events and fixed IdManager bug --- Source/Basic Shapes/SvgVisualElement.cs | 2 - .../Document Structure/SvgDefinitionList.cs | 1 - Source/Painting/SvgGradientServer.cs | 2 +- Source/SvgAttributeCollection.cs | 85 +++++++++++++++- Source/SvgDocument.cs | 11 +++ Source/SvgElement.cs | 96 ++++++++++++++----- Source/SvgElementCollection.cs | 4 +- Source/SvgElementIdManager.cs | 31 ++++++ Source/SvgExtentions.cs | 11 +++ 9 files changed, 214 insertions(+), 29 deletions(-) diff --git a/Source/Basic Shapes/SvgVisualElement.cs b/Source/Basic Shapes/SvgVisualElement.cs index a979870..cb6b404 100644 --- a/Source/Basic Shapes/SvgVisualElement.cs +++ b/Source/Basic Shapes/SvgVisualElement.cs @@ -61,7 +61,6 @@ namespace Svg set { this.Attributes["clip-rule"] = value; } } - /// /// Gets the associated if one has been specified. /// @@ -72,7 +71,6 @@ namespace Svg set { this.Attributes["filter"] = value; } } - /// /// Gets or sets a value to determine if anti-aliasing should occur when the element is being rendered. /// diff --git a/Source/Document Structure/SvgDefinitionList.cs b/Source/Document Structure/SvgDefinitionList.cs index bd39d97..9342773 100644 --- a/Source/Document Structure/SvgDefinitionList.cs +++ b/Source/Document Structure/SvgDefinitionList.cs @@ -26,7 +26,6 @@ namespace Svg // Do nothing. Children should NOT be rendered. } - public override SvgElement DeepCopy() { return DeepCopy(); diff --git a/Source/Painting/SvgGradientServer.cs b/Source/Painting/SvgGradientServer.cs index 83070db..e84fd4b 100644 --- a/Source/Painting/SvgGradientServer.cs +++ b/Source/Painting/SvgGradientServer.cs @@ -88,7 +88,7 @@ namespace Svg /// /// Gets or sets another gradient fill from which to inherit the stops from. /// - [SvgAttributeAttribute("href")] + [SvgAttribute("href")] public SvgGradientServer InheritGradient { get { return this._inheritGradient; } diff --git a/Source/SvgAttributeCollection.cs b/Source/SvgAttributeCollection.cs index 8929e51..0c504d0 100644 --- a/Source/SvgAttributeCollection.cs +++ b/Source/SvgAttributeCollection.cs @@ -87,7 +87,90 @@ namespace Svg public new object this[string attributeName] { get { return this.GetInheritedAttribute(attributeName); } - set { base[attributeName] = value; } + set + { + if(base.ContainsKey(attributeName)) + { + var oldVal = base[attributeName]; + base[attributeName] = value; + if(oldVal != value) OnAttributeChanged(attributeName, value); + } + else + { + base[attributeName] = value; + OnAttributeChanged(attributeName, value); + } + } + } + + /// + /// Fired when an Atrribute has changed + /// + public event EventHandler AttributeChanged; + + protected void OnAttributeChanged(string attribute, object value) + { + var handler = AttributeChanged; + if(handler != null) + { + handler(this._owner, new AttributeEventArgs { Attribute = attribute, Value = value }); + } + } + } + + + /// + /// A collection of Custom Attributes + /// + public sealed class SvgCustomAttributeCollection : Dictionary + { + private SvgElement _owner; + + /// + /// Initialises a new instance of a with the given as the owner. + /// + /// The owner of the collection. + public SvgCustomAttributeCollection(SvgElement owner) + { + this._owner = owner; + } + + /// + /// Gets the attribute with the specified name. + /// + /// A containing the attribute name. + /// The attribute value associated with the specified name; If there is no attribute the parent's value will be inherited. + public new string this[string attributeName] + { + get { return base[attributeName]; } + set + { + if(base.ContainsKey(attributeName)) + { + var oldVal = base[attributeName]; + base[attributeName] = value; + if(oldVal != value) OnAttributeChanged(attributeName, value); + } + else + { + base[attributeName] = value; + OnAttributeChanged(attributeName, value); + } + } + } + + /// + /// Fired when an Atrribute has changed + /// + public event EventHandler AttributeChanged; + + protected void OnAttributeChanged(string attribute, object value) + { + var handler = AttributeChanged; + if(handler != null) + { + handler(this._owner, new AttributeEventArgs { Attribute = attribute, Value = value }); + } } } } \ No newline at end of file diff --git a/Source/SvgDocument.cs b/Source/SvgDocument.cs index 52ef7be..81c9876 100644 --- a/Source/SvgDocument.cs +++ b/Source/SvgDocument.cs @@ -44,6 +44,17 @@ namespace Svg return _idManager; } } + + /// + /// Overwrites the current IdManager with a custom implementation. + /// Be careful with this: If elements have been inserted into the document before, + /// you have to take care that the new IdManager also knows of them. + /// + /// + public void OverwriteIdManager(SvgElementIdManager manager) + { + _idManager = manager; + } /// /// Gets or sets the Pixels Per Inch of the rendered image. diff --git a/Source/SvgElement.cs b/Source/SvgElement.cs index b4c8fb1..daad734 100644 --- a/Source/SvgElement.cs +++ b/Source/SvgElement.cs @@ -41,7 +41,7 @@ namespace Svg private SvgElementCollection _children; private static readonly object _loadEventKey = new object(); private Matrix _graphicsMatrix; - private Dictionary _customAttributes; + private SvgCustomAttributeCollection _customAttributes; /// /// Gets the name of the element. @@ -121,24 +121,20 @@ namespace Svg /// public virtual SvgDocument OwnerDocument { - get - { - if (Parent == null) - { - if (this is SvgDocument) - { - return (SvgDocument)this; - } - else - { - return null; - } - } - else - { - return Parent.OwnerDocument; - } - } + get + { + if (this is SvgDocument) + { + return this as SvgDocument; + } + else + { + if(this.Parent != null) + return Parent.OwnerDocument; + else + return null; + } + } } /// @@ -157,7 +153,10 @@ namespace Svg } } - public Dictionary CustomAttributes + /// + /// Gets a collection of custom attributes + /// + public SvgCustomAttributeCollection CustomAttributes { get { return this._customAttributes; } } @@ -301,7 +300,11 @@ namespace Svg this._children = new SvgElementCollection(this); this._eventHandlers = new EventHandlerList(); this._elementName = string.Empty; - this._customAttributes = new Dictionary(); + this._customAttributes = new SvgCustomAttributeCollection(this); + + //subscribe to attribute events + Attributes.AttributeChanged += Attributes_AttributeChanged; + CustomAttributes.AttributeChanged += Attributes_AttributeChanged; //find svg attribute descriptions _svgPropertyAttributes = from PropertyDescriptor a in TypeDescriptor.GetProperties(this) @@ -316,6 +319,12 @@ namespace Svg } + //dispatch attribute event + void Attributes_AttributeChanged(object sender, AttributeEventArgs e) + { + OnAttributeChanged(e); + } + public virtual void InitialiseFromXML(XmlTextReader reader, SvgDocument document) { throw new NotImplementedException(); @@ -628,6 +637,20 @@ namespace Svg return newObj; } + + /// + /// Fired when an Atrribute of this Element has changed + /// + public event EventHandler AttributeChanged; + + protected void OnAttributeChanged(AttributeEventArgs args) + { + var handler = AttributeChanged; + if(handler != null) + { + handler(this, args); + } + } #region graphical EVENTS @@ -640,7 +663,7 @@ namespace Svg onmouseup = "" onmouseover = "" onmousemove = "" - onmouseout = "" + onmouseout = "" */ /// @@ -662,6 +685,25 @@ namespace Svg caller.RegisterAction(rpcID + "onmouseout", OnMouseOut); } } + + /// + /// Use this method to provide your implementation ISvgEventCaller to unregister Actions + /// + /// + public void UnregisterEvents(ISvgEventCaller caller) + { + if (caller != null && !string.IsNullOrWhiteSpace(this.ID)) + { + var rpcID = this.ID + "/"; + + caller.UnregisterAction(rpcID + "onclick"); + caller.UnregisterAction(rpcID + "onmousedown"); + caller.UnregisterAction(rpcID + "onmouseup"); + caller.UnregisterAction(rpcID + "onmousemove"); + caller.UnregisterAction(rpcID + "onmouseover"); + caller.UnregisterAction(rpcID + "onmouseout"); + } + } [SvgAttribute("onclick")] public event EventHandler Click; @@ -774,6 +816,15 @@ namespace Svg #endregion graphical EVENTS } + + /// + /// Describes the Attribute which was set + /// + public class AttributeEventArgs : EventArgs + { + public string Attribute; + public object Value; + } //deriving class registers event actions and calls the actions if the event occurs public interface ISvgEventCaller @@ -783,6 +834,7 @@ namespace Svg void RegisterAction(string rpcID, Action action); void RegisterAction(string rpcID, Action action); void RegisterAction(string rpcID, Action action); + void UnregisterAction(string rpcID); } /// diff --git a/Source/SvgElementCollection.cs b/Source/SvgElementCollection.cs index 2069848..0d3b35f 100644 --- a/Source/SvgElementCollection.cs +++ b/Source/SvgElementCollection.cs @@ -78,7 +78,7 @@ namespace Svg { if (this._owner.OwnerDocument != null) { - this._owner.OwnerDocument.IdManager.Add(item); + item.ApplyRecursive(this._owner.OwnerDocument.IdManager.Add); } item._parent = this._owner; @@ -132,7 +132,7 @@ namespace Svg if (this._owner.OwnerDocument != null) { - this._owner.OwnerDocument.IdManager.Remove(item); + item.ApplyRecursive(this._owner.OwnerDocument.IdManager.Remove); } } } diff --git a/Source/SvgElementIdManager.cs b/Source/SvgElementIdManager.cs index 1956501..2520f79 100644 --- a/Source/SvgElementIdManager.cs +++ b/Source/SvgElementIdManager.cs @@ -52,6 +52,8 @@ namespace Svg this.EnsureValidId(element.ID); this._idValueMap.Add(element.ID, element); } + + OnAdded(element); } /// @@ -64,6 +66,8 @@ namespace Svg { this._idValueMap.Remove(element.ID); } + + OnRemoved(element); } /// @@ -101,5 +105,32 @@ namespace Svg this._document = document; this._idValueMap = new Dictionary(); } + + public event EventHandler ElementAdded; + public event EventHandler ElementRemoved; + + protected void OnAdded(SvgElement element) + { + var handler = ElementAdded; + if(handler != null) + { + handler(this._document, new SvgElementEventArgs{ Element = element }); + } + } + + protected void OnRemoved(SvgElement element) + { + var handler = ElementRemoved; + if(handler != null) + { + handler(this._document, new SvgElementEventArgs{ Element = element }); + } + } + + } + + public class SvgElementEventArgs : EventArgs + { + public SvgElement Element; } } \ No newline at end of file diff --git a/Source/SvgExtentions.cs b/Source/SvgExtentions.cs index 589a33c..7f77a66 100644 --- a/Source/SvgExtentions.cs +++ b/Source/SvgExtentions.cs @@ -52,5 +52,16 @@ namespace Svg { return element.CustomAttributes.ContainsKey(name) && !string.IsNullOrEmpty(element.CustomAttributes[name]); } + + public static void ApplyRecursive(this SvgElement elem, Action action) + { + action(elem); + + foreach (var element in elem.Children) + { + if(!(elem is SvgDocument)) + element.ApplyRecursive(action); + } + } } } -- GitLab