using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Resources;
using System.Windows.Forms;
namespace IssueVision
{
public class SectionControl : UserControl
{
// events
public delegate void DrawItemEventHandler(object sender, DrawItemEventArgs e, DataRowView dr);
public delegate void SelectionChangedEventHandler(SectionControl sender, DataRowView dr);
public delegate void SelectionDoubleClickedEventHandler(SectionControl sender, DataRowView dr);
public virtual event DrawItemEventHandler DrawItem;
public virtual event SelectionChangedEventHandler SelectionChanged;
public virtual event SelectionDoubleClickedEventHandler SelectionDoubleClicked;
private ImageList imageList;
private PictureBox pictExpand;
// const values
public const int DefaultItemHeight = 36;
private const int HeaderHeight = 40;
private int m_expansionState = 1;
private int m_itemHeight = SectionControl.DefaultItemHeight;
private DataRowView[] m_rows;
private string m_groupTitle = string.Empty;
private int m_currrentSelectionIndex = -1;
private Pen m_penSeparate;
private Font m_fontGroupTitle;
private StringFormat m_format;
private IContainer components;
[DescriptionAttribute("Gets and sets a data source for this group.")]
[CategoryAttribute("Data")]
[DefaultValueAttribute(null)]
public DataRowView[] DataSource
{
get
{
return m_rows;
}
set
{
m_rows = value;
UpdateLayout();
}
}
[DefaultValueAttribute(SectionControl.DefaultItemHeight)]
[CategoryAttribute("Layout")]
[DescriptionAttribute("Height of each row in the group.")]
public int ItemHeight
{
get
{
return m_itemHeight;
}
set
{
m_itemHeight = value;
}
}
[BrowsableAttribute(false)]
public int SelectedIndex
{
get
{
return m_currrentSelectionIndex;
}
set
{
if (m_currrentSelectionIndex != value)
{
m_currrentSelectionIndex = value;
Invalidate();
}
}
}
[BrowsableAttribute(false)]
public int Count
{
get
{
if (m_rows == null)
{
return 0;
}
else
{
return m_rows.Length;
}
}
}
public override string Text
{
get
{
return m_groupTitle;
}
set
{
m_groupTitle = value;
}
}
public SectionControl()
{
InitializeComponent();
// init gdi objects
m_penSeparate = new Pen(SystemColors.InactiveCaption, 2.0F);
// font for the group section header
m_fontGroupTitle = new Font("tahoma", Font.Size, FontStyle.Bold);
// draw strings w/ ellipsis
m_format = new StringFormat();
m_format.FormatFlags = StringFormatFlags.NoWrap;
m_format.LineAlignment = StringAlignment.Center;
m_format.Trimming = StringTrimming.EllipsisCharacter;
// turn on double buffering
SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true);
}
// Return the row index that contains the specified data row.
public int GetRow(DataRowView dr)
{
// return right away if don't have any rows
if (dr == null || m_rows == null || m_rows.Length == 0)
{
return -1;
}
// look for the matching row
for (int i = 0; i < m_rows.Length; i++)
{
if (m_rows[i].Row.Equals(dr.Row))
{
return i;
}
}
// did not find a match
return -1;
}
// Set the expand / collapse image.
private void SetImage(int index)
{
pictExpand.Image = imageList.Images[index];
}
// Calculate the total height of the control.
private void UpdateLayout()
{
if (m_expansionState == 1)
{
Height = HeaderHeight + m_rows.Length * (m_itemHeight + 1);
}
else
{
Height = HeaderHeight;
}
}
protected override void OnPaint(PaintEventArgs e)
{
//Draw the group title
RectangleF groupTitleBounds = new RectangleF( pictExpand.Right + 5,
pictExpand.Top,
this.Width - pictExpand.Right - 10,
m_fontGroupTitle.Height);
e.Graphics.DrawString(this.Text, m_fontGroupTitle, SystemBrushes.Highlight, groupTitleBounds, m_format);
//Draw a line to separate the header from its associated items.
e.Graphics.DrawLine(m_penSeparate, 0, HeaderHeight - 1, this.Width, HeaderHeight - 1);
//Loop through and draw each row.
int topItem = HeaderHeight;
int index = 0;
foreach (DataRowView dr in m_rows)
{
// Determine what state the row is in.
DrawItemState state = DrawItemState.None;
if (m_currrentSelectionIndex == index)
state = state | DrawItemState.Selected;
if (this.Focused)
state = state | DrawItemState.Focus;
// Create object that holds the drawing data.
DrawItemEventArgs drawArg = new DrawItemEventArgs( e.Graphics,
this.Font,
new Rectangle(0, topItem, this.Width, m_itemHeight),
index,
state);
// Have some other code render the item.
OnDrawItem(drawArg, dr);
// Draw a line to separate each item.
e.Graphics.DrawLine(SystemPens.Control, 0, topItem + m_itemHeight, this.Width, topItem + m_itemHeight);
// Update the top of the next item.
topItem += m_itemHeight + 1;
index += 1;
}
}
protected virtual void OnDrawItem(DrawItemEventArgs e, DataRowView dr)
{
if (DrawItem != null)
{
DrawItem(this, e, dr);
}
}
private void SectionControl_Load(object sender, EventArgs e)
{
SetImage(m_expansionState);
UpdateLayout();
}
private void PictExpand_Click(object sender, EventArgs e)
{
m_expansionState = 1 - m_expansionState;
SetImage(m_expansionState);
UpdateLayout();
}
protected override void Dispose(bool disposing)
{
if (disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}
[DebuggerStepThroughAttribute()]
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(SectionControl));
this.pictExpand = new System.Windows.Forms.PictureBox();
this.imageList = new System.Windows.Forms.ImageList(this.components);
this.SuspendLayout();
//
// pictExpand
//
this.pictExpand.Location = new System.Drawing.Point(8, 16);
this.pictExpand.Name = "pictExpand";
this.pictExpand.Size = new System.Drawing.Size(11, 11);
this.pictExpand.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictExpand.TabIndex = 0;
this.pictExpand.TabStop = false;
this.pictExpand.Click += new EventHandler(this.PictExpand_Click);
//
// imageList
//
this.imageList.ImageSize = new System.Drawing.Size(11, 11);
this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream")));
this.imageList.TransparentColor = System.Drawing.Color.Lime;
//
// SectionControl
//
this.BackColor = System.Drawing.SystemColors.Window;
this.Controls.Add(this.pictExpand);
this.Name = "SectionControl";
this.Size = new System.Drawing.Size(208, 48);
base.DoubleClick += new EventHandler(this.SectionControl_DoubleClick);
base.MouseDown += new MouseEventHandler(this.SectionControl_MouseDown);
base.GotFocus += new EventHandler(this.SectionControl_GotFocus);
base.LostFocus += new EventHandler(this.SectionControl_LostFocus);
base.Load += new EventHandler(this.SectionControl_Load);
this.ResumeLayout(false);
}
private void SectionControl_DoubleClick(object sender, EventArgs e)
{
if (SelectionDoubleClicked != null)
{
SelectionDoubleClicked(this, null);
}
}
private void SectionControl_MouseDown(object sender, MouseEventArgs e)
{
// holds the new selection
int sel;
if (e.Y < HeaderHeight)
{
// the header was selected, usually would set this to -1
// but set to the first item in the list (selecting the
// header selects the first row)
if (m_rows == null || m_rows.Length == 0)
{
// the group does not contain any rows
sel = -1;
}
else
{
// the first row in the group
sel = 0;
}
}
else
{
// the selected row
sel = (e.Y - HeaderHeight) / (m_itemHeight + 1);
}
// update if a new row was selected
if (sel != m_currrentSelectionIndex)
{
m_currrentSelectionIndex = sel;
Invalidate();
OnSelectionChanged(m_currrentSelectionIndex);
}
}
protected virtual void OnSelectionChanged(int index)
{
// pass the selected row data if available
if (index == -1)
{
if (SelectionChanged != null)
{
SelectionChanged(this, null);
}
}
else if (SelectionChanged != null)
{
SelectionChanged(this, m_rows[index]);
}
}
private void SectionControl_GotFocus(object sender, EventArgs e)
{
// Invalidate so the selected row can be repainted
if (m_currrentSelectionIndex != -1)
{
Invalidate();
}
}
private void SectionControl_LostFocus(object sender, EventArgs e)
{
// Invalidate so the selected row can be repainted
if (m_currrentSelectionIndex != -1)
{
Invalidate();
}
}
}
}