Click here to Skip to main content
15,884,721 members
Articles / Programming Languages / Visual Basic

AGE, Another Graphic Engine in .NET

Rate me:
Please Sign up or sign in to vote.
4.96/5 (36 votes)
10 May 2007CPOL8 min read 135.9K   5.9K   170  
A library that allows some GDI+ manipulation at runtime in an easy way
/////////////////////////////////////////////////////////////////////////////////
// NeoDataType Another Graphic Engine
// --------------------
// Project Copyright (C)    : Fabio Zanetta, email: support@neodatatype.net
// Portions Copyright (C)   : Microsoft Corporation. All Rights Reserved.
// License                  : docs/license.txt
// ------------------------------------------------------------------------------
// File created by          : Fabio Zanetta, email: support@neodatatype.net
// ------------------------------------------------------------------------------
// Please, if you modify some parts of this file mark them as described in
// docs/modify_guidelines.txt
/////////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.ComponentModel;
using System.Reflection;

namespace NeoDataType.Documents
{

    #region Document interaction
    public class DocumentActionEventArgs : EventArgs
    {
        public readonly Document Document;
        public readonly DocumentGroup Group;
        public readonly DocumentItem Item;
        public bool Cancel = false;

        public DocumentActionEventArgs(Document document, DocumentGroup group, DocumentItem item)
        {
            Document = document;
            Group = group;
            Item = item;
        }

    }

    public delegate void DocumentActionEventHandler(object sender, DocumentActionEventArgs e);

    public class LoadLibraryEventArgs : EventArgs
    {
        public readonly System.Reflection.Assembly Library;
        public LoadLibraryEventArgs(System.Reflection.Assembly library)
        {
            Library = library;
        }
    }

    #endregion

    #region DocumentItem
    [SaveThisClass()]
    public class DocumentItem
    {
        int _id;
        bool _toBeSaved = true;        
        DocumentGroup _group;

        /// <summary>
        /// Identifier used for serialization
        /// </summary>
        private int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        [Browsable(false)]
        [SaveThisProperty]
        public DocumentGroup Group
        {
            get { return _group; }
            internal set { _group = value; }
        }

        /// <summary>
        /// Indicate that the item must be saved with the document.
        /// </summary>
        [Browsable(false)]
        public bool ToBeSaved
        {
            get { return _toBeSaved; }
            set { _toBeSaved = value; }
        }

        /// <summary>
        /// Move the item to the specified index.
        /// </summary>
        protected void MoveAt(int newIndex)
        {
            if (Group != null)
            {
                if (Group.Items.Count > 1)
                {
                    Group.Items.Move(this, newIndex);
                    DocumentActionEventArgs e = new DocumentActionEventArgs(Group.Document, Group, this);
                    OnMoved(e);
                }
            }
        }


        #region virtual On...

        protected virtual void OnMoved(DocumentActionEventArgs e)
        {
        }

        public virtual void OnAddingToDocument(DocumentActionEventArgs e)
        { }

        public virtual void OnRemovingFromDocument(DocumentActionEventArgs e)
        { }

        public virtual void OnAddedToDocument(DocumentActionEventArgs e)
        { }

        public virtual void OnRemovedFromDocument(DocumentActionEventArgs e)
        { }
        #endregion

    }
    #endregion

    #region Collections
    public class DocumentGroupCollection : DocumentCollection<DocumentGroup>
    {
        internal void Add(DocumentGroup item)
        {
            InternalList.Add(item);
        }

        internal void Insert(int index, DocumentGroup item)
        {
            InternalList.Insert(index, item);
        }

        internal void Remove(DocumentGroup item)
        {
            InternalList.Remove(item);
        }

        internal void Clear()
        {
            InternalList.Clear();
        }

    }

    [SaveThisClass()]
    public class DocumentItemCollection : DocumentCollection<DocumentItem>
    {

        internal void Add(DocumentItem item)
        {
            InternalList.Add(item);
        }

        internal void Insert(int index, DocumentItem item)
        {
            InternalList.Insert(index, item);
        }

        internal void Remove(DocumentItem item)
        {
            InternalList.Remove(item);
        }

        internal void Clear()
        {
            InternalList.Clear();
        }

        internal void AddRange(DocumentItemCollection items)
        {
            foreach (DocumentItem item in items)
                InternalList.Add(item);
        }

    }

    public class DocumentLibraryCollection : DocumentCollection<DocumentLibrary>
    {
        internal void Add(DocumentLibrary library)
        {
            InternalList.Add(library);
        }

        public void Remove(DocumentLibrary library)
        {
            InternalList.Remove(library);
        }

        public void Clear()
        {
            InternalList.Clear();
        }

    }

    #endregion

