using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace UserControls
{
#region CollapsePanel CLASS
/// <summary>
/// Provides an XP type Collapsible panel, that can be one of 2 states, collapsed or
/// expanded.
/// </summary>
public partial class CollapsePanel : Panel
{
#region Instance Fields
//instance fields
private Color titleBarTextColor = Color.Black;
private Color panelBorderColor = Color.Gray;
private Color titleBarStartColor = Color.SteelBlue;
private Color titleBarEndColor = Color.White;
private String titleText="Title1";
private Font titleBarFont = new Font(FontFamily.GenericSerif, 10.0f);
private System.Windows.Forms.ImageList imageList;
private int panelMinSize = 20;
private int oPanelHeight;
private int imageIndex = 0;
private const int imageBorder = 2;
private const int expandBorder = 4;
private int squareSize = 7;
private int squareBorder = 2;
private CollapsePanelCurrentState state = CollapsePanelCurrentState.Expanded;
/// <summary>
/// A CollapsePanelCurrentState changed event.
/// </summary>
[Category("State"),
Description("Raised when Panel state has changed.")]
public event CollapsePanelCurrentStateChangedEventHandler CollapsePanelCurrentStateChanged;
#endregion
#region Constructor
/// <summary>
/// Constructs a new CollapsePanel panel object
/// </summary>
public CollapsePanel()
{
InitializeComponent();
this.Paint += new PaintEventHandler(CollapsePanel_Paint);
this.MouseUp += new MouseEventHandler(CollapsePanel_MouseUp);
this.MouseMove += new MouseEventHandler(CollapsePanel_MouseMove);
this.Resize += new EventHandler(CollapsePanel_Resize);
this.Invalidate();
}
#endregion
#region Private Methods
/// <summary>
/// The resize event, that is fired when the CollapsePanel is resized
/// </summary>
/// <param name="sender">The CollapsePanel</param>
/// <param name="e">The event args</param>
private void CollapsePanel_Resize(object sender, EventArgs e)
{
this.Invalidate();
}
/// <summary>
/// The MouseMove event, that is fired when the CollapsePanel is mouse is moved
/// this is used to show different cursors dependant on mouse co-ordinates
/// </summary>
/// <param name="sender">The CollapsePanel</param>
/// <param name="e">The event args</param>
private void CollapsePanel_MouseMove(object sender, MouseEventArgs e)
{
//Change the cursor type dependant on the area that the user is hovering over with
//the mouse
if ((e.Button == MouseButtons.None) && (IsOverTitle(e.X, e.Y)))
{
this.Cursor = Cursors.Hand;
}
else
{
this.Cursor = Cursors.Default;
}
}
/// <summary>
/// The MouseUp event, that is fired when the CollapsePanel is mouse button is
/// released. This will either collapse the panel to expand it, depending on
/// its current state
/// this is used to show different cursors dependant on mouse co-ordinates
/// </summary>
/// <param name="sender">The CollapsePanel</param>
/// <param name="e">The event args</param>
private void CollapsePanel_MouseUp(object sender, MouseEventArgs e)
{
//was the click in the correct area to change the panel state
if ((e.Button == MouseButtons.Left) && (IsOverTitle(e.X, e.Y)))
{
if ((this.imageList != null) && (this.imageList.Images.Count >= 2))
{
if (this.imageIndex == 0)
{
// Currently expanded, so store the current height.
this.state = CollapsePanelCurrentState.Collapsed;
}
else
{
// Currently collapsed, so expand the oPanel.
this.state = CollapsePanelCurrentState.Expanded;
}
UpdateDisplayedState();
}
}
}
/// <summary>
/// The Paint event, that is fired when the CollapsePanel is painted. This
/// event paints the CollapsePanel using custom GDI+ painting methods
/// </summary>
/// <param name="sender">The CollapsePanel</param>
/// <param name="e">The event args</param>
private void CollapsePanel_Paint(object sender, PaintEventArgs e)
{
//draw the title area with correct colors
Graphics g = e.Graphics;
//draw the title panel area
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle recTitleBar = new Rectangle(0, 0, Width, panelMinSize);
LinearGradientBrush lbTitleBarColor = new LinearGradientBrush(
recTitleBar, titleBarStartColor, titleBarEndColor, LinearGradientMode.Horizontal);
g.FillRectangle(lbTitleBarColor, recTitleBar);
//draw 4 squares in border color
SolidBrush sbSquares = new SolidBrush(Color.White);
Rectangle recSquarePos = new Rectangle(Width - (squareSize + (squareBorder*2)), squareBorder, squareSize, squareSize);
g.FillRectangle(sbSquares, recSquarePos);
recSquarePos = new Rectangle(Width - (squareSize + (squareBorder * 2)), (squareBorder * 2) + squareSize, squareSize, squareSize);
g.FillRectangle(sbSquares, recSquarePos);
recSquarePos = new Rectangle(Width - (2*(squareSize + (squareBorder * 2))), squareBorder, squareSize, squareSize);
g.FillRectangle(sbSquares, recSquarePos);
recSquarePos = new Rectangle(Width - (2*(squareSize + (squareBorder * 2))), (squareBorder * 2) + squareSize, squareSize, squareSize);
g.FillRectangle(sbSquares, recSquarePos);
recSquarePos = new Rectangle(Width - (3*(squareSize + (squareBorder * 2))), squareBorder, squareSize, squareSize);
Pen pSquare = new Pen(sbSquares);
g.DrawRectangle(pSquare, recSquarePos);
// Draw the expand/collapse image
Image iState= ImageList.Images[(int)this.state];
g.DrawImage(iState, new Point(2,2));
//Draw the title text
Brush bTitleBarTextColor = new SolidBrush(TitleBarTextColor);
int xPos= iState.Width + (imageBorder*4);
int yPos=panelMinSize/2 - titleBarFont.Height/2;
g.DrawString(titleText, titleBarFont, bTitleBarTextColor, xPos, yPos);
//draw the title area border
Brush bPanelBorderColor = new SolidBrush(PanelBorderColor);
Pen pPanelBorderColor = new Pen(bPanelBorderColor);
Rectangle recTitleBarBorder = new Rectangle(0, 0, Width - 1, panelMinSize - 1);
g.DrawRectangle(pPanelBorderColor, recTitleBarBorder);
//draw the main panel area border
Rectangle recMainAreaBorder = new Rectangle(0, 0, Width - 1, Height - 1);
g.DrawRectangle(pPanelBorderColor, recMainAreaBorder);
}
/// <summary>
/// returns true if the mouse is over the title area
/// </summary>
/// <param name="xPos">The current mouse XPos</param>
/// <param name="yPos">The current mouse YPos</param>
/// <returns>true if the mouse is over the title area</returns>
private bool IsOverTitle(int xPos, int yPos)
{
// Get the dimensions of the title label
Rectangle rectTest = new Rectangle(0, 0, Width, panelMinSize);
// Check if the supplied coordinates are over the title label
if (rectTest.Contains(xPos, yPos))
{
return true;
}
return false;
}
/// <summary>
/// Updates the state of the CollapsePanel
/// </summary>
private void UpdateDisplayedState()
{
switch (this.state)
{
case CollapsePanelCurrentState.Collapsed:
// Entering collapsed state, so store the current height.
this.oPanelHeight = this.Height;
// Collapse the oPanel
this.Height = panelMinSize;
// Update the image.
this.imageIndex = 1;
break;
case CollapsePanelCurrentState.Expanded:
// Entering expanded state, so expand the oPanel.
this.Height = this.oPanelHeight;
// Update the image.
this.imageIndex = 0;
break;
default:
// Ignore
break;
}
this.Invalidate();
OnCollapsePanelCurrentStateChanged(new PanelEventArgs(this));
}
#endregion
#region Protected Methods
/// <summary>
/// Raises the OnCollapsePanelCurrentStateChanged event for the <see cref="UserControls.CollapsePanel.CollapsePanelCurrentStateChanged">CollapsePanelCurrentStateChanged</see>.
/// Any users of the <see cref="UserControls.CollapsePanel.CollapsePanelCurrentStateChanged">CollapsePanelCurrentStateChanged</see> may now subscribe to this event
/// using a CollapsePanelCurrentStateChangedEventHandler delegate.
/// </summary>
/// <param name="e">The <see cref="UserControls.PanelEventArgs">PanelEventArgs</see>that contains the event data</param>
protected virtual void OnCollapsePanelCurrentStateChanged(PanelEventArgs e)
{
if (CollapsePanelCurrentStateChanged != null)
{
// Invokes the delegates.
CollapsePanelCurrentStateChanged(this, e);
}
}
#endregion
#region Public Methods / Events / Properties
/// <summary>
/// Gets/sets the font used for the title bar text.
/// </summary>
[Category("Title"),
Description("The font used to display the title text.")]
public Font TitleFont
{
get
{
return this.titleBarFont;
}
set
{
this.titleBarFont = value;
this.Invalidate();
}
}
/// <summary>
/// Gets/sets the image list used for the expand/collapse image.
/// </summary>
[Category("Title"),
Description("The image list to get the images displayed for expanding/collapsing the CollapsePanel.")]
public ImageList ImageList
{
get
{
return this.imageList;
}
set
{
this.imageList = value;
//is the imageList valid
if (this.imageList != null)
{
//are there images within it
if (this.imageList.Images.Count > 0)
{
this.imageIndex = 0;
}
}
else
{
this.imageIndex = -1;
}
this.Invalidate();
}
}
/// <summary>
/// Gets/sets the font used for the title bar text.
/// </summary>
[Category("Title"),
Description("The color used to display the title text.")]
public Color TitleBarTextColor
{
get { return this.titleBarTextColor; }
set
{
this.titleBarTextColor = value;
this.Invalidate();
}
}
/// <summary>
/// Gets/sets the font used for the title bar text.
/// </summary>
[Category("Title"),
Description("The title text.")]
public String TitleText
{
get { return this.titleText; }
set
{
this.titleText = value;
this.Invalidate();
}
}
/// <summary>
/// Gets/sets the font used for the title bar text.
/// </summary>
[Category("Title"),
Description("The border color used to display the title area border.")]
public Color PanelBorderColor
{
get { return this.panelBorderColor; }
set
{
this.panelBorderColor = value;
this.Invalidate();
}
}
/// <summary>
/// Gets/sets the start color used for the title bar area
/// </summary>
[Category("Title"),
Description("The start color used to display the title area background.")]
public Color TitleBarStartColor
{
get { return titleBarStartColor; }
set
{
this.Invalidate();
this.titleBarStartColor = value;
}
}
/// <summary>
/// Gets/sets the <see cref="UserControls.CollapsePanelCurrentState">CollapsePanelCurrentState</see>, which
/// can either be Expanded/Collapsed
/// </summary>
[Browsable(false)]
public CollapsePanelCurrentState CollapsePanelCurrentState
{
get
{
return this.state;
}
set
{
CollapsePanelCurrentState oldState = this.state;
this.state = value;
if (oldState != this.state)
{
// State has changed to update the display
UpdateDisplayedState();
}
}
}
/// <summary>
/// Gets/sets the end color used for the title bar area
/// </summary>
[Category("Title"),
Description("The end color used to display the title area background.")]
public Color TitleBarEndColor
{
get { return titleBarEndColor; }
set
{
this.Invalidate();
this.titleBarEndColor = value;
}
}
#endregion
}
#endregion
#region Public Enumeration
/// <summary>
/// Defines the state of a <see cref="UserControls.CollapsePanel">CollapsePanel</see>.
/// </summary>
public enum CollapsePanelCurrentState
{
/// <summary>
/// The <see cref="UserControls.CollapsePanel">CollapsePanel</see> is expanded.
/// </summary>
Expanded,
/// <summary>
/// The <see cref="UserControls.CollapsePanel">CollapsePanel</see> is collapsed.
/// </summary>
Collapsed
}
#endregion
#region Delegates
/// <summary>
/// A delegate type for hooking up a <see cref="UserControls.CollapsePanel">CollapsePanel</see> state
/// change notifications.
/// </summary>
public delegate void CollapsePanelCurrentStateChangedEventHandler(object sender, PanelEventArgs e);
#endregion
#region PanelEventArgs CLASS
/// <summary>
/// Provides PanelEventArgs for the <see cref="UserControls.CollapsePanel.CollapsePanelCurrentStateChanged">CollapsePanelCurrentStateChanged</see> event.
/// This event is then used by the <see cref="UserControls.CollapsePanelBar">CollapsePanelBar</see> to determine the new layout
/// positions for all of the <see cref="UserControls.CollapsePanel">CollapsePanel</see> contained.
/// </summary>
public class PanelEventArgs : System.EventArgs
{
#region Instance Fields
//Instance Fields
private CollapsePanel oPanel;
#endregion
#region Public Constructor
/// <summary>
/// Simply creates a new PanelEventArgs object using the paremeter provided
/// </summary>
/// <param name="sender">The originating <see cref="UserControls.CollapsePanel">CollapsePanel</see>.</param>
public PanelEventArgs(CollapsePanel sender)
{
this.oPanel = sender;
}
#endregion
#region Public Properties
/// <summary>
/// Gets the <see cref="UserControls.CollapsePanel">CollapsePanel</see> that triggered the event.
/// </summary>
public CollapsePanel CollapsePanel
{
get
{
return this.oPanel;
}
}
/// <summary>
/// Gets the CollapsePanelCurrentState of the <see cref="UserControls.CollapsePanel">CollapsePanel</see> that triggered the event.
/// </summary>
public CollapsePanelCurrentState CollapsePanelCurrentState
{
get
{
return this.oPanel.CollapsePanelCurrentState;
}
}
#endregion
}
#endregion
}