using System; using System.Collections; using System.Drawing; using System.Globalization; using System.Reflection; using System.Runtime.Serialization; using System.Security.Permissions; using System.Windows.Forms; namespace CraftSynth.ImageEditor { /// /// Collection of s used to organize the drawing surface /// [Serializable] public class Layers : ISerializable, IDisposable { // Contains the list of Layers private ArrayList layerList; private bool _isDirty; /// /// Dirty is True if any graphic element in any Layer is dirty, else False /// public bool Dirty { get { if (_isDirty == false) { foreach (Layer l in layerList) { if (l.Dirty) { _isDirty = true; break; } } } return _isDirty; } //set //{ // foreach (Layer l in layerList) // l.Dirty = false; // _isDirty = false; //} } private const string entryCount = "LayerCount"; private const string entryLayer = "LayerType"; public Layers() { layerList = new ArrayList(); } /// /// Returns the index of the Active Layer - only one Layer may be active at any one time /// public int ActiveLayerIndex { get { int i = 0; foreach (Layer l in layerList) { if (l.IsActive) break; i++; } return i; } } protected Layers(SerializationInfo info, StreamingContext context) { layerList = new ArrayList(); int n = info.GetInt32(entryCount); for (int i = 0; i < n; i++) { string typeName; typeName = info.GetString( String.Format(CultureInfo.InvariantCulture, "{0}{1}", entryLayer, i)); object _layer; _layer = Assembly.GetExecutingAssembly().CreateInstance(typeName); ((Layer)_layer).LoadFromStream(info, i); layerList.Add(_layer); } } /// /// Save object to serialization stream /// /// /// [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(entryCount, layerList.Count); int i = 0; foreach (Layer l in layerList) { info.AddValue( String.Format(CultureInfo.InvariantCulture, "{0}{1}", entryLayer, i), l.GetType().FullName); l.SaveToStream(info, i); i++; } } /// /// Draw all objects contained in all visible layers /// /// Graphics object to draw on public void Draw(Graphics g) { foreach (Layer l in layerList) { if (l.IsVisible) l.Draw(g); } } /// /// Clear all objects in the list /// /// /// true if at least one object is deleted /// public bool Clear() { bool result = (layerList.Count > 0); foreach (Layer l in layerList) l.Graphics.Clear(); if (layerList.Count > 0) { for (int i = layerList.Count - 1; i >= 0; i--) { if (layerList[i] != null) { ((DrawObject) layerList[i]).Dispose(); } layerList.RemoveAt(i); } } // Create a default Layer since there must be at least one Layer at all times CreateNewLayer("Default"); // Set dirty flag based on result. Result is true only if at least one item was cleared and since the list is empty, there can be nothing dirty. if (result) _isDirty = false; return result; } /// /// Returns number layers in the collection - useful for for loops /// public int Count { get { return layerList.Count; } } /// /// Allows iterating through the list of layers using a for loop /// /// the index of the layer to return /// the specified layer object public Layer this[int index] { get { if (index < 0 || index >= layerList.Count) return null; return (Layer)layerList[index]; } } /// /// Adds a new layer to the collection /// /// The layer object to add public void Add(Layer obj) { layerList.Add(obj); // insert to the top of z-order //layerList.Insert(0, obj); } /// /// Create a new layer at the head of the layers list and set it to Active and Visible. /// /// The name to assign to the new layer public void CreateNewLayer(string theName) { // Deactivate the currently active Layer if (layerList.Count > 0) ((Layer)layerList[ActiveLayerIndex]).IsActive = false; // Create new Layer, set it visible and active Layer l = new Layer(); l.IsVisible = true; l.IsActive = true; l.LayerName = theName; // Initialize empty GraphicsList for future objects l.Graphics = new GraphicsList(); // Add to Layers collection Add(l); } /// /// Inactivate the active by setting all layers to inactive. /// Brute force approach /// public void InactivateAllLayers() { foreach (Layer l in layerList) { l.IsActive = false; // Make sure nothing is selected on the currently active layer before switching layers. if (l.Graphics != null) l.Graphics.UnselectAll(); } } /// /// Makes the specified invisible /// /// index of to make invisible public void MakeLayerInvisible(int p) { if (p > -1 && p < layerList.Count) ((Layer)layerList[p]).IsVisible = false; } /// /// Makes the specified visible /// /// index of to make visible public void MakeLayerVisible(int p) { if (p > -1 && p < layerList.Count) ((Layer)layerList[p]).IsVisible = true; } /// /// Changes the active to the one indicated /// /// index of the to activate public void SetActiveLayer(int p) { //// If the current layer is the same as the layer we are switching to, then do nothing. //if (ActiveLayerIndex == p) // return; // Ensure the index is valid if (p > -1 && p < layerList.Count) { // Make sure nothing is selected on the currently active layer before switching layers. //if (((Layer)layerList[ActiveLayerIndex]).Graphics != null) // ((Layer)layerList[ActiveLayerIndex]).Graphics.UnselectAll(); //((Layer)layerList[ActiveLayerIndex]).IsActive = false; ((Layer)layerList[p]).IsActive = true; ((Layer)layerList[p]).IsVisible = true; } } /// /// Removes the specified from the collection - deleting all graphic objects the contains /// /// index of the to remove public void RemoveLayer(int p) { if (ActiveLayerIndex == p) { MessageBox.Show("Cannot Remove the Active Layer"); return; } if (layerList.Count == 1) { MessageBox.Show("There is only one Layer in this drawing! You Cannot Remove the Only Layer!"); return; } // Ensure the index is valid if (p > -1 && p < layerList.Count) { ((Layer)layerList[p]).Graphics.Clear(); layerList.RemoveAt(p); } } // Public implementation of Dispose pattern callable by consumers. public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } // Flag: Has Dispose already been called? bool _disposed = false; // Protected implementation of Dispose pattern. protected virtual void Dispose(bool disposing) { if (!this._disposed) { if (disposing) { // Free any managed objects here. // if (layerList != null) { foreach (Layer layer in layerList) { if (layer != null) { layer.Dispose(); } } } } // Free any unmanaged objects here. // this._disposed = true; } } ~Layers() { this.Dispose(false); } } }