1. Darius Damalakas
  2. SourceGrid

Commits

Darius Damalakas  committed 76360ea

Renaming SourceGrid4 to SourceGrid

  • Participants
  • Parent commits 25aa76d
  • Branches default

Comments (4)

Files changed (627)

File SourceGrid/DevAge.Windows.Forms/ComponentModel/BoundDataView.cs

View file
  • Ignore whitespace
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace DevAge.ComponentModel
+{
+	/// <summary>
+	/// A class to support list binding to a DataView object.
+	/// Implement the IBoundList.
+	/// </summary>
+	[Serializable]
+	public class BoundDataView : IBoundList
+	{
+		private System.Data.DataView m_dataView;
+		private System.Data.DataTable m_dataTable;
+
+		[Obsolete("Use property DataView instead")]
+		public System.Data.DataView mDataView {
+			get { return mDataView; }
+		}
+		
+		[Obsolete("Use property DataTable instead")]
+		public System.Data.DataTable mDataTable {
+			get { return mDataTable; }
+		}
+		
+		public System.Data.DataView DataView {
+			get { return m_dataView; }
+		}
+		
+		public System.Data.DataTable DataTable {
+			get { return m_dataTable; }
+		}
+		
+
+		
+		public BoundDataView(System.Data.DataView dataView)
+		{
+			m_dataView = dataView;
+
+			m_dataView.ListChanged += new System.ComponentModel.ListChangedEventHandler(mDataView_ListChanged);
+			// Save it for destructor
+			m_dataTable = m_dataView.Table;
+			if ( m_dataTable != null )
+			{
+				m_dataTable.TableCleared += new System.Data.DataTableClearEventHandler(Table_TableCleared);
+				m_dataTable.RowDeleted += new System.Data.DataRowChangeEventHandler(Table_RowDeleted);
+			}
+		}
+
+		~BoundDataView()
+		{
+			if ( m_dataTable != null )
+			{
+				m_dataTable.TableCleared -= new System.Data.DataTableClearEventHandler(Table_TableCleared);
+				m_dataTable.RowDeleted -= new System.Data.DataRowChangeEventHandler(Table_RowDeleted);
+			}
+		}
+
+		public event System.ComponentModel.ListChangedEventHandler ListChanged;
+		protected virtual void OnListChanged(System.ComponentModel.ListChangedEventArgs e)
+		{
+			if (ListChanged != null)
+				ListChanged(this, e);
+		}
+		void mDataView_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
+		{
+			OnListChanged(e);
+		}
+
+		public event EventHandler ListCleared;
+		protected virtual void OnListCleared(EventArgs e)
+		{
+			if ( ListCleared != null )
+				ListCleared(this, e);
+		}
+		void Table_TableCleared ( object sender, System.Data.DataTableClearEventArgs e )
+		{
+			OnListCleared(EventArgs.Empty);
+		}
+
+		public event ItemDeletedEventHandler ItemDeleted;
+		protected virtual void OnItemDeleted(ItemDeletedEventArgs e)
+		{
+			if ( ItemDeleted != null )
+				ItemDeleted(this, e);
+		}
+		void Table_RowDeleted ( object sender, System.Data.DataRowChangeEventArgs e )
+		{
+			OnItemDeleted(new ItemDeletedEventArgs(e.Row));
+		}
+
+		private System.Data.DataRowView mEditingRow;
+		public virtual int BeginAddNew()
+		{
+			if (mEditingRow != null)
+				throw new DevAgeApplicationException("There is already a row in editing state, call EndEdit first");
+
+			mEditingRow = m_dataView.AddNew();
+
+			mEditingRow.BeginEdit();
+
+			System.Collections.IList list = (System.Collections.IList)m_dataView;
+
+			return list.IndexOf(mEditingRow);
+		}
+
+		public virtual void BeginEdit(int index)
+		{
+			if (mEditingRow != null)
+				throw new DevAgeApplicationException("There is already a row in editing state, call EndEdit first");
+
+			mEditingRow = m_dataView[index];
+
+			mEditingRow.BeginEdit();
+		}
+
+		public virtual void EndEdit(bool cancel)
+		{
+			if (mEditingRow == null)
+				return;
+
+			if (cancel)
+				mEditingRow.CancelEdit();
+			else
+				mEditingRow.EndEdit();
+
+			mEditingRow = null;
+
+			//when CancelEdit the DataView doesn't automatically call a ListChanged event, so I will call it manually
+			if (cancel)
+				OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, -1));
+		}
+
+		/// <summary>
+		/// Gets the current edited object
+		/// </summary>
+		public virtual object EditedObject
+		{
+			get { return mEditingRow; }
+		}
+
+		public virtual int IndexOf(object item)
+		{
+			System.Collections.IList list = (System.Collections.IList)m_dataView;
+
+			return list.IndexOf(item);
+		}
+
+		public virtual void RemoveAt(int index)
+		{
+			m_dataView[index].Delete();
+		}
+
+		public virtual object this[int index]
+		{
+			get
+			{
+				if ( index >= m_dataView.Table.Rows.Count)
+					throw new ArgumentException(string.Format(
+						"Data table does not have row with given index. It has only {0} number of rows," +
+						"you requested to return row number {1}",
+						m_dataView.Table.Rows.Count,
+						index));
+				try
+				{
+					return m_dataView[index];
+				}
+				catch (InvalidOperationException )
+				{
+					// we sometimes get this error. Don't know why. Maybe it is multithreading issue
+					// It says that internal index is corrupt, number 13.
+					// Return null in this case, works fine afaik
+					return null;
+				}
+			}
+		}
+
+		public virtual int Count
+		{
+			get { return m_dataView.Count; }
+		}
+
+		public virtual System.ComponentModel.PropertyDescriptorCollection GetItemProperties()
+		{
+			//Removed for mono compatibility
+			//return System.Windows.Forms.ListBindingHelper.GetListItemProperties(mDataView);
+			
+			if (m_dataView == null)
+				return new System.ComponentModel.PropertyDescriptorCollection(null);
+			else
+				return ((System.ComponentModel.ITypedList)m_dataView).GetItemProperties(null);
+		}
+
+		public System.ComponentModel.PropertyDescriptor GetItemProperty(string name, StringComparison comparison)
+		{
+			foreach (System.ComponentModel.PropertyDescriptor prop in GetItemProperties())
+			{
+				if (prop.Name.Equals(name, comparison))
+					return prop;
+			}
+
+			return null;
+		}
+
+		public virtual object GetItemValue(int index, System.ComponentModel.PropertyDescriptor property)
+		{
+			object dataVal = property.GetValue(m_dataView[index]);
+
+			//Convert DbNull to null
+			if (System.DBNull.Value == dataVal)
+				return null;
+			else
+				return dataVal;
+		}
+
+		public virtual void SetEditValue(System.ComponentModel.PropertyDescriptor property, object value)
+		{
+			//Convert the null value to DbNull
+			if (value == null)
+				value = System.DBNull.Value;
+
+			if (mEditingRow == null)
+				throw new DevAgeApplicationException("There isn't a row in editing state, call BeginAddNew or BeginEdit first");
+
+			property.SetValue(mEditingRow, value);
+		}
+
+		public virtual void ApplySort(System.ComponentModel.ListSortDescriptionCollection sorts)
+		{
+			System.ComponentModel.IBindingListView listView = (System.ComponentModel.IBindingListView)m_dataView;
+
+			if (sorts != null && sorts.Count > 0)
+				listView.ApplySort(sorts);
+			else
+				listView.RemoveSort();
+		}
+
+		private bool mAllowEdit = true;
+		public virtual bool AllowEdit
+		{
+			get { return m_dataView.AllowEdit && mAllowEdit; }
+			set { mAllowEdit = value; }
+		}
+
+		private bool mAllowNew = true;
+		public virtual bool AllowNew
+		{
+			get { return m_dataView.AllowNew && mAllowNew; }
+			set { mAllowNew = value; }
+		}
+
+		private bool mAllowDelete = true;
+		public virtual bool AllowDelete
+		{
+			get { return m_dataView.AllowDelete && mAllowDelete; }
+			set { mAllowDelete = value; }
+		}
+
+		private bool mAllowSort = true;
+		public virtual bool AllowSort
+		{
+			get { return mAllowSort; }
+			set { mAllowSort = value; }
+		}
+	}
+}

