//#########################################################################################
//★★★★★★★ http://www.cnpopsoft.com [华普软件] ★★★★★★★
//★★★★★★★ 华普软件 - VB & C#.NET 专业论文与源码荟萃! ★★★★★★★
//#########################################################################################
/*
* Copyright ?2005, Mathew Hall
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using XPTable.Editors;
using XPTable.Events;
using XPTable.Models.Design;
using XPTable.Renderers;
namespace XPTable.Models
{
///
/// Summary description for ColumnModel.
///
[DesignTimeVisible(true),
ToolboxItem(true),
ToolboxBitmap(typeof(ColumnModel))]
public class ColumnModel : Component
{
#region EventHandlers
///
/// Occurs when a Column has been added to the ColumnModel
///
public event ColumnModelEventHandler ColumnAdded;
///
/// Occurs when a Column is removed from the ColumnModel
///
public event ColumnModelEventHandler ColumnRemoved;
///
/// Occurs when the value of the HeaderHeight property changes
///
public event EventHandler HeaderHeightChanged;
#endregion
#region Class Data
///
/// The default height of a column header
///
public static readonly int DefaultHeaderHeight = 20;
///
/// The minimum height of a column header
///
public static readonly int MinimumHeaderHeight = 16;
///
/// The maximum height of a column header
///
public static readonly int MaximumHeaderHeight = 128;
///
/// The collection of Column's contained in the ColumnModel
///
private ColumnCollection columns;
///
/// The list of all default CellRenderers used by the Columns in the ColumnModel
///
private Hashtable cellRenderers;
///
/// The list of all default CellEditors used by the Columns in the ColumnModel
///
private Hashtable cellEditors;
///
/// The Table that the ColumnModel belongs to
///
private Table table;
///
/// The height of the column headers
///
private int headerHeight;
#endregion
#region Constructor
///
/// Initializes a new instance of the ColumnModel class with default settings
///
public ColumnModel()
{
this.Init();
}
///
/// Initializes a new instance of the ColumnModel class with an array of strings
/// representing TextColumns
///
/// An array of strings that represent the Columns of
/// the ColumnModel
public ColumnModel(string[] columns)
{
if (columns == null)
{
throw new ArgumentNullException("columns", "string[] cannot be null");
}
this.Init();
if (columns.Length > 0)
{
Column[] cols = new Column[columns.Length];
for (int i=0; i
/// Initializes a new instance of the Row class with an array of Column objects
///
/// An array of Cell objects that represent the Columns
/// of the ColumnModel
public ColumnModel(Column[] columns)
{
if (columns == null)
{
throw new ArgumentNullException("columns", "Column[] cannot be null");
}
this.Init();
if (columns.Length > 0)
{
this.Columns.AddRange(columns);
}
}
///
/// Initialise default settings
///
private void Init()
{
this.columns = null;
this.table = null;
this.headerHeight = ColumnModel.DefaultHeaderHeight;
this.cellRenderers = new Hashtable();
this.SetCellRenderer("TEXT", new TextCellRenderer());
this.cellEditors = new Hashtable();
this.SetCellEditor("TEXT", new TextCellEditor());
}
#endregion
#region Methods
#region Coordinate Translation
///
/// Returns the index of the Column that lies on the specified position
///
/// The x-coordinate to check
/// The index of the Column or -1 if no Column is found
public int ColumnIndexAtX(int xPosition)
{
if (xPosition < 0 || xPosition > this.VisibleColumnsWidth)
{
return -1;
}
for (int i=0; i
/// Returns the Column that lies on the specified position
///
/// The x-coordinate to check
/// The Column that lies on the specified position,
/// or null if not found
public Column ColumnAtX(int xPosition)
{
if (xPosition < 0 || xPosition > this.VisibleColumnsWidth)
{
return null;
}
int index = this.ColumnIndexAtX(xPosition);
if (index != -1)
{
return this.Columns[index];
}
return null;
}
///
/// Returns a rectangle that countains the header of the column
/// at the specified index in the ColumnModel
///
/// The index of the column
/// that countains the header of the specified column
public Rectangle ColumnHeaderRect(int index)
{
// make sure the index is valid and the column is not hidden
if (index < 0 || index >= this.Columns.Count || !this.Columns[index].Visible)
{
return Rectangle.Empty;
}
return new Rectangle(this.Columns[index].Left, 0, this.Columns[index].Width, this.HeaderHeight);
}
///
/// Returns a rectangle that countains the header of the specified column
///
/// The column
/// A rectangle that countains the header of the specified column
public Rectangle ColumnHeaderRect(Column column)
{
// check if we actually own the column
int index = this.Columns.IndexOf(column);
if (index == -1)
{
return Rectangle.Empty;
}
return this.ColumnHeaderRect(index);
}
#endregion
#region Dispose
///
/// Releases the unmanaged resources used by the ColumnModel and optionally
/// releases the managed resources
///
protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}
#endregion
#region Editors
///
/// Returns the ICellEditor that is associated with the specified name
///
/// The name thst is associated with an ICellEditor
/// The ICellEditor that is associated with the specified name,
/// or null if the name or ICellEditor do not exist
public ICellEditor GetCellEditor(string name)
{
if (name == null || name.Length == 0)
{
return null;
}
name = name.ToUpper();
if (!this.cellEditors.ContainsKey(name))
{
if (this.cellEditors.Count == 0)
{
this.SetCellEditor("TEXT", new TextCellEditor());
}
return null;
}
return (ICellEditor) this.cellEditors[name];
}
///
/// Gets the ICellEditor for the Column at the specified index in the
/// ColumnModel
///
/// The index of the Column in the ColumnModel for
/// which an ICellEditor will be retrieved
/// The ICellEditor for the Column at the specified index, or
/// null if the editor does not exist
public ICellEditor GetCellEditor(int column)
{
if (column < 0 || column >= this.Columns.Count)
{
return null;
}
//
if (this.Columns[column].Editor != null)
{
return this.Columns[column].Editor;
}
return this.GetCellEditor(this.Columns[column].GetDefaultEditorName());
}
///
/// Associates the specified ICellRenderer with the specified name
///
/// The name to be associated with the specified ICellEditor
/// The ICellEditor to be added to the ColumnModel
public void SetCellEditor(string name, ICellEditor editor)
{
if (name == null || name.Length == 0 || editor == null)
{
return;
}
name = name.ToUpper();
if (this.cellEditors.ContainsKey(name))
{
this.cellEditors.Remove(name);
this.cellEditors[name] = editor;
}
else
{
this.cellEditors.Add(name, editor);
}
}
///
/// Gets whether the ColumnModel contains an ICellEditor with the
/// specified name
///
/// The name associated with the ICellEditor
/// true if the ColumnModel contains an ICellEditor with the
/// specified name, false otherwise
public bool ContainsCellEditor(string name)
{
if (name == null)
{
return false;
}
return this.cellEditors.ContainsKey(name);
}
///
/// Gets the number of ICellEditors contained in the ColumnModel
///
internal int EditorCount
{
get
{
return this.cellEditors.Count;
}
}
#endregion
#region Renderers
///
/// Returns the ICellRenderer that is associated with the specified name
///
/// The name thst is associated with an ICellEditor
/// The ICellRenderer that is associated with the specified name,
/// or null if the name or ICellRenderer do not exist
public ICellRenderer GetCellRenderer(string name)
{
if (name == null)
{
name = "TEXT";
}
name = name.ToUpper();
if (!this.cellRenderers.ContainsKey(name))
{
if (this.cellRenderers.Count == 0)
{
this.SetCellRenderer("TEXT", new TextCellRenderer());
}
return (ICellRenderer) this.cellRenderers["TEXT"];
}
return (ICellRenderer) this.cellRenderers[name];
}
///
/// Gets the ICellRenderer for the Column at the specified index in the
/// ColumnModel
///
/// The index of the Column in the ColumnModel for
/// which an ICellRenderer will be retrieved
/// The ICellRenderer for the Column at the specified index, or
/// null if the renderer does not exist
public ICellRenderer GetCellRenderer(int column)
{
//
if (column < 0 || column >= this.Columns.Count)
{
return null;
}
//
if (this.Columns[column].Renderer != null)
{
return this.Columns[column].Renderer;
}
//
return this.GetCellRenderer(this.Columns[column].GetDefaultRendererName());
}
///
/// Associates the specified ICellRenderer with the specified name
///
/// The name to be associated with the specified ICellRenderer
/// The ICellRenderer to be added to the ColumnModel
public void SetCellRenderer(string name, ICellRenderer renderer)
{
if (name == null || renderer == null)
{
return;
}
name = name.ToUpper();
if (this.cellRenderers.ContainsKey(name))
{
this.cellRenderers.Remove(name);
this.cellRenderers[name] = renderer;
}
else
{
this.cellRenderers.Add(name, renderer);
}
}
///
/// Gets whether the ColumnModel contains an ICellRenderer with the
/// specified name
///
/// The name associated with the ICellRenderer
/// true if the ColumnModel contains an ICellRenderer with the
/// specified name, false otherwise
public bool ContainsCellRenderer(string name)
{
if (name == null)
{
return false;
}
return this.cellRenderers.ContainsKey(name);
}
///
/// Gets the number of ICellRenderers contained in the ColumnModel
///
internal int RendererCount
{
get
{
return this.cellRenderers.Count;
}
}
#endregion
#region Utility Methods
///
/// Returns the index of the first visible Column that is to the
/// left of the Column at the specified index in the ColumnModel
///
/// The index of the Column for which the first
/// visible Column that is to the left of the specified Column is to
/// be found
/// the index of the first visible Column that is to the
/// left of the Column at the specified index in the ColumnModel, or
/// -1 if the Column at the specified index is the first visible column,
/// or there are no Columns in the Column model
public int PreviousVisibleColumn(int index)
{
if (this.Columns.Count == 0)
{
return -1;
}
if (index <= 0)
{
return -1;
}
if (index >= this.Columns.Count)
{
if (this.Columns[this.Columns.Count-1].Visible)
{
return this.Columns.Count - 1;
}
index = this.Columns.Count - 1;
}
for (int i=index; i>0; i--)
{
if (this.Columns[i-1].Visible)
{
return i - 1;
}
}
return -1;
}
///
/// Returns the index of the first visible Column that is to the
/// right of the Column at the specified index in the ColumnModel
///
/// The index of the Column for which the first
/// visible Column that is to the right of the specified Column is to
/// be found
/// the index of the first visible Column that is to the
/// right of the Column at the specified index in the ColumnModel, or
/// -1 if the Column at the specified index is the last visible column,
/// or there are no Columns in the Column model
public int NextVisibleColumn(int index)
{
if (this.Columns.Count == 0)
{
return -1;
}
if (index >= this.Columns.Count - 1)
{
return -1;
}
for (int i=index; i
/// A ColumnCollection representing the collection of
/// Columns contained within the ColumnModel
///
[Category("Behavior"),
Description("Column Collection"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(ColumnCollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
public ColumnCollection Columns
{
get
{
if (this.columns == null)
{
this.columns = new ColumnCollection(this);
}
return this.columns;
}
}
///
/// Gets or sets the height of the column headers
///
[Category("Appearance"),
Description("The height of the column headers")]
public int HeaderHeight
{
get
{
return this.headerHeight;
}
set
{
if (value < ColumnModel.MinimumHeaderHeight)
{
value = ColumnModel.MinimumHeaderHeight;
}
else if (value > ColumnModel.MaximumHeaderHeight)
{
value = ColumnModel.MaximumHeaderHeight;
}
if (this.headerHeight != value)
{
this.headerHeight = value;
this.OnHeaderHeightChanged(EventArgs.Empty);
}
}
}
///
/// Specifies whether the HeaderHeight property should be serialized at
/// design time
///
/// true if the HeaderHeight property should be serialized,
/// false otherwise
private bool ShouldSerializeHeaderHeight()
{
return this.headerHeight != ColumnModel.DefaultHeaderHeight;
}
///
/// Gets a rectangle that specifies the width and height of all the
/// visible column headers in the model
///
[Browsable(false)]
public Rectangle HeaderRect
{
get
{
if (this.VisibleColumnCount == 0)
{
return Rectangle.Empty;
}
return new Rectangle(0, 0, this.VisibleColumnsWidth, this.HeaderHeight);
}
}
///
/// Gets the total width of all the Columns in the model
///
[Browsable(false)]
public int TotalColumnWidth
{
get
{
return this.Columns.TotalColumnWidth;
}
}
///
/// Gets the total width of all the visible Columns in the model
///
[Browsable(false)]
public int VisibleColumnsWidth
{
get
{
return this.Columns.VisibleColumnsWidth;
}
}
///
/// Gets the index of the last Column that is not hidden
///
[Browsable(false)]
public int LastVisibleColumnIndex
{
get
{
return this.Columns.LastVisibleColumn;
}
}
///
/// Gets the number of Columns in the ColumnModel that are visible
///
[Browsable(false)]
public int VisibleColumnCount
{
get
{
return this.Columns.VisibleColumnCount;
}
}
///
/// Gets the Table the ColumnModel belongs to
///
[Browsable(false)]
public Table Table
{
get
{
return this.table;
}
}
///
/// Gets or sets the Table the ColumnModel belongs to
///
internal Table InternalTable
{
get
{
return this.table;
}
set
{
this.table = value;
}
}
///
/// Gets whether the ColumnModel is able to raise events
///
protected internal bool CanRaiseEvents
{
get
{
// check if the Table that the ColumModel belongs to is able to
// raise events (if it can't, the ColumModel shouldn't raise
// events either)
if (this.Table != null)
{
return this.Table.CanRaiseEvents;
}
return true;
}
}
///
/// Gets whether the ColumnModel is enabled
///
internal bool Enabled
{
get
{
if (this.Table == null)
{
return true;
}
return this.Table.Enabled;
}
}
#endregion
#region Events
///
/// Raises the ColumnAdded event
///
/// A ColumnModelEventArgs that contains the event data
protected internal virtual void OnColumnAdded(ColumnModelEventArgs e)
{
e.Column.ColumnModel = this;
if (!this.ContainsCellRenderer(e.Column.GetDefaultRendererName()))
{
this.SetCellRenderer(e.Column.GetDefaultRendererName(), e.Column.CreateDefaultRenderer());
}
if (!this.ContainsCellEditor(e.Column.GetDefaultEditorName()))
{
this.SetCellEditor(e.Column.GetDefaultEditorName(), e.Column.CreateDefaultEditor());
}
if (this.CanRaiseEvents)
{
if (this.Table != null)
{
this.Table.OnColumnAdded(e);
}
if (ColumnAdded != null)
{
ColumnAdded(this, e);
}
}
}
///
/// Raises the ColumnRemoved event
///
/// A ColumnModelEventArgs that contains the event data
protected internal virtual void OnColumnRemoved(ColumnModelEventArgs e)
{
if (e.Column != null && e.Column.ColumnModel == this)
{
e.Column.ColumnModel = null;
}
if (this.CanRaiseEvents)
{
if (this.Table != null)
{
this.Table.OnColumnRemoved(e);
}
if (ColumnRemoved != null)
{
ColumnRemoved(this, e);
}
}
}
///
/// Raises the HeaderHeightChanged event
///
/// An EventArgs that contains the event data
protected virtual void OnHeaderHeightChanged(EventArgs e)
{
if (this.CanRaiseEvents)
{
if (this.Table != null)
{
this.Table.OnHeaderHeightChanged(e);
}
if (HeaderHeightChanged != null)
{
HeaderHeightChanged(this, e);
}
}
}
///
/// Raises the ColumnPropertyChanged event
///
/// A ColumnEventArgs that contains the event data
internal void OnColumnPropertyChanged(ColumnEventArgs e)
{
if (e.EventType == ColumnEventType.WidthChanged || e.EventType == ColumnEventType.VisibleChanged)
{
this.Columns.RecalcWidthCache();
}
if (this.CanRaiseEvents)
{
if (this.Table != null)
{
this.Table.OnColumnPropertyChanged(e);
}
}
}
#endregion
}
}