using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Resources;
using System.Windows.Forms;
namespace IssueVision
{
// This is the IssueVision specific control that derives from the generic
// Outlook-like ExandableList control. Responsible for rendering the
// content of each row.
public class IssueList : ExpandableList
{
// maps to the icons in the imagelist
private enum RowStateIcon
{
Conflict = 0,
Modified = 1
}
// cell space in each row
private const int Buffer = 4;
// where to draw the second column of information (from right side)
private const int RightBuffer = 90;
// don't draw the second column if the control is only this wide
private const int DrawRightSideWidth = 200;
// room for icon on the left side
private const int LeftPos = 22;
// gdi objects
private StringFormat m_formatRight;
private StringFormat m_formatEllipsis;
private IssueSubject m_subject;
private ImageList imageList;
private IContainer components;
public IssueSubject Subject
{
set
{
m_subject = value;
}
}
public IssueList()
{
// right aligned text, setting the DirectionRightToLeft
// works better then setting Alignment to StringAlignment.Far,
// the latter approach does not always align the strings correctly
m_formatRight = new StringFormat(StringFormatFlags.DirectionRightToLeft);
// strings with ellipsis
m_formatEllipsis = new StringFormat();
m_formatEllipsis.FormatFlags = StringFormatFlags.NoWrap;
m_formatEllipsis.Trimming = StringTrimming.EllipsisCharacter;
InitializeComponent();
}
// a row needs to be painted
protected override void OnDrawItem(DrawItemEventArgs e, DataRowView dr)
{
// colors that depend if the row is currently selected or not,
// assign to a system brush so should not be disposed
// not selected colors
Brush brushBack = SystemBrushes.Window;
Brush brushText = SystemBrushes.WindowText;
Brush brushDim = Brushes.Gray;
if ((e.State & DrawItemState.Selected) != 0)
{
if ((e.State & DrawItemState.Focus) != 0)
{
//selected and has focus
brushBack = SystemBrushes.Highlight;
brushText = SystemBrushes.HighlightText;
brushDim = SystemBrushes.HighlightText;
}
else
{
//selected and does not have focus
brushBack = SystemBrushes.Control;
brushDim = SystemBrushes.WindowText;
}
}
//background
e.Graphics.FillRectangle(brushBack, e.Bounds);
//decrease the bounds to get a visual buffer around each row
RectangleF rc = new RectangleF(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
rc.Inflate(-Buffer, -Buffer);
//values
DrawValues(e.Graphics, rc, brushText, brushDim, dr);
//icon
DrawIcon(e.Graphics, (int)rc.Left, (int)rc.Top, dr);
}
// draw content of a row
private void DrawValues(Graphics g, RectangleF rc, Brush brushText, Brush brushDim, DataRowView dr)
{
// calculate the bounds of the title, necessary to
// draw ellipsis if string is too long
RectangleF bounds = new RectangleF(rc.Left + LeftPos, rc.Top, rc.Width - LeftPos, Font.Height);
//see if should leave room for the second column (date and username)
if (rc.Width > DrawRightSideWidth)
{
bounds.Width -= RightBuffer;
}
//title
g.DrawString((string)dr["Title"], Font, brushText, bounds, m_formatEllipsis);
//comments
bounds.Y += this.Font.Height + 2;
g.DrawString((string)dr["Description"], Font, brushDim, bounds, m_formatEllipsis);
//second column, date and open status
if (rc.Width > DrawRightSideWidth)
{
//date
g.DrawString(((DateTime)dr["DateOpened"]).ToShortDateString(), Font, brushDim, rc.Right, rc.Top, m_formatRight);
//open / closed
if ((bool)dr["IsOpen"])
{
g.DrawString("Open", Font, brushText, rc.Right, rc.Top + Font.Height + 2.0F, m_formatRight);
}
else
{
g.DrawString("Closed", Font, brushDim, rc.Right, rc.Top + Font.Height + 2.0F, m_formatRight);
}
}
}
// rows can have conflict, modified or no icon
private void DrawIcon(Graphics g, int x, int y, DataRowView dr)
{
// conflict
if (m_subject.ConflictItems != null && m_subject.ConflictItems.ContainsKey(dr["IssueID"]))
{
imageList.Draw(g, x, y, (int)RowStateIcon.Conflict);
return;
}
// modified
if (dr.Row.RowState == DataRowState.Modified || dr.Row.RowState == DataRowState.Added)
{
imageList.Draw(g, x, y, (int)RowStateIcon.Modified);
}
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(IssueList));
this.imageList = new System.Windows.Forms.ImageList(this.components);
//
// imageList
//
this.imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit;
this.imageList.ImageSize = new System.Drawing.Size(16, 16);
this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream")));
this.imageList.TransparentColor = System.Drawing.Color.Lime;
//
// IssueList
//
this.Name = "IssueList";
}
protected override void Dispose(bool disposing)
{
if (disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}
}
}