File SourceGrid/DevAge.Windows.Forms/ComponentModel/BoundList.cs

View file
  • Ignore whitespace
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.ComponentModel;
+
+namespace DevAge.ComponentModel
+{
+    /// <summary>
+    /// A class derived from BoundListBase that can be used to bind a list control (like SourceGrid) to a generic IList class.
+    /// If the IList is an instance of List class then also the Sort is supported.
+    /// Implement the IBoundList interface used for data binding.
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    [Serializable]
+    public class BoundList<T> : BoundListBase<T>
+    {
+		private IList<T> mList;
+
+        public BoundList(IList<T> list)
+        {
+            mList = list;
+
+            AllowNew = true;
+            AllowDelete = true;
+            AllowEdit = true;
+            AllowSort = mList is List<T>;
+        }
+
+        protected override T OnAddNew()
+        {
+            T editItem = Activator.CreateInstance<T>();
+
+            mList.Add(editItem);
+
+            return editItem;
+        }
+
+        public override int IndexOf(object item)
+        {
+            return mList.IndexOf((T)item);
+        }
+
+        protected override void OnRemoveAt(int index)
+        {
+            mList.RemoveAt(index);
+        }
+
+		protected override void OnClear ()
+		{
+			mList.Clear();
+		}
+
+        public override object this[int index]
+        {
+            get { return mList[index]; }
+        }
+
+        public override int Count
+        {
+            get { return mList.Count; }
+        }
+
+        public override void ApplySort(System.ComponentModel.ListSortDescriptionCollection sorts)
+        {
+            List<T> sortableList = mList as List<T>;
+
+            if (sortableList == null)
+                throw new DevAgeApplicationException("Sort not supported, the list must be an instance of List<T>.");
+
+            sortableList.Sort(
+                delegate(T x, T y)
+                {
+                    foreach (System.ComponentModel.ListSortDescription sort in sorts)
+                    {
+                        IComparable valx = sort.PropertyDescriptor.GetValue(x) as IComparable;
+                        IComparable valy = sort.PropertyDescriptor.GetValue(y) as IComparable;
+
+                        //Swap the objects if the sort direction is Descending
+                        if (sort.SortDirection == ListSortDirection.Descending)
+                        {
+                            IComparable tmp = valx;
+                            valx = valy;
+                            valy = tmp;
+                        }
+
+                        if (valx != null && valy != null)
+                        {
+                            int result = valx.CompareTo(valy);
+                            if (result != 0)
+                                return result;
+                        }
+                        else if (valx != null)
+                            return 1;
+                        else
+                            return -1;
+                    }
+
+                    return 0;
+                }
+                );
+
+            OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, -1));
+        }
+	}
+}

