using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Imaging;
namespace Sand.Services.CodeXchange.Client.Controls
{
/// <summary>
/// Panel control with a themeable header that can expand and collapse
/// </summary>
public class ExplorerGroup : Panel
{
/// <summary>
/// Event raised when the control expands or collapses
/// </summary>
public event EventHandler ExpandedChanged;
private const int CHEVRON_X_PADDING = 22;
private const int CHEVRON_Y_PADDING = 4;
private bool m_Expanded = true;
private bool m_MosueIsOverTitle = false;
private int m_PanelHeight;
private string m_Title = string.Empty;
private Bitmap m_Icon = null;
private System.ComponentModel.IContainer components;
protected System.Windows.Forms.Label TitleLabel;
public ExplorerGroup()
{
components = new System.ComponentModel.Container();
InitializeComponent();
}
[Category("Appearance"), Description("The text contained in the control")]
[Browsable(true)]
public override string Text
{
get
{
return m_Title;
}
set
{
m_Title = value;
Refresh();
}
}
[Category("Appearance"), Description("Determines whether the panel's contents are shown or not")]
[DefaultValue (true)]
[Browsable(true)]
public bool Expanded
{
get
{
return m_Expanded;
}
set
{
m_Expanded = value;
OnExpandedChanged();
}
}
[Category("Appearance"), Description("")]
[Browsable(true)]
public Bitmap Icon
{
get
{
return m_Icon;
}
set
{
m_Icon = value;
Refresh();
}
}
/// <summary>
/// Updates the display to reflect the current expansion state
/// </summary>
private void ChangeExpansionDisplay()
{
if ( m_Expanded )
Height = m_PanelHeight;
else
{
m_PanelHeight = Height;
Height = TitleLabel.Height;
}
}
private Rectangle HeaderBounds
{
get
{
return new Rectangle( 0, 0, TitleLabel.Bounds.Width, TitleLabel.Bounds.Height );
}
}
/// <summary>
/// Called in order to raise the ExpandedChanged event
/// </summary>
protected void OnExpandedChanged()
{
ChangeExpansionDisplay();
if ( ExpandedChanged != null )
ExpandedChanged( this, EventArgs.Empty );
Refresh();
}
private void DrawChevrons(Graphics g, int x, int y, int offset)
{
// Determine the orientation of the pseudo-button
if (!Expanded)
{
DrawChevron(g, x + offset + 1, y + 1*offset, -offset);
DrawChevron(g, x + offset + 1, y + 2*offset, -offset);
}
else
{
DrawChevron(g, x + offset + 1, y + 2*offset, offset);
DrawChevron(g, x + offset + 1, y + 3*offset, offset);
}
}
private void DrawChevron(Graphics g, int x, int y, int offset)
{
Pen p = new Pen(Color.White);
Point[] points = { new Point(x, y),
new Point(x+Math.Abs(offset), y-offset),
new Point(x+2*Math.Abs(offset), y)
};
g.DrawLines(p, points);
p.Dispose();
}
/// <summary>
/// Draws the header portion of the control
/// </summary>
/// <param name="graphics">Graphics object used for painting</param>
protected void DrawHeader( Graphics graphics )
{
int x = TitleLabel.Bounds.Right - CHEVRON_X_PADDING;
int y = TitleLabel.Bounds.Top + CHEVRON_Y_PADDING;
Rectangle rect = new Rectangle( x, y, 12, 12 );
Rectangle rect1 = new Rectangle( x + ( rect.Width / 3 ) - 2, y + 3, 12, 12 );
DrawChevrons ( graphics ,
rect1.X ,
rect1.Y ,
rect1.Width / 4);
DrawChevronEdge( graphics );
DrawHeaderIcon ( graphics );
DrawHeaderTitle ( graphics );
if (m_MosueIsOverTitle)
{
TitleLabel.BackColor = System.Drawing.SystemColors.ActiveCaption;
}
else
{
TitleLabel.BackColor = System.Drawing.SystemColors.AppWorkspace;
}
}
protected void DrawHeaderTitle( Graphics graphics )
{
using (Brush brush = new SolidBrush (System.Drawing.SystemColors.ActiveCaptionText))
{
Font font = new Font (Font.FontFamily , Font.Size , FontStyle.Bold);
if (m_Icon != null)
{
graphics.DrawString (
m_Title ,
font ,
brush ,
20 ,
4 ,
StringFormat.GenericDefault);
}
else
{
graphics.DrawString (
m_Title ,
font ,
brush ,
4 ,
4 ,
StringFormat.GenericDefault);
}
}
}
protected void DrawHeaderIcon( Graphics graphics )
{
if (m_Icon != null)
graphics.DrawImage (m_Icon , 4 , 4);
}
/// <summary>
/// Draw a faint rectangle around the chevron if the mouse if currently over the title bar
/// </summary>
/// <param name="graphics">Graphics object used for painting</param>
private void DrawChevronEdge( Graphics graphics )
{
if( m_MosueIsOverTitle )
{
Rectangle bounds = TitleLabel.Bounds;
int x = bounds.Right - CHEVRON_X_PADDING;
int y = bounds.Top + CHEVRON_Y_PADDING;
Pen lightPen = new Pen( SystemColors.ControlLightLight );
Pen darkPen = new Pen( Color.DarkGray );
Rectangle rect = new Rectangle( x, y, 18 , 16);
graphics.DrawLine( lightPen, x, y, x, y + rect.Height );
graphics.DrawLine( lightPen, x, y, x + rect.Width, y );
graphics.DrawLine( darkPen, x + rect.Width, y, x + rect.Width, y + rect.Height );
graphics.DrawLine( darkPen, x + rect.Width, y + rect.Height, x, y + rect.Height );
}
}
#region Constituent Control Events
private void TitleLabel_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if( e.Button == MouseButtons.Left && TitleLabel.Bounds.Contains( e.X, e.Y ) )
Expanded = !Expanded;
}
private void CollapsiblePanel_MouseLeave(object sender, System.EventArgs e)
{
TitleLabel.Cursor = Cursors.Default;
m_MosueIsOverTitle = false;
TitleLabel.Refresh();
}
private void TitleLabel_MouseLeave(object sender, System.EventArgs e)
{
TitleLabel.Cursor = Cursors.Default;
m_MosueIsOverTitle = false;
TitleLabel.Refresh();
}
private void TitleLabel_MouseEnter(object sender, System.EventArgs e)
{
TitleLabel.Cursor = Cursors.Hand;
m_MosueIsOverTitle = true;
TitleLabel.Refresh();
}
private void TitleLabel_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
//when the title is painted do the cutom rendering
DrawHeader( e.Graphics );
}
#endregion
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.TitleLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// TitleLabel
//
this.TitleLabel.BackColor = System.Drawing.SystemColors.AppWorkspace;
this.TitleLabel.Cursor = System.Windows.Forms.Cursors.Default;
this.TitleLabel.Dock = System.Windows.Forms.DockStyle.Top;
this.TitleLabel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.TitleLabel.ForeColor = System.Drawing.SystemColors.HighlightText;
this.TitleLabel.Location = new System.Drawing.Point(17, 17);
this.TitleLabel.Name = "TitleLabel";
this.TitleLabel.Size = new System.Drawing.Size(200, 24);
this.TitleLabel.TabIndex = 0;
this.TitleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.TitleLabel.Paint += new System.Windows.Forms.PaintEventHandler(this.TitleLabel_Paint);
this.TitleLabel.MouseEnter += new System.EventHandler(this.TitleLabel_MouseEnter);
this.TitleLabel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.TitleLabel_MouseUp);
this.TitleLabel.MouseLeave += new System.EventHandler(this.TitleLabel_MouseLeave);
//
// ExplorerGroup
//
this.Controls.Add(this.TitleLabel);
this.MouseLeave += new System.EventHandler(this.CollapsiblePanel_MouseLeave);
this.ResumeLayout(false);
}
#endregion
#region Disposer
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
}
}