    #region DocumentGroup
    [SaveThisClass]
    public class DocumentGroup
    {

        DocumentItemCollection _items = new DocumentItemCollection();
        Document _document;        
        string _name = "";

        [Browsable(false)]
        [SaveThisProperty]
        public Document Document
        {
            get { return _document; }
            internal set { _document = value; }
        }


        [SaveThisProperty]
        public DocumentItemCollection Items
        {
            get { return _items; }
            //set { _items = value; }
        }


        [SaveThisProperty]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        /// <summary>
        /// Move the group to the specified index.
        /// </summary>
        protected void MoveAt(int newIndex)
        {
            if (Document != null)
            {
                if (Document.GroupsInternal.Count > 1)
                {
                    Document.GroupsInternal.Move(this, newIndex);
                    DocumentActionEventArgs e = new DocumentActionEventArgs(Document, this, null);
                    OnMoved(e);
                }
            }
        }



        public override string ToString()
        {
            return GetType().Name + ", Name = " + _name;
        }

        protected virtual void OnMoved(DocumentActionEventArgs e)
        { }

        public virtual void OnAddingToDocument(DocumentActionEventArgs e)
        { }

        public virtual void OnRemovingFromDocument(DocumentActionEventArgs e)
        { }

        public virtual void OnAddedToDocument(DocumentActionEventArgs e)
        { }

        public virtual void OnRemovedFromDocument(DocumentActionEventArgs e)
        { }

        #region Virtual method for Adding/Removing Item
        public virtual void OnAddingItem(DocumentActionEventArgs e)
        { }

        public virtual void OnItemAdded(DocumentActionEventArgs e)
        { }

        public virtual void OnRemovingItem(DocumentActionEventArgs e)
        { }

        public virtual void OnItemRemoved(DocumentActionEventArgs e)
        { }
        #endregion


    }

    #endregion


    [SaveThisClass]
    public class DocumentLibrary : DocumentItem
    {
        Assembly _assembly;
        string _fileName;

        [SaveThisProperty]
        public string FileName
        {
            get { return System.IO.Path.GetFileName(_fileName); }
            set { _fileName = value; }
        }

        public Assembly Assembly
        {
            get { return _assembly; }
            set { _assembly = value; }
        }
    }


    /// <summary>
    /// The base class for each type of document.
    /// </summary>
    [SaveThisClass()]
    public class Document
    {
        string _title = "<Untitled>";
        string _author = "";
        string _fileName = "";


        DocumentItemCollection _items = new DocumentItemCollection();
        DocumentGroupCollection _groups = new DocumentGroupCollection();
        DocumentLibraryCollection _libraries = new DocumentLibraryCollection();
        bool _refreshItemsCache = true;


        public DocumentLibraryCollection Libraries
        {
            get { return _libraries; }
        }

        public string FileName
        {
            get { return _fileName; }
            internal set { _fileName = value; }
        }

        /// <summary>
        /// Gets or sets a the name of the document author.
        /// </summary>
        [SaveThisProperty()]
        public string Author
        {
            get { return _author; }
            set { _author = value; }
        }

        /// <summary>
        /// Gets or sets a the title of the document.
        /// </summary>
        [SaveThisProperty()]
        public virtual string Title 
        {
            get { return _title; }
            set { _title = value; }
        }

        /// <summary>
        /// Groups of items.
        /// </summary>
        [SaveThisProperty]
        protected DocumentGroupCollection Groups
        {
            get { return _groups; }
            set { _groups = value; }
        }

        protected DocumentItemCollection Items
        {
            get
            {

                if (_refreshItemsCache)
                {
                    _items.Clear();

                    foreach (DocumentGroup dg in _groups)
                    {
                        _items.AddRange(dg.Items);
                    }

                    _refreshItemsCache = false;
                }

                return _items;
            }
        }


        internal DocumentItemCollection ItemsInternal
        {
            get { return Items; }
        }

        internal DocumentGroupCollection GroupsInternal
        {
            get { return Groups; }
        }


        internal void OnAddingItemInternal(DocumentActionEventArgs e)
        {
            OnAddingItem(e);
        }

        internal void OnItemAddedInternal(DocumentActionEventArgs e)
        {
            OnItemAdded(e);
        }


        /// <summary>
        /// Called in derived classes when the document is cleared.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the document cleared.</param>
        protected virtual void OnCleared(DocumentActionEventArgs e)
        { }

        protected virtual void OnLibraryLoaded(LoadLibraryEventArgs e)
        { }


        #region Virtual method for Adding/Removing Item
        /// <summary>
        /// Called in derived classes when an item is about to be added to the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the item to be added.</param>
        protected virtual void OnAddingItem(DocumentActionEventArgs e)
        { }