File SourceGrid/DevAge.Windows.Forms/ComponentModel/BoundListBase.cs

View file
  • Ignore whitespace
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.ComponentModel;
+
+namespace DevAge.ComponentModel
+{
+    /// <summary>
+    /// An abstract class used for data binding. This class can be used as a base implementation of the IBoundList interface.
+    /// You can use the concreate classes BoundList or BoundDataView or a custom class.
+    /// To implement you own bound list class simply derive from this class and implement the abstract methods.
+    /// </summary>
+    [Serializable]
+    public abstract class BoundListBase<T> : IBoundList
+    {
+        private int mEditIndex;
+        private T mEditItem;
+        private bool mAdding = false;
+        private Dictionary<PropertyDescriptor, object> mPreviousValues = new Dictionary<PropertyDescriptor, object>();
+
+        public int BeginAddNew()
+        {
+            if (mEditItem != null)
+                throw new DevAgeApplicationException("There is already a row in editing state, call EndEdit first");
+
+            mEditItem = OnAddNew();
+
+            mEditIndex = Count - 1;
+
+            mAdding = true;
+
+            OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.ItemAdded, mEditIndex));
+
+            return mEditIndex;
+        }
+
+        public void BeginEdit(int index)
+        {
+            if (mEditItem != null)
+                throw new DevAgeApplicationException("There is already a row in editing state, call EndEdit first");
+
+            mEditItem = (T)this[index];
+            mEditIndex = index;
+        }
+
+        public void EndEdit(bool cancel)
+        {
+            if (mEditItem == null)
+                return;
+
+            //Cancel edit
+            if (cancel)
+            {
+                //Delete added value
+                if (mAdding)
+                    RemoveAt(mEditIndex);
+                else //restore edited values
+                {
+                    foreach (KeyValuePair<PropertyDescriptor, object> editVal in mPreviousValues)
+                    {
+                        editVal.Key.SetValue(mEditItem, editVal.Value);
+                    }
+                }
+            }
+            else //Apply edit
+            {
+                if (mAdding)
+                    mAddedItems.Add(mEditItem);
+                else
+                {
+                    //I consider the item edited only if not already edited or if is not a new item
+                    if (mEditedItems.Contains(mEditItem) == false &&
+                        mAddedItems.Contains(mEditItem) == false)
+                        mEditedItems.Add(mEditItem);
+                }
+            }
+
+
+            mEditItem = default(T);
+            mAdding = false;
+            mEditIndex = -1;
+            mPreviousValues.Clear();
+
+            OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, -1));
+        }
+
+        /// <summary>
+        /// Gets the current edited object
+        /// </summary>
+        public object EditedObject
+        {
+            get { return mEditItem; }
+        }
+
+        public void RemoveAt(int index)
+        {
+            T item = (T)this[index];
+
+            OnRemoveAt(index);
+
+            if (mAddedItems.Contains(item))
+                mAddedItems.Remove(item);
+            else
+            {
+                if (mEditedItems.Contains(item))
+                    mEditedItems.Remove(item);
+
+                mRemovedItems.Add(item);
+            }
+
+			OnItemDeleted(new ItemDeletedEventArgs(item));
+            OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.ItemDeleted, index));
+        }
+
+		/// <summary>
+		/// Clear all list items
+		/// </summary>
+		public void Clear()
+		{
+			mEditedItems.Clear();
+			mAddedItems.Clear();
+			mEditedItems.Clear();
+			mEditItem = default(T);
+			mAdding = false;
+			mEditIndex = -1;
+			mPreviousValues.Clear();
+			OnListCleared(EventArgs.Empty);
+			OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.Reset, -1));
+		}
+		
+
+        public System.ComponentModel.PropertyDescriptorCollection GetItemProperties()
+        {
+            return System.ComponentModel.TypeDescriptor.GetProperties(typeof(T));
+        }
+
+        public object GetItemValue(int index, System.ComponentModel.PropertyDescriptor property)
+        {
+            return property.GetValue(this[index]);
+        }
+
+        public void SetEditValue(System.ComponentModel.PropertyDescriptor property, object value)
+        {
+            if (mEditItem == null)
+                throw new DevAgeApplicationException("There isn't a row in editing state, call BeginAddNew or BeginEdit first");
+
+            //Save the previous value to enable the restore if the user cancel the editing
+            if (mPreviousValues.ContainsKey(property) == false)
+                mPreviousValues.Add(property, property.GetValue(mEditItem));
+
+            property.SetValue(mEditItem, value);
+
+            OnListChanged(new System.ComponentModel.ListChangedEventArgs(System.ComponentModel.ListChangedType.ItemChanged, mEditIndex, property));
+        }
+
+        private bool mAllowEdit = false;
+        public bool AllowEdit
+        {
+            get { return mAllowEdit; }
+            set { mAllowEdit = value; }
+        }
+
+        private bool mAllowNew = false;
+        public bool AllowNew
+        {
+            get { return mAllowNew; }
+            set { mAllowNew = value; }
+        }
+
+        private bool mAllowDelete = false;
+        public bool AllowDelete
+        {
+            get { return mAllowDelete; }
+            set { mAllowDelete = value; }
+        }
+
+        private bool mAllowSort = false;
+        /// <summary>
+        /// Gets or sets if the sort is enabled. Usually is enabled only if the IList is an instance of List class
+        /// </summary>
+        public bool AllowSort
+        {
+            get { return mAllowSort; }
+            set { mAllowSort = value; }
+        }
+
+        private List<T> mAddedItems = new List<T>();
+        public List<T> AddedItems
+        {
+            get { return mAddedItems; }
+        }
+
+        private List<T> mRemovedItems = new List<T>();
+        public List<T> RemovedItems
+        {
+            get { return mRemovedItems; }
+        }
+
+        private List<T> mEditedItems = new List<T>();
+        public List<T> EditedItems
+        {
+            get { return mEditedItems; }
+        }
+
+        /// <summary>
+        /// Get an item property by name
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        public System.ComponentModel.PropertyDescriptor GetItemProperty(string name, StringComparison comparison)
+        {
+            foreach (System.ComponentModel.PropertyDescriptor prop in GetItemProperties())
+            {
+                if (prop.Name.Equals(name, comparison))
+                    return prop;
+            }
+
+            return null;
+        }
+
+        public event System.ComponentModel.ListChangedEventHandler ListChanged;
+        protected virtual void OnListChanged(System.ComponentModel.ListChangedEventArgs e)
+        {
+            if (ListChanged != null)
+                ListChanged(this, e);
+        }
+
+		public event EventHandler ListCleared;
+		protected virtual void OnListCleared ( EventArgs e )
+		{
+			if ( ListCleared != null )
+				ListCleared(this, e);
+		}
+
+		public event ItemDeletedEventHandler ItemDeleted;
+		protected virtual void OnItemDeleted ( ItemDeletedEventArgs e )
+		{
+			if ( ItemDeleted != null )
+				ItemDeleted(this, e);
+		}
+
+        #region Abstract methods
+        /// <summary>
+        /// Create a new item (row) add it at the end of the list and return the new item.
+        /// </summary>
+        /// <returns></returns>
+        protected abstract T OnAddNew();
+        /// <summary>
+        /// Return the index of the specified item
+        /// </summary>
+        /// <param name="item"></param>
+        /// <returns></returns>
+        public abstract int IndexOf(object item);
+        /// <summary>
+        /// Remove the item at the specified position.
+        /// </summary>
+        /// <param name="index"></param>
+        protected abstract void OnRemoveAt(int index);
+        /// <summary>
+        /// Remove all items.
+        /// </summary>
+        protected abstract void OnClear();
+        /// <summary>
+        /// Return the item at the specified position.
+        /// </summary>
+        /// <param name="index"></param>
+        /// <returns></returns>
+        public abstract object this[int index]
+        {
+            get;
+        }
+        /// <summary>
+        /// Return the row count of the list
+        /// </summary>
+        public abstract int Count
+        {
+            get;
+        }
+        /// <summary>
+        /// Sort the list
+        /// </summary>
+        /// <param name="sorts"></param>
+        public abstract void ApplySort(System.ComponentModel.ListSortDescriptionCollection sorts);
+		#endregion
+    }
+}

