//######################################################################################### //★★★★★★★ 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 } }