        /// <summary>
        /// Called in derived classes when an item is added to the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the item added.</param>
        protected virtual void OnItemAdded(DocumentActionEventArgs e)
        { }

        /// <summary>
        /// Called in derived classes when an item is about to be removed from the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the item to be removed.</param>
        protected virtual void OnRemovingItem(DocumentActionEventArgs e)
        { }

        /// <summary>
        /// Called in derived classes when an item is removed from the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the item removed.</param>
        protected virtual void OnItemRemoved(DocumentActionEventArgs e)
        { }
        #endregion

        #region Virtual method for Adding/Removing Group

        /// <summary>
        /// Called in derived classes when a group is about to be added to the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the group to be added.</param>
        protected virtual void OnAddingGroup(DocumentActionEventArgs e)
        { }

        /// <summary>
        /// Called in derived classes when a group is about to be added to the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the group added.</param>
        protected virtual void OnGroupAdded(DocumentActionEventArgs e)
        { }

        /// <summary>
        /// Called in derived classes when a group is about to be removed from the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the group to be removed.</param>
        protected virtual void OnRemovingGroup(DocumentActionEventArgs e)
        { }

        /// <summary>
        /// Called in derived classes when a group is removed from the document.
        /// </summary>
        /// <param name="e">DocumentActionEventArgs that indicates the group removed.</param>
        protected virtual void OnGroupRemoved(DocumentActionEventArgs e)
        { }
        #endregion



        /// <summary>
        /// Removes all the items from the document.
        /// </summary>
        public virtual void Clear()
        {
            DocumentActionEventArgs e = new DocumentActionEventArgs(this, null, null);
            
            _groups.Clear();
            _refreshItemsCache = true;
            this.OnCleared(e);
        }

        /// <summary>
        /// Adds the specified item to the default document group.
        /// </summary>
        /// <param name="item">The item to be added.</param>        
        public virtual void AddItem(DocumentItem item)
        {
            AddItem(_groups[0], item);
        }


        /// <summary>
        /// Adds the specified item to the specified document group.
        /// </summary>
        /// <param name="item">The item to be added.</param>        
        /// <param name="destinationGroup">The group that will contain the item.</param>        
        public virtual void AddItem(DocumentGroup destinationGroup, DocumentItem item)
        {

            #region Pre-assertions
            if (destinationGroup == null)
                throw Exceptions.A0_CannotBeNull("group");

            if (item == null)
                throw Exceptions.A0_CannotBeNull("item");


            if (!_groups.Contains(destinationGroup))
                throw Exceptions.GroupDoesNotBelongsToThisDocument(typeof(ArgumentException));


            if ((item.Group != null) && (item.Group != destinationGroup))
                throw Exceptions.A0_IsAlreadyAssignedToAnother_A1("item", "group");

            #endregion


            if (!destinationGroup.Items.Contains(item))
            {

                DocumentActionEventArgs e = new DocumentActionEventArgs(this, destinationGroup, item);
                item.OnAddingToDocument(e);
                if (!e.Cancel)
                {
                    destinationGroup.OnAddingItem(e);
                    if (!e.Cancel)
                    {
                        this.OnAddingItem(e);
                        if (!e.Cancel)
                        {
                            item.Group = destinationGroup;
                            destinationGroup.Items.Add(item);
                            item.Group = destinationGroup;
                            _refreshItemsCache = true;
                            this.OnItemAdded(e);
                            destinationGroup.OnItemAdded(e);
                            item.OnAddedToDocument(e);
                        }
                    }
                }
            }
        }


        /// <summary>
        /// Adds the specified group to the document groups.
        /// </summary>
        /// <param name="group">The group to be added.</param>
        public virtual void AddGroup(DocumentGroup group)
        {

            #region Pre-assertions
            if (group == null)
                throw Exceptions.A0_CannotBeNull("group");

            if ((group.Document != null) && (group.Document != this))
                throw Exceptions.A0_IsAlreadyAssignedToAnother_A1("group", "document");

            #endregion

            if (!_groups.Contains(group))
            {
            
                DocumentActionEventArgs e = new DocumentActionEventArgs(this, group, null);
                group.OnAddingToDocument(e);
                if (!e.Cancel)
                {
                    this.OnAddingGroup(e);
                    if (!e.Cancel)
                    {
                        _groups.Add(group);
                        group.Document = this;
                        _refreshItemsCache = true;
                        this.OnGroupAdded(e);
                        group.OnAddedToDocument(e);
                    }
                }
            }
        }