File SourceGrid/DevAge.Windows.Forms/ComponentModel/IBoundList.cs

View file
  • Ignore whitespace
+using System;
+namespace DevAge.ComponentModel
+{
+    /// <summary>
+    /// A generic binded list interface. See BoundDataView or BoundList for a concreate implementation.
+    /// It is used as an abstraction layer for list objects (typically a list can be a DataView or a IList class)
+    /// Can be used to bind a list control (like SourceGrid).
+    /// </summary>
+    public interface IBoundList
+    {
+        bool AllowDelete { get; set; }
+        bool AllowEdit { get; set; }
+        bool AllowNew { get; set; }
+        bool AllowSort { get; set; }
+        void ApplySort(System.ComponentModel.ListSortDescriptionCollection sorts);
+        int BeginAddNew();
+        void BeginEdit(int index);
+        int Count { get; }
+        object EditedObject { get; }
+        void EndEdit(bool cancel);
+        System.ComponentModel.PropertyDescriptorCollection GetItemProperties();
+        System.ComponentModel.PropertyDescriptor GetItemProperty(string name, StringComparison comparison);
+        object GetItemValue(int index, System.ComponentModel.PropertyDescriptor property);
+        int IndexOf(object item);
+        event System.ComponentModel.ListChangedEventHandler ListChanged;
+        void RemoveAt(int index);
+        void SetEditValue(System.ComponentModel.PropertyDescriptor property, object value);
+        object this[int index] { get; }
+		
+        event EventHandler ListCleared;
+		event ItemDeletedEventHandler ItemDeleted;
+	}
+
+	/// <summary>
+	/// Item deletion event handler.
+	/// </summary>
+	/// <param name="sender">Event sender.</param>
+	/// <param name="e">Event arguments.</param>
+	public delegate void ItemDeletedEventHandler ( object sender, ItemDeletedEventArgs e );
+
+	/// <summary>
+	/// Event arguments for item deletion event.
+	/// </summary>
+	public class ItemDeletedEventArgs : EventArgs
+	{
+		private object mItem;
+
+		public object Item
+		{
+			get { return mItem; }
+			set { mItem = value; }
+		}
+
+		public ItemDeletedEventArgs(object item)
+		{
+			mItem = item;
+		}
+	}
+}

