|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace AutoDiagramer
{
#region ucExpander CLASS
/// <summary>
/// This control is a control that is used to represent
/// one section of the overall class drwing. It has a title
/// bar and n-many rows (RowContent). Each row is rendering
/// with an image and a string. The control may be collapsed
/// or expanded. This single control may be used to draw the
/// following sections on overall class
/// Properties,Events,Fields,Constructors,Methods
/// </summary>
public partial class ucExpander : UserControl
{
#region Instance Fields
//private fields
private Font _rowFont;
private List<string> _rowContent;
private PossibleTypes _examiningType = PossibleTypes.Methods;
private int _oldhieght = 0;
private States _currentState = States.Expanded;
public enum States { Collapsed, Expanded };
private int _pictureSize = 16;
private int _RowSpacerSize = 2;
private int _EndSpacerSize = 40;
//public fields
public enum PossibleTypes { Properties,Events,Fields,Constructors,Methods };
public delegate void PanelStateChangedEventHandler(object sender, ExpanderSizeEventArgs args );
public event PanelStateChangedEventHandler PanelStateChanged;
#endregion
#region Ctor
/// <summary>
/// Constructs a new ucExpander using the parameters provided
/// </summary>
/// <param name="title">The title for this control</param>
/// <param name="examiningType">The type this control is gooing to represent.
/// Could be one of the following Properties,Events,Fields,Constructors,Methods.
/// This allows the control to grab the correct image to diaply for each row
/// in the RowContent</param>
public ucExpander(string title,PossibleTypes examiningType)
{
InitializeComponent();
//set to flickerless style
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw |
ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true);
lblTitle.Text = title;
this._examiningType = examiningType;
_rowFont = new Font("Microsoft Sans Serif", 8.25F);
this.Refresh();
Application.DoEvents();
}
#endregion
#region Private Methods
/// <summary>
/// Calls the getMaxWidth() and getMaxHeight() methods
/// and causes the control to redraw
/// </summary>
private void RegenerateControl()
{
this.Width = getMaxWidth();
this.Height = getMaxHeight();
this.Invalidate();
Application.DoEvents();
}
/// <summary>
/// Paint each row (thats an image and the text)
/// for each row in the RowContent list
/// </summary>
/// <param name="e">the event args</param>
protected override void OnPaint(PaintEventArgs e)
{
int X_Pos = 0;
int Y_Pos = pnlTop.Height;
base.OnPaint(e);
Graphics g = e.Graphics;
SolidBrush b_Black = new SolidBrush(Color.Black);
Image img = getImage();
//paint each row
foreach (string s in _rowContent)
{
g.DrawImage(img, new Point(X_Pos, Y_Pos));
g.DrawString(s, _rowFont, b_Black,
new Point(X_Pos + (_pictureSize+(_RowSpacerSize*2)), Y_Pos+(_RowSpacerSize*3)));
Y_Pos += img.Height + _RowSpacerSize;
}
}
/// <summary>
/// returns the correct image for the type is being examining
/// So if this controls is displaying methods, return a methods
/// Image
/// </summary>
/// <returns>An image for the type is being examining
/// So if this controls is displaying methods, return a methods
/// Image</returns>
private Image getImage()
{
Image img = null;
//look at what type is being examining and return correct image
switch (this._examiningType)
{
case PossibleTypes.Constructors:
img = global::AutoDiagramer.Resource1.Constructors16;
break;
case PossibleTypes.Events:
img = global::AutoDiagramer.Resource1.Events16;
break;
case PossibleTypes.Properties:
img = global::AutoDiagramer.Resource1.Prop16;
break;
case PossibleTypes.Methods:
img = global::AutoDiagramer.Resource1.Method16;
break;
case PossibleTypes.Fields:
img = global::AutoDiagramer.Resource1.Fields16;
break;
}
return img;
}
/// <summary>
/// Measures all contenst to see how height this control needs to be
/// to fit its contents
/// </summary>
/// <returns>An int which is the highest height this control needs to be
/// to fit its contents</returns>
private int getMaxHeight()
{
int MaxHeight = pnlTop.Height + 1;
Graphics g = this.CreateGraphics();
//look at each row
if (_rowContent != null)
{
//work out what the highest content is
foreach (string s in _rowContent)
{
//picture is larger than text so use that for height,
//also add on _RowSpacerSize height
MaxHeight += _pictureSize + _RowSpacerSize;
}
}
//store old height (for re-expansion)
_oldhieght = MaxHeight + _RowSpacerSize;
//return the MaxHeight
return MaxHeight + _RowSpacerSize;
}
/// <summary>
/// Measures all contenst to see how wide this control needs to be
/// to fit its contents
/// </summary>
/// <returns>An int which is the widest width this control needs to be
/// to fit its contents</returns>
private int getMaxWidth()
{
int MaxWidth = 0;
Graphics g = this.CreateGraphics();
//get the width of the title banner
MaxWidth = lblTitle.Location.X +
(int)((SizeF)g.MeasureString(lblTitle.Text, lblTitle.Font)).Width + _EndSpacerSize;
//test each rows width
if (_rowContent!=null)
{
//look at each row
foreach(string s in _rowContent)
{
//work out what the widest content is
int rowWidth = (int)((SizeF)g.MeasureString(s, _rowFont)).Width +
(_pictureSize+(_RowSpacerSize*3));
if (rowWidth > MaxWidth)
{
MaxWidth = rowWidth;
}
}
}
//return the MaxWidth
return MaxWidth;
}
/// <summary>
/// Raised when the panel state changes state (collaped/expanded)
/// </summary>
/// <param name="sender"><see cref="ucExpander">this</see></param>
/// <param name="e">the event args</param>
private void OnPanelStateChanged(object sender, ExpanderSizeEventArgs args)
{
// Check if there are any Subscribers
if (PanelStateChanged != null)
{
// Call the Event
PanelStateChanged(sender, args);
}
}
/// <summary>
/// Will either expand or collapse the control, and will
/// store the current state. And will fire the
/// OnPanelStateChanged() event
/// </summary>
/// <param name="sender">picState</param>
/// <param name="e">the event args</param>
private void picState_Click(object sender, EventArgs e)
{
if (_currentState == States.Expanded)
{
_currentState = States.Collapsed;
}
else if (_currentState == States.Collapsed)
{
_currentState = States.Expanded;
}
switch (_currentState)
{
case States.Expanded:
this.picState.Image = global::AutoDiagramer.Resource1.Collapse9;
this.Height = _oldhieght;
break;
case States.Collapsed:
this.picState.Image = global::AutoDiagramer.Resource1.Expand9;
this.Height = pnlTop.Height;
break;
}
// If anyone has subscribed, notify them
OnPanelStateChanged(this, new ExpanderSizeEventArgs(this));
}
#endregion
#region Public Properties
/// <summary>
/// gets / sets a List of strings that provide the
/// row content for this control. The set will call
/// the RegenerateControl() method
/// </summary>
[Browsable(false)]
public List<string> RowContent
{
get { return _rowContent; }
set
{
if (value != null)
{
_rowContent = value;
RegenerateControl();
}
}
}
/// <summary>
/// gets the current state expanded / collapsed
/// </summary>
[Browsable(false)]
public States CurrentState
{
get { return this._currentState; }
}
/// <summary>
/// gets / sets the Font to use for the rows
/// </summary>
[Category("Appearance")]
[Browsable(true)]
public Font RowFont
{
get { return _rowFont; }
set { _rowFont = value; }
}
/// <summary>
/// gets / sets the Font to use for the title
/// </summary>
[Category("Appearance")]
[Browsable(true)]
public string TitleBarText
{
get { return lblTitle.Text; }
set { lblTitle.Text = value; }
}
/// <summary>
/// gets / sets the Color to use for the title bar
/// </summary>
[Category("Appearance")]
[DefaultValue(typeof(Color))]
[Browsable(true)]
public Color TitleBarColor
{
get { return pnlTop.BackColor; }
set { pnlTop.BackColor = value; }
}
/// <summary>
/// gets / sets the Color to use for the title text
/// </summary>
[Category("Appearance")]
[DefaultValue(typeof(Color))]
[Browsable(true)]
public Color TitleBarTextColor
{
get { return lblTitle.ForeColor; }
set { lblTitle.ForeColor = value; }
}
#endregion
}
#endregion
#region ExpanderSizeEventArgs CLASS
/// <summary>
/// provides the events args for the <see cref="ucExpander">
/// ucExpander </see>SizeChanged event
/// </summary>
public class ExpanderSizeEventArgs : System.EventArgs
{
#region Instance Fields
//instance fields
private ucExpander ucExp;
#endregion
#region Ctor
/// <summary>
/// Constructs a new ExpanderSizeEventArgs using the params provided
/// </summary>
/// <param name="ucd">A <see cref="ucExpander">ucExpander </see>
/// ucExpander</param>object which raised the event
public ExpanderSizeEventArgs(ucExpander ucExp)
{
this.ucExp = ucExp;
}
#endregion
#region Public Properties
/// <summary>
/// gets the CurrentState collapsed / expanded
/// </summary>
public ucExpander.States CurrentState
{
get { return this.ucExp.CurrentState; }
}
#endregion
}
#endregion
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
Both of these at Sussex University UK.
Award(s)
I am lucky enough to have won a few awards for Zany Crazy code articles over the years
- Microsoft C# MVP 2016
- Codeproject MVP 2016
- Microsoft C# MVP 2015
- Codeproject MVP 2015
- Microsoft C# MVP 2014
- Codeproject MVP 2014
- Microsoft C# MVP 2013
- Codeproject MVP 2013
- Microsoft C# MVP 2012
- Codeproject MVP 2012
- Microsoft C# MVP 2011
- Codeproject MVP 2011
- Microsoft C# MVP 2010
- Codeproject MVP 2010
- Microsoft C# MVP 2009
- Codeproject MVP 2009
- Microsoft C# MVP 2008
- Codeproject MVP 2008
- And numerous codeproject awards which you can see over at my blog