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