File SourceGrid/DevAge.Windows.Forms/Drawing/AnchorArea.cs

View file
  • Ignore whitespace
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.ComponentModel;
+using System.Drawing;
+
+namespace DevAge.Drawing
+{
+    //[TypeConverter(typeof(AnchorAreaConverter))]
+    //[ODL.SerializationMode(ODL.DefinitionType.ComplexTypeFields)]
+    /// <summary>
+    /// The AnchorArea class is used to specify the anchor properties of an object.
+    /// You can set to align the content to the left, right, top or bottom using the relative properties (Left, Right, Top, Bottom).
+    /// You can also set more than one properties to allign the content to more than one side.
+    /// Use float.NaN to set a null value for one of the properties.
+    /// </summary>
+    [Serializable]
+    public class AnchorArea : ICloneable, IComparable
+    {
+        /// <summary>
+        /// Default is constructor
+        /// </summary>
+        public AnchorArea()
+        {
+        }
+
+        /// <summary>
+        /// Construct an anchor area object
+        /// </summary>
+        /// <param name="left"></param>
+        /// <param name="top"></param>
+        /// <param name="right"></param>
+        /// <param name="bottom"></param>
+        /// <param name="center"></param>
+        /// <param name="middle"></param>
+        public AnchorArea(float left, float top, float right, float bottom, bool center, bool middle)
+        {
+            Left = left;
+            Top = top;
+            Right = right;
+            Bottom = bottom;
+            Center = center;
+            Middle = middle;
+        }
+
+        /// <summary>
+        /// Copy constructor
+        /// </summary>
+        /// <param name="other"></param>
+        public AnchorArea(AnchorArea other)
+        {
+            Right = other.Right;
+            Left = other.Left;
+            Bottom = other.Bottom;
+            Top = other.Top;
+            Center = other.Center;
+            Middle = other.Middle;
+        }
+
+        /// <summary>
+        /// Constructo an anchorarea class based on the aligment and the stretch parameters.
+        /// </summary>
+        /// <param name="aligment"></param>
+        /// <param name="stretch"></param>
+        public AnchorArea(ContentAlignment aligment, bool stretch)
+        {
+            if (Utilities.IsBottom(aligment) || stretch)
+                Bottom = 0;
+            if (Utilities.IsLeft(aligment) || stretch)
+                Left = 0;
+            if (Utilities.IsRight(aligment) || stretch)
+                Right = 0;
+            if (Utilities.IsTop(aligment) || stretch)
+                Top = 0;
+
+            if (Utilities.IsCenter(aligment) && stretch == false)
+                Center = true;
+            if (Utilities.IsMiddle(aligment) && stretch == false)
+                Middle = true;
+        }
+
+        public static AnchorArea Empty
+        {
+            get { return new AnchorArea(); }
+        }
+
+        public bool IsEmpty
+        {
+            get { return HasRight == false && HasLeft == false && 
+                        HasTop == false && HasBottom == false && 
+                        Middle == false && Center == false; }
+        }
+
+        [DefaultValue(float.NaN)]
+        public float Right = float.NaN;
+
+        [DefaultValue(float.NaN)]
+        public float Left = float.NaN;
+
+        [DefaultValue(false)]
+        public bool Center;
+
+        [DefaultValue(float.NaN)]
+        public float Top = float.NaN;
+
+        [DefaultValue(float.NaN)]
+        public float Bottom = float.NaN;
+
+        [DefaultValue(false)]
+        public bool Middle;
+
+        public bool HasRight
+        {
+            get { return float.IsNaN(Right) == false; }
+        }
+        public bool HasLeft
+        {
+            get { return float.IsNaN(Left) == false; }
+        }
+        public bool HasTop
+        {
+            get { return float.IsNaN(Top) == false; }
+        }
+        public bool HasBottom
+        {
+            get { return float.IsNaN(Bottom) == false; }
+        }
+
+        public override string ToString()
+        {
+            return "Top " + Top.ToString() + ", " +
+                "Bottom " + Bottom.ToString() + ", " +
+                "Right " + Right.ToString() + ", " +
+                "Left " + Left.ToString();
+        }
+
+        public override int GetHashCode()
+        {
+            return (int)(Top + Bottom + Left + Right);
+        }
+
+        public override bool Equals(object obj)
+        {
+            return CompareTo(obj) == 0;
+        }
+
+        #region ICloneable Members
+
+        public object Clone()
+        {
+            return new AnchorArea(this);
+        }
+
+        #endregion
+
+        #region IComparable Members
+
+        public int CompareTo(object obj)
+        {
+            if (obj == null)
+                return 1;
+            
+            if (!(obj is AnchorArea))
+                throw new ArgumentException("Invalid object, AnchorArea expected");
+
+            AnchorArea other = (AnchorArea)obj;
+
+            int topCompare = Top.CompareTo(other.Top);
+            int bottomCompare = Bottom.CompareTo(other.Bottom);
+            int leftCompare = Left.CompareTo(other.Left);
+            int rightCompare = Right.CompareTo(other.Right);
+            int centerCompare = Center.CompareTo(other.Center);
+            int middleCompare = Middle.CompareTo(other.Middle);
+
+            if (topCompare > 1)
+                return 1;
+            else if (topCompare < 1)
+                return -1;
+            else
+            {
+                if (bottomCompare > 1)
+                    return 1;
+                else if (bottomCompare < 1)
+                    return -1;
+                else
+                {
+                    if (rightCompare > 1)
+                        return 1;
+                    else if (rightCompare < 1)
+                        return -1;
+                    else
+                    {
+                        if (leftCompare > 1)
+                            return 1;
+                        else if (leftCompare < 1)
+                            return -1;
+                        else
+                        {
+                            if (centerCompare > 1)
+                                return 1;
+                            else if (centerCompare < 1)
+                                return -1;
+                            else
+                            {
+                                if (middleCompare > 1)
+                                    return 1;
+                                else if (middleCompare < 1)
+                                    return -1;
+                                else
+                                {
+                                    return 0;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+        }
+
+        #endregion
+
+        public static bool operator ==(AnchorArea a, AnchorArea b)
+        {
+            // If both are null, or both are same instance, return true.
+            if (System.Object.ReferenceEquals(a, b))
+            {
+                return true;
+            }
+
+            // If one is null, but not both, return false.
+            if (((object)a == null) || ((object)b == null))
+            {
+                return false;
+            }
+
+            // Return true if the fields match:
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(AnchorArea a, AnchorArea b)
+        {
+            return !(a == b);
+        }
+
+        /// <summary>
+        /// Calculate the destination area of 
+        /// </summary>
+        /// <param name="area"></param>
+        /// <param name="content"></param>
+        /// <param name="anchor"></param>
+        /// <returns></returns>
+        public static RectangleF CalculateArea(RectangleF area, SizeF content, AnchorArea anchor)
+        {