//######################################################################################### //★★★★★★★ 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.ComponentModel; using System.Drawing; using System.Windows.Forms; using XPTable.Editors; using XPTable.Events; using XPTable.Models; using XPTable.Themes; namespace XPTable.Renderers { /// /// A base class for drawing Cells contents as numbers /// public class NumberCellRenderer : CellRenderer { #region Class Data /// /// The width of the ComboBox's dropdown button /// private int buttonWidth; /// /// Specifies whether the up and down buttons should be drawn /// private bool showUpDownButtons; /// /// The alignment of the up and down buttons in the Cell /// private LeftRightAlignment upDownAlignment; /// /// The maximum value for the Cell /// private decimal maximum; /// /// The minimum value for the Cell /// private decimal minimum; #endregion #region Constructor /// /// Initializes a new instance of the NumberCellRenderer class with /// default settings /// public NumberCellRenderer() : base() { this.StringFormat.Trimming = StringTrimming.None; this.Format = "G"; this.buttonWidth = 15; this.showUpDownButtons = false; this.upDownAlignment = LeftRightAlignment.Right; this.maximum = (decimal) 100; this.minimum = (decimal) 0; } #endregion #region Methods /// /// Returns a Rectangle that specifies the size and location of the /// up and down buttons /// /// A Rectangle that specifies the size and location of the /// up and down buttons protected Rectangle CalcButtonBounds() { Rectangle buttonRect = this.ClientRectangle; buttonRect.Width = this.ButtonWidth; if (this.UpDownAlign == LeftRightAlignment.Right) { buttonRect.X = this.ClientRectangle.Right - buttonRect.Width; } if (buttonRect.Width > this.ClientRectangle.Width) { buttonRect = this.ClientRectangle; } return buttonRect; } /// /// Returns a Rectangle that specifies the size and location of the up button /// /// A Rectangle that specifies the size and location of the up button protected Rectangle GetUpButtonBounds() { Rectangle buttonRect = this.CalcButtonBounds(); buttonRect.Height /= 2; return buttonRect; } /// /// Returns a Rectangle that specifies the size and location of the down button /// /// A Rectangle that specifies the size and location of the down button protected Rectangle GetDownButtonBounds() { Rectangle buttonRect = this.CalcButtonBounds(); int height = buttonRect.Height / 2; buttonRect.Height -= height; buttonRect.Y += height; return buttonRect; } /// /// Gets the NumberRendererData specific data used by the Renderer from /// the specified Cell /// /// The Cell to get the NumberRendererData data for /// The NumberRendererData data for the specified Cell protected NumberRendererData GetNumberRendererData(Cell cell) { object rendererData = this.GetRendererData(cell); if (rendererData == null || !(rendererData is NumberRendererData)) { rendererData = new NumberRendererData(); this.SetRendererData(cell, rendererData); } return (NumberRendererData) rendererData; } /// /// Gets whether the specified Table is using a NumericCellEditor to edit the /// Cell at the specified CellPos /// /// The Table to check /// A CellPos that represents the Cell to check /// true if the specified Table is using a NumericCellEditor to edit the /// Cell at the specified CellPos, false otherwise internal bool TableUsingNumericCellEditor(Table table, CellPos cellPos) { return (table.IsEditing && cellPos == table.EditingCell && table.EditingCellEditor is NumberCellEditor); } #endregion #region Properties /// /// Gets or sets the width of the dropdown button /// protected internal int ButtonWidth { get { return this.buttonWidth; } set { this.buttonWidth = value; } } /// /// Gets or sets whether the up and down buttons should be drawn /// protected bool ShowUpDownButtons { get { return this.showUpDownButtons; } set { this.showUpDownButtons = value; } } /// /// Gets or sets the alignment of the up and down buttons in the Cell /// protected LeftRightAlignment UpDownAlign { get { return this.upDownAlignment; } set { if (!Enum.IsDefined(typeof(LeftRightAlignment), value)) { throw new InvalidEnumArgumentException("value", (int) value, typeof(LeftRightAlignment)); } this.upDownAlignment = value; } } /// /// Gets or sets the maximum value for the Cell /// protected decimal Maximum { get { return this.maximum; } set { this.maximum = value; if (this.minimum > this.maximum) { this.minimum = this.maximum; } } } /// /// Gets or sets the minimum value for the Cell /// protected decimal Minimum { get { return this.minimum; } set { this.minimum = value; if (this.minimum > this.maximum) { this.maximum = value; } } } #endregion #region Events #region Mouse #region MouseLeave /// /// Raises the MouseLeave event /// /// A CellMouseEventArgs that contains the event data public override void OnMouseLeave(CellMouseEventArgs e) { base.OnMouseLeave(e); if (this.ShowUpDownButtons || this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { if (e.Table.IsCellEditable(e.CellPos)) { // get the button renderer data NumberRendererData rendererData = this.GetNumberRendererData(e.Cell); if (rendererData.UpButtonState != UpDownStates.Normal) { rendererData.UpButtonState = UpDownStates.Normal; e.Table.Invalidate(e.CellRect); } else if (rendererData.DownButtonState != UpDownStates.Normal) { rendererData.DownButtonState = UpDownStates.Normal; e.Table.Invalidate(e.CellRect); } } } } #endregion #region MouseUp /// /// Raises the MouseUp event /// /// A CellMouseEventArgs that contains the event data public override void OnMouseUp(CellMouseEventArgs e) { base.OnMouseUp(e); // if (this.ShowUpDownButtons || this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { if (e.Table.IsCellEditable(e.CellPos)) { // get the renderer data NumberRendererData rendererData = this.GetNumberRendererData(e.Cell); rendererData.ClickPoint = new Point(-1, -1); if (this.GetUpButtonBounds().Contains(e.X, e.Y)) { rendererData.UpButtonState = UpDownStates.Hot; if (!e.Table.IsEditing) { e.Table.EditCell(e.CellPos); } ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseUp(this, e); e.Table.Invalidate(e.CellRect); } else if (this.GetDownButtonBounds().Contains(e.X, e.Y)) { rendererData.DownButtonState = UpDownStates.Hot; if (!e.Table.IsEditing) { e.Table.EditCell(e.CellPos); } ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseUp(this, e); e.Table.Invalidate(e.CellRect); } } } } #endregion #region MouseDown /// /// Raises the MouseDown event /// /// A CellMouseEventArgs that contains the event data public override void OnMouseDown(CellMouseEventArgs e) { base.OnMouseDown(e); // if (this.ShowUpDownButtons || this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { if (e.Table.IsCellEditable(e.CellPos)) { // get the button renderer data NumberRendererData rendererData = this.GetNumberRendererData(e.Cell); rendererData.ClickPoint = new Point(e.X, e.Y); if (this.CalcButtonBounds().Contains(e.X, e.Y)) { if (!(e.Table.ColumnModel.GetCellEditor(e.CellPos.Column) is NumberCellEditor)) { throw new InvalidOperationException("Cannot edit Cell as NumberCellRenderer requires a NumberColumn that uses a NumberCellEditor"); } if (!e.Table.IsEditing) { e.Table.EditCell(e.CellPos); } if (this.GetUpButtonBounds().Contains(e.X, e.Y)) { rendererData.UpButtonState = UpDownStates.Pressed; ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseDown(this, e); e.Table.Invalidate(e.CellRect); } else if (this.GetDownButtonBounds().Contains(e.X, e.Y)) { rendererData.DownButtonState = UpDownStates.Pressed; ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseDown(this, e); e.Table.Invalidate(e.CellRect); } } } } } #endregion #region MouseMove /// /// Raises the MouseMove event /// /// A CellMouseEventArgs that contains the event data public override void OnMouseMove(XPTable.Events.CellMouseEventArgs e) { base.OnMouseMove(e); if (this.ShowUpDownButtons || this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { if (e.Table.IsCellEditable(e.CellPos)) { // get the button renderer data NumberRendererData rendererData = this.GetNumberRendererData(e.Cell); if (this.GetUpButtonBounds().Contains(e.X, e.Y)) { if (rendererData.UpButtonState == UpDownStates.Normal) { if (e.Button == MouseButtons.Left && e.Row == e.Table.LastMouseDownCell.Row && e.Column == e.Table.LastMouseDownCell.Column) { if (this.GetUpButtonBounds().Contains(rendererData.ClickPoint)) { rendererData.UpButtonState = UpDownStates.Pressed; if (this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseDown(this, e); } } else if (this.GetDownButtonBounds().Contains(rendererData.ClickPoint)) { rendererData.DownButtonState = UpDownStates.Normal; if (this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseUp(this, e); } } } else { rendererData.UpButtonState = UpDownStates.Hot; if (rendererData.DownButtonState == UpDownStates.Hot) { rendererData.DownButtonState = UpDownStates.Normal; } } e.Table.Invalidate(e.CellRect); } } else if (this.GetDownButtonBounds().Contains(e.X, e.Y)) { if (rendererData.DownButtonState == UpDownStates.Normal) { if (e.Button == MouseButtons.Left && e.Row == e.Table.LastMouseDownCell.Row && e.Column == e.Table.LastMouseDownCell.Column) { if (this.GetDownButtonBounds().Contains(rendererData.ClickPoint)) { rendererData.DownButtonState = UpDownStates.Pressed; if (this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseDown(this, e); } } else if (this.GetUpButtonBounds().Contains(rendererData.ClickPoint)) { rendererData.UpButtonState = UpDownStates.Normal; if (this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseUp(this, e); } } } else { rendererData.DownButtonState = UpDownStates.Hot; if (rendererData.UpButtonState == UpDownStates.Hot) { rendererData.UpButtonState = UpDownStates.Normal; } } e.Table.Invalidate(e.CellRect); } } else { if (rendererData.UpButtonState != UpDownStates.Normal || rendererData.DownButtonState != UpDownStates.Normal) { rendererData.UpButtonState = UpDownStates.Normal; rendererData.DownButtonState = UpDownStates.Normal; if (this.TableUsingNumericCellEditor(e.Table, e.CellPos)) { ((IEditorUsesRendererButtons) e.Table.EditingCellEditor).OnEditorButtonMouseUp(this, e); } e.Table.Invalidate(e.CellRect); } } } } } #endregion #endregion #region Paint /// /// Raises the PaintCell event /// /// A PaintCellEventArgs that contains the event data public override void OnPaintCell(PaintCellEventArgs e) { if (e.Table.ColumnModel.Columns[e.Column] is NumberColumn) { NumberColumn column = (NumberColumn) e.Table.ColumnModel.Columns[e.Column]; this.ShowUpDownButtons = column.ShowUpDownButtons; this.UpDownAlign = column.UpDownAlign; this.Maximum = column.Maximum; this.Minimum = column.Minimum; // if the table is editing this cell and the editor is a // NumberCellEditor then we should display the updown buttons if (e.Table.IsEditing && e.Table.EditingCell == e.CellPos && e.Table.EditingCellEditor is NumberCellEditor) { this.ShowUpDownButtons = true; } } else { this.ShowUpDownButtons = false; this.UpDownAlign = LeftRightAlignment.Right; this.Maximum = 100; this.Minimum = 0; } base.OnPaintCell(e); } /// /// Raises the PaintBackground event /// /// A PaintCellEventArgs that contains the event data protected override void OnPaintBackground(PaintCellEventArgs e) { base.OnPaintBackground(e); // don't bother going any further if the Cell is null if (e.Cell == null) { return; } if (this.ShowUpDownButtons) { UpDownStates upButtonState = this.GetNumberRendererData(e.Cell).UpButtonState; UpDownStates downButtonState = this.GetNumberRendererData(e.Cell).DownButtonState; if (!e.Enabled) { upButtonState = UpDownStates.Disabled; downButtonState = UpDownStates.Disabled; } ThemeManager.DrawUpDownButtons(e.Graphics, this.GetUpButtonBounds(), upButtonState, this.GetDownButtonBounds(), downButtonState); } } /// /// Raises the Paint event /// /// A PaintCellEventArgs that contains the event data protected override void OnPaint(PaintCellEventArgs e) { base.OnPaint(e); // don't bother if the Cell is null if (e.Cell == null) { return; } // get the Cells value decimal decimalVal = decimal.MinValue; if (e.Cell.Data != null && (e.Cell.Data is int || e.Cell.Data is double || e.Cell.Data is float || e.Cell.Data is decimal)) { decimalVal = Convert.ToDecimal(e.Cell.Data); } // draw the value if (decimalVal != decimal.MinValue) { Rectangle textRect = this.ClientRectangle; if (this.ShowUpDownButtons) { textRect.Width -= this.CalcButtonBounds().Width - 1; if (this.UpDownAlign == LeftRightAlignment.Left) { textRect.X = this.ClientRectangle.Right - textRect.Width; } } if (e.Enabled) { e.Graphics.DrawString(decimalVal.ToString(this.Format), this.Font, this.ForeBrush, textRect, this.StringFormat); } else { e.Graphics.DrawString(decimalVal.ToString(this.Format), this.Font, this.GrayTextBrush, textRect, this.StringFormat); } } if (e.Focused && e.Enabled) { Rectangle focusRect = this.ClientRectangle; if (this.ShowUpDownButtons) { focusRect.Width -= this.CalcButtonBounds().Width; if (this.UpDownAlign == LeftRightAlignment.Left) { focusRect.X = this.ClientRectangle.Right - focusRect.Width; } } ControlPaint.DrawFocusRectangle(e.Graphics, focusRect); } } #endregion #endregion } }