        /// <summary>
        /// Remove the specified item from the document items.
        /// </summary>
        /// <param name="item">The item to be removed.</param>
        public virtual void Remove(DocumentItem item)
        {

            DocumentGroup group = null;

            #region Find the group that contains the item
            foreach (DocumentGroup g in _groups)
            {
                if (g.Items.Contains(item))
                {
                    group = g;
                    break;
                }
            }
            #endregion

            #region Assertions
            if (group == null)
                throw Exceptions.A0_DoesNotBelongsToThis_A1("item", "document", typeof(ArgumentException));
            #endregion

            DocumentActionEventArgs e = new DocumentActionEventArgs(this, group, item);
            item.OnRemovingFromDocument(e);
            if (!e.Cancel)
            {
                group.OnRemovingItem(e);
                if (!e.Cancel)
                {
                    this.OnRemovingItem(e);
                    if (!e.Cancel)
                    {
                        item.Group = null;
                        group.Items.Remove(item);
                        _refreshItemsCache = true;
                        this.OnItemRemoved(e);
                        group.OnItemRemoved(e);
                        item.OnRemovedFromDocument(e);
                    }
                }
            }
        }

        /// <summary>
        /// Remove the specified group from the document groups.
        /// </summary>
        /// <param name="group">The group to be removed.</param>
        public virtual void Remove(DocumentGroup group)
        {

            #region Assertions
            if (group == null)
                throw Exceptions.A0_DoesNotBelongsToThis_A1("item", "document", typeof(ArgumentNullException));
            #endregion

            DocumentActionEventArgs e = new DocumentActionEventArgs(this, group, null);
            group.OnRemovingFromDocument(e);
            if (!e.Cancel)
            {
                this.OnRemovingGroup(e);
                if (!e.Cancel)
                {
                    group.Document = null;
                    _groups.Remove(group);
                    _refreshItemsCache = true;
                    this.OnGroupRemoved(e);
                    group.OnRemovedFromDocument(e);
                }
            }
        }

        #region Methods for saving/loading document
        /// <summary>
        /// Save the document to a file.
        /// </summary>
        /// <param name="fileName">The destination file.</param>
        public void SaveTo(string fileName)
        {
            DocumentManager.Save(this, fileName);
        }

        /// <summary>
        /// Load a document from a file.
        /// </summary>
        /// <param name="fileName">The source file.</param>
        /// <returns>The saved document.</returns>
        public static Document LoadFrom(string fileName)
        {            
            Document d = DocumentManager.Load(fileName);        
            return d;
        }

        /// <summary>
        /// Load a document from a stream.
        /// </summary>
        /// <param name="stream">The source stream.</param>
        /// <returns>The saved document.</returns>
        public static Document LoadFrom(StreamReader stream)
        {
            Document d = DocumentManager.Load(stream);
            return d;
        }
        

        public void LoadLibrary(string fileName)
        {
            try
            {

                string path = Path.GetDirectoryName(fileName);
                if (path.Length <= 0) 
                    fileName = Path.Combine(Path.GetDirectoryName(_fileName), fileName);
                
                // try looking at file under exefolder\Libraries
                if (!File.Exists(fileName))
                {
                    path = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Libraries");
                    fileName = Path.Combine(path, Path.GetFileName(fileName));
                }

                // check if another assembly with the same filename was already loaded.
                bool alreadyLoaded = false;
                foreach (DocumentLibrary dl in _libraries)
                    if (string.Compare(dl.FileName, Path.GetFileName(fileName), true) == 0)
                    {
                        alreadyLoaded = true;
                        break;
                    }

                if (!alreadyLoaded) 
                {
                    if (File.Exists(fileName))
                    {
                        Assembly asm = Assembly.LoadFile(fileName);
                        LoadLibraryEventArgs e = new LoadLibraryEventArgs(asm);
                        DocumentLibrary lib = new DocumentLibrary();
                        lib.Assembly = asm;
                        lib.FileName = Path.GetFileName(fileName);
                        _libraries.Add(lib);
                        OnLibraryLoaded(e);
                    }
                    else
                        throw new FileNotFoundException();
                }
            }
            catch (Exception ex) 
            {
                throw Exceptions.CannotLoad_A0(fileName, ex);
            }
        }

        #endregion

        #region Internal methods for saving/loading document
        internal void OnLoadingDocumentInternal()
        { OnLoadingDocument(); }

        internal void OnSavingDocumentInternal()
        { OnSavingDocument();  }

        internal void OnDocumentLoadedInternal()
        { OnDocumentLoaded();  }

        internal void OnDocumentSavedInternal()
        { OnDocumentSaved(); }
        #endregion

        #region Virtual methods for saving/loading document
        protected virtual void OnLoadingDocument()
        { }

        protected virtual void OnSavingDocument()
        { }

        protected virtual void OnDocumentLoaded()
        {
            _refreshItemsCache = true;
        }

        protected virtual void OnDocumentSaved()
        { }
        #endregion

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions