Pastebin launched a little side project called HostCabi.net, check it out ;-)Pastebin is 300% more awesome when you are logged in. Sign Up, it's FREE!
Guest

C# Version Gantt Chart Control from CodeProject

By: orilon on Sep 3rd, 2012  |  syntax: C#  |  size: 51.51 KB  |  hits: 254  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // -----------------------------------------------------------------------
  2. // <copyright file="GanttChart.cs">
  3. // http://www.codeproject.com/Articles/20731/Gantt-Chart
  4. // <summary>
  5. // Adds an easy to use Gantt Chart to your application
  6. // Created by Adrian "Adagio" Grau
  7. // Version 0.55
  8. // </summary>
  9. // <remarks></remarks>
  10. // </copyright>
  11. // -----------------------------------------------------------------------
  12.  
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Linq;
  16. using System.Text;
  17. using System.Drawing.Drawing2D;
  18. using System.Drawing;
  19. using System.Windows.Forms;
  20.  
  21. /// <summary>
  22. /// TODO: Update summary.
  23. /// </summary>
  24. public class GanttChart : Control
  25. {
  26.  
  27.     private MouseOverPart mouseHoverPart = MouseOverPart.Empty;
  28.  
  29.     private int mouseHoverBarIndex = -1;
  30.     private List<ChartBarDate> bars = new List<ChartBarDate>();
  31.     private System.DateTime headerFromDate;
  32.  
  33.     private System.DateTime headerToDate;
  34.  
  35.     private int barIsChanging = -1;
  36.     private int barStartRight = 20;
  37.     private int barStartLeft = 100;
  38.     private int headerTimeStartTop = 30;
  39.  
  40.     private List<Header> shownHeaderList;
  41.     private int barStartTop = 50;
  42.     private int barHeight = 9;
  43.  
  44.     private int barSpace = 5;
  45.  
  46.     private int widthPerItem;
  47.     private System.DateTime _mouseOverColumnValue;
  48.     private string _mouseOverRowText = "";
  49.  
  50.     private object _mouseOverRowValue = null;
  51.     private Pen lineColor = Pens.Bisque;
  52.     private Font dateTextFont = new Font("VERDANA", 8.0f, FontStyle.Regular, GraphicsUnit.Point);
  53.     private Font timeTextFont = new Font("VERDANA", 8.0f, FontStyle.Regular, GraphicsUnit.Point);
  54.  
  55.     private Font rowTextFont = new Font("VERDANA", 8.0f, FontStyle.Regular, GraphicsUnit.Point);
  56.     private System.Windows.Forms.ToolTip withEventsField_ToolTip = new System.Windows.Forms.ToolTip();
  57.     internal System.Windows.Forms.ToolTip ToolTip
  58.     {
  59.         get { return withEventsField_ToolTip; }
  60.         set
  61.         {
  62.             if (withEventsField_ToolTip != null)
  63.             {
  64.                 withEventsField_ToolTip.Draw -= ToolTipText_Draw;
  65.                 withEventsField_ToolTip.Popup -= ToolTipText_Popup;
  66.             }
  67.             withEventsField_ToolTip = value;
  68.             if (withEventsField_ToolTip != null)
  69.             {
  70.                 withEventsField_ToolTip.Draw += ToolTipText_Draw;
  71.                 withEventsField_ToolTip.Popup += ToolTipText_Popup;
  72.             }
  73.         }
  74.  
  75.     }
  76.  
  77.     private bool _allowEditBarWithMouse = false;
  78.     public event MouseDraggedEventHandler MouseDragged;
  79.     public delegate void MouseDraggedEventHandler(object sender, System.Windows.Forms.MouseEventArgs e);
  80.     public event BarChangedEventHandler BarChanged;
  81.     public delegate void BarChangedEventHandler(object sender, object barValue);
  82.     public event BarChangingEventHandler BarChanging;
  83.     public delegate void BarChangingEventHandler(object sender, object barValue);
  84.  
  85.     private Bitmap objBmp;
  86.  
  87.     private Graphics objGraphics;
  88.  
  89.     protected new bool DesignMode
  90.     {
  91.         get
  92.         {
  93.             if (base.DesignMode)
  94.                 return true;
  95.  
  96.             return System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime;
  97.         }
  98.     }
  99.  
  100.     #region "Public properties"
  101.  
  102.     /// <summary>
  103.     /// Sets to true if the user should be able to manually edit bars
  104.     /// </summary>
  105.     /// <value></value>
  106.     /// <returns></returns>
  107.     /// <remarks></remarks>
  108.  
  109.     public bool AllowManualEditBar
  110.     {
  111.         get { return _allowEditBarWithMouse; }
  112.         set { _allowEditBarWithMouse = value; }
  113.     }
  114.  
  115.     /// <summary>
  116.     /// The start date/time of the chart
  117.     /// </summary>
  118.     /// <value></value>
  119.     /// <returns></returns>
  120.     /// <remarks></remarks>
  121.  
  122.     public System.DateTime FromDate
  123.     {
  124.         get { return headerFromDate; }
  125.         set { headerFromDate = value; }
  126.     }
  127.  
  128.     /// <summary>
  129.     /// The end date/time of the chart
  130.     /// </summary>
  131.     /// <value></value>
  132.     /// <returns></returns>
  133.     /// <remarks></remarks>
  134.  
  135.     public System.DateTime ToDate
  136.     {
  137.         get { return headerToDate; }
  138.         set { headerToDate = value; }
  139.     }
  140.  
  141.     /// <summary>
  142.     /// The text for the current row the mouse hovers above
  143.     /// </summary>
  144.     /// <value></value>
  145.     /// <returns></returns>
  146.     /// <remarks></remarks>
  147.  
  148.     public string MouseOverRowText
  149.     {
  150.         get { return _mouseOverRowText; }
  151.     }
  152.  
  153.     /// <summary>
  154.     /// The value for the current bar the mouse hovers above
  155.     /// </summary>
  156.     /// <value></value>
  157.     /// <returns></returns>
  158.     /// <remarks></remarks>
  159.  
  160.     public object MouseOverRowValue
  161.     {
  162.         get { return _mouseOverRowValue; }
  163.     }
  164.  
  165.     /// <summary>
  166.     /// The date/time the mouse hovers above
  167.     /// </summary>
  168.     /// <value></value>
  169.     /// <returns></returns>
  170.     /// <remarks></remarks>
  171.  
  172.     public System.DateTime MouseOverColumnDate
  173.     {
  174.         get { return _mouseOverColumnValue; }
  175.     }
  176.  
  177.     /// <summary>
  178.     /// The color of the grid
  179.     /// </summary>
  180.     /// <value></value>
  181.     /// <returns></returns>
  182.     /// <remarks></remarks>
  183.  
  184.     public System.Drawing.Pen GridColor
  185.     {
  186.         get { return lineColor; }
  187.         set { lineColor = value; }
  188.     }
  189.  
  190.     /// <summary>
  191.     /// The font used for the row text
  192.     /// </summary>
  193.     /// <value></value>
  194.     /// <returns></returns>
  195.     /// <remarks></remarks>
  196.  
  197.     public Font RowFont
  198.     {
  199.         get { return rowTextFont; }
  200.         set { rowTextFont = value; }
  201.     }
  202.  
  203.     /// <summary>
  204.     /// The font used for the "date" text in the columns
  205.     /// </summary>
  206.     /// <value></value>
  207.     /// <returns></returns>
  208.     /// <remarks></remarks>
  209.  
  210.     public Font DateFont
  211.     {
  212.         get { return dateTextFont; }
  213.         set { dateTextFont = value; }
  214.     }
  215.  
  216.     /// <summary>
  217.     /// The font used for the "time" text in the colums)
  218.     /// </summary>
  219.     /// <value></value>
  220.     /// <returns></returns>
  221.     /// <remarks></remarks>
  222.  
  223.     public Font TimeFont
  224.     {
  225.         get { return timeTextFont; }
  226.         set { timeTextFont = value; }
  227.     }
  228.  
  229.     #endregion
  230.  
  231.     #region "Constructor"
  232.  
  233.     /// <summary>
  234.     /// Default constructor
  235.     /// </summary>
  236.     /// <remarks></remarks>
  237.  
  238.     public GanttChart()
  239.     {
  240.         MouseWheel += GanttChart_MouseWheel;
  241.         MouseClick += GanttChart_Click;
  242.         MouseDragged += GanttChart_MouseDragged;
  243.         MouseLeave += GanttChart_MouseLeave;
  244.         MouseMove += GanttChart_MouseMove;
  245.         ToolTip.AutoPopDelay = 15000;
  246.         ToolTip.InitialDelay = 250;
  247.         ToolTip.OwnerDraw = true;
  248.         objBmp = new Bitmap(1280, 1024, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  249.         objGraphics = Graphics.FromImage(objBmp);
  250.         if (!DesignMode)
  251.         {
  252.             // Flicker free drawing
  253.             this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
  254.         }
  255.  
  256.     }
  257.  
  258.     #endregion
  259.  
  260.     #region "Bars"
  261.  
  262.     private void SetBarStartLeft(string rowText)
  263.     {
  264.         Graphics gfx = this.CreateGraphics();
  265.  
  266.         int length = Convert.ToInt32(gfx.MeasureString(rowText, rowTextFont, 500).Width);
  267.  
  268.         if (length > barStartLeft)
  269.         {
  270.             barStartLeft = length;
  271.         }
  272.     }
  273.  
  274.     /// <summary>
  275.     /// Adds a bar to the list
  276.     /// </summary>
  277.     /// <param name="rowText">Text for the row</param>
  278.     /// <param name="barValue">Value for the row</param>
  279.     /// <param name="fromTime">The date/time the bar starts</param>
  280.     /// <param name="toTime">The date/time the bar ends</param>
  281.     /// <param name="color">The color of the bar</param>
  282.     /// <param name="hoverColor">The hover color of the bar</param>
  283.     /// <param name="rowIndex">The rowindex of the bar (useful if you want several bars on the same row)</param>
  284.     /// <remarks></remarks>
  285.  
  286.     public void AddChartBar(string rowText, object barValue, System.DateTime fromTime, System.DateTime toTime, Color color, Color hoverColor, int rowIndex)
  287.     {
  288.         ChartBarDate bar = new ChartBarDate();
  289.         bar.Text = rowText;
  290.         bar.Value = barValue;
  291.         bar.StartValue = fromTime;
  292.         bar.EndValue = toTime;
  293.         bar.Color = color;
  294.         bar.HoverColor = hoverColor;
  295.         bar.RowIndex = rowIndex;
  296.         bars.Add(bar);
  297.  
  298.         SetBarStartLeft(rowText);
  299.     }
  300.  
  301.     /// <summary>
  302.     /// Adds a bar to the list
  303.     /// </summary>
  304.     /// <param name="rowText">Text for the row</param>
  305.     /// <param name="barValue">Value for the row</param>
  306.     /// <param name="fromTime">The date/time the bar starts</param>
  307.     /// <param name="toTime">The date/time the bar ends</param>
  308.     /// <param name="color">The color of the bar</param>
  309.     /// <param name="hoverColor">The hover color of the bar</param>
  310.     /// <param name="rowIndex">The rowindex of the bar (useful if you want several bars on the same row)</param>
  311.     /// <param name="hideFromMouseMove">If you want to "hide" the bar from mousemove event</param>
  312.     /// <remarks></remarks>
  313.  
  314.     public void AddChartBar(string rowText, object barValue, System.DateTime fromTime, System.DateTime toTime, Color color, Color hoverColor, int rowIndex, bool hideFromMouseMove)
  315.     {
  316.         ChartBarDate bar = new ChartBarDate();
  317.         bar.Text = rowText;
  318.         bar.Value = barValue;
  319.         bar.StartValue = fromTime;
  320.         bar.EndValue = toTime;
  321.         bar.Color = color;
  322.         bar.HoverColor = hoverColor;
  323.         bar.RowIndex = rowIndex;
  324.         bar.HideFromMouseMove = hideFromMouseMove;
  325.         bars.Add(bar);
  326.  
  327.         SetBarStartLeft(rowText);
  328.     }
  329.  
  330.     /// <summary>
  331.     /// Gets the next index
  332.     /// </summary>
  333.     /// <param name="rowText"></param>
  334.     /// <returns></returns>
  335.     /// <remarks></remarks>
  336.  
  337.     public int GetIndexChartBar(string rowText)
  338.     {
  339.         int index = -1;
  340.  
  341.         foreach (ChartBarDate bar in bars)
  342.         {
  343.             if (bar.Text.Equals(rowText) == true)
  344.             {
  345.                 return bar.RowIndex;
  346.             }
  347.             if (bar.RowIndex > index)
  348.             {
  349.                 index = bar.RowIndex;
  350.             }
  351.         }
  352.  
  353.         return index + 1;
  354.     }
  355.  
  356.     /// <summary>
  357.     /// Removes all bars from list
  358.     /// </summary>
  359.     /// <remarks></remarks>
  360.  
  361.     public void RemoveBars()
  362.     {
  363.         bars = new List<ChartBarDate>();
  364.  
  365.         barStartLeft = 100;
  366.     }
  367.  
  368.     #endregion
  369.  
  370.     #region "Draw"
  371.  
  372.     /// <summary>
  373.     /// Redraws the Gantt chart
  374.     /// </summary>
  375.     /// <remarks></remarks>
  376.  
  377.     public void PaintChart()
  378.     {
  379.         this.Invalidate();
  380.     }
  381.  
  382.     /// <summary>
  383.     /// Redraws the Gantt chart
  384.     /// </summary>
  385.     /// <param name="gfx"></param>
  386.     /// <remarks></remarks>
  387.  
  388.     private void PaintChart(Graphics gfx)
  389.     {
  390.         gfx.Clear(this.BackColor);
  391.  
  392.         if (headerFromDate == null | headerToDate == null)
  393.             return;
  394.  
  395.         DrawScrollBar(gfx);
  396.         DrawHeader(gfx, null);
  397.         DrawNetHorizontal(gfx);
  398.         DrawNetVertical(gfx);
  399.         DrawBars(gfx);
  400.  
  401.         objBmp = new Bitmap(this.Width - barStartRight, lastLineStop, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  402.         objGraphics = Graphics.FromImage(objBmp);
  403.     }
  404.  
  405.     /// <summary>
  406.     /// Redraws the Gantt chart
  407.     /// </summary>
  408.     /// <param name="pe"></param>
  409.     /// <remarks></remarks>
  410.  
  411.     protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
  412.     {
  413.         base.OnPaint(pe);
  414.         if (!DesignMode)
  415.         {
  416.             PaintChart(pe.Graphics);
  417.         }
  418.     }
  419.  
  420.     /// <summary>
  421.     /// Draws the list of headers. Automatically shows which headers to draw, based on the width of the Gantt Chart
  422.     /// </summary>
  423.     /// <param name="gfx"></param>
  424.     /// <param name="headerList"></param>
  425.     /// <remarks></remarks>
  426.  
  427.     private void DrawHeader(Graphics gfx, List<Header> headerList)
  428.     {
  429.         if (headerList == null)
  430.         {
  431.             headerList = GetFullHeaderList();
  432.         }
  433.  
  434.         if (headerList.Count == 0)
  435.             return;
  436.  
  437.         dynamic availableWidth = this.Width - 10 - barStartLeft - barStartRight;
  438.         widthPerItem = availableWidth / headerList.Count;
  439.  
  440.         if (widthPerItem < 40)
  441.         {
  442.             List<Header> newHeaderList = new List<Header>();
  443.  
  444.             bool showNext = true;
  445.  
  446.             // If there's not enough room for all headers remove 50%
  447.  
  448.             foreach (Header header in headerList)
  449.             {
  450.                 if (showNext == true)
  451.                 {
  452.                     newHeaderList.Add(header);
  453.                     showNext = false;
  454.                 }
  455.                 else
  456.                 {
  457.                     showNext = true;
  458.                 }
  459.             }
  460.  
  461.             DrawHeader(gfx, newHeaderList);
  462.             return;
  463.         }
  464.  
  465.         int index = 0;
  466.         int headerStartPosition = -1;
  467.         Header lastHeader = null;
  468.  
  469.         foreach (Header header in headerList)
  470.         {
  471.             int startPos = barStartLeft + (index * widthPerItem);
  472.             bool showDateHeader = false;
  473.  
  474.             header.StartLocation = startPos;
  475.  
  476.             // Checks whether to show the date or not
  477.  
  478.             if (lastHeader == null)
  479.             {
  480.                 showDateHeader = true;
  481.             }
  482.             else if (header.Time.Hour < lastHeader.Time.Hour)
  483.             {
  484.                 showDateHeader = true;
  485.             }
  486.             else if (header.Time.Minute == lastHeader.Time.Minute)
  487.             {
  488.                 showDateHeader = true;
  489.             }
  490.  
  491.             // Show date
  492.  
  493.             if (showDateHeader == true)
  494.             {
  495.                 string str = "";
  496.  
  497.                 if (header.HeaderTextInsteadOfTime.Length > 0)
  498.                 {
  499.                     str = header.HeaderTextInsteadOfTime;
  500.                 }
  501.                 else
  502.                 {
  503.                     str = header.Time.ToString("d-MMM");
  504.                 }
  505.                 gfx.DrawString(str, dateTextFont, Brushes.Black, startPos, 0);
  506.             }
  507.  
  508.             // Show time
  509.  
  510.             gfx.DrawString(header.HeaderText, timeTextFont, Brushes.Black, startPos, headerTimeStartTop);
  511.             index += 1;
  512.  
  513.             lastHeader = header;
  514.         }
  515.  
  516.         shownHeaderList = headerList;
  517.         widthPerItem = (this.Width - 10 - barStartLeft - barStartRight) / shownHeaderList.Count;
  518.     }
  519.  
  520.     /// <summary>
  521.     /// Draws the bars
  522.     /// </summary>
  523.     /// <param name="grfx"></param>
  524.     /// <remarks></remarks>
  525.  
  526.     private void DrawBars(Graphics grfx, bool ignoreScrollAndMousePosition = false)
  527.     {
  528.         if (shownHeaderList == null)
  529.             return;
  530.         if (shownHeaderList.Count == 0)
  531.             return;
  532.  
  533.         int index = 0;
  534.  
  535.         // Finds pixels per minute
  536.  
  537.         TimeSpan timeBetween = shownHeaderList[1].Time - shownHeaderList[0].Time;
  538.         int minutesBetween = Convert.ToInt32(timeBetween.TotalMinutes);
  539.         //(timeBetween.Days * 1440) + (timeBetween.Hours * 60) + timeBetween.Minutes
  540.         dynamic widthBetween = (shownHeaderList[1].StartLocation - shownHeaderList[0].StartLocation);
  541.         decimal perMinute = Convert.ToDecimal(widthBetween) / Convert.ToDecimal(minutesBetween);
  542.  
  543.         // Draws each bar
  544.  
  545.         foreach (ChartBarDate bar in bars)
  546.         {
  547.             index = bar.RowIndex;
  548.  
  549.             int startLocation = 0;
  550.             int width = 0;
  551.             int startMinutes = 0;
  552.             // Number of minutes from start of the gantt chart
  553.             TimeSpan startTimeSpan = default(TimeSpan);
  554.             int lengthMinutes = 0;
  555.             // Number of minutes from bar start to bar end
  556.             TimeSpan lengthTimeSpan = default(TimeSpan);
  557.  
  558.             int scrollPos = 0;
  559.  
  560.             if (ignoreScrollAndMousePosition == false)
  561.             {
  562.                 scrollPos = scrollPosition;
  563.             }
  564.  
  565.             // Calculates where the bar should be located
  566.  
  567.             startTimeSpan = bar.StartValue - FromDate;
  568.             startMinutes = (startTimeSpan.Days * 1440) + (startTimeSpan.Hours * 60) + startTimeSpan.Minutes;
  569.  
  570.             startLocation = Convert.ToInt32(perMinute * startMinutes);
  571.  
  572.             System.DateTime endValue = bar.EndValue;
  573.  
  574.             if (endValue == null)
  575.             {
  576.                 endValue = System.DateTime.Now;
  577.             }
  578.  
  579.             lengthTimeSpan = endValue - bar.StartValue;
  580.             lengthMinutes = (lengthTimeSpan.Days * 1440) + (lengthTimeSpan.Hours * 60) + lengthTimeSpan.Minutes;
  581.  
  582.             width = Convert.ToInt32(perMinute * lengthMinutes);
  583.  
  584.             int a = barStartLeft + startLocation;
  585.             int b = barStartTop + (barHeight * (index - scrollPos)) + (barSpace * (index - scrollPos)) + 2;
  586.             int c = width;
  587.             int d = barHeight;
  588.  
  589.             if (c == 0)
  590.                 c = 1;
  591.  
  592.             // Stops a bar from going into the row-text area
  593.  
  594.             if (a - barStartLeft < 0)
  595.             {
  596.                 a = barStartLeft;
  597.             }
  598.  
  599.             System.Drawing.Color color = default(System.Drawing.Color);
  600.  
  601.             // If mouse is over bar, set the color to be hovercolor
  602.  
  603.             if (MouseOverRowText == bar.Text & bar.StartValue <= _mouseOverColumnValue & bar.EndValue >= _mouseOverColumnValue)
  604.             {
  605.                 color = bar.HoverColor;
  606.             }
  607.             else
  608.             {
  609.                 color = bar.Color;
  610.             }
  611.  
  612.             // Set the location for the graphics
  613.  
  614.             bar.TopLocation.Left = new Point(a, b);
  615.             bar.TopLocation.Right = new Point(a + c, b);
  616.             bar.BottomLocation.Left = new Point(a, b + d);
  617.             bar.BottomLocation.Right = new Point(a, b + d);
  618.  
  619.             LinearGradientBrush obBrush = null;
  620.             Rectangle obRect = new Rectangle(a, b, c, d);
  621.  
  622.             if (bar.StartValue != null & endValue != null)
  623.             {
  624.  
  625.                 if ((index >= scrollPos & index < barsViewable + scrollPos) | ignoreScrollAndMousePosition == true)
  626.                 {
  627.                     // Makes the bar gradient
  628.  
  629.                     obBrush = new LinearGradientBrush(obRect, color, Color.Gray, LinearGradientMode.Vertical);
  630.  
  631.                     // Draws the bar
  632.  
  633.                     grfx.DrawRectangle(Pens.Black, obRect);
  634.                     grfx.FillRectangle(obBrush, obRect);
  635.  
  636.                     // Draws the rowtext
  637.  
  638.                     grfx.DrawString(bar.Text, rowTextFont, Brushes.Black, 0, barStartTop + (barHeight * (index - scrollPos)) + (barSpace * (index - scrollPos)));
  639.  
  640.                     obBrush = null;
  641.                     //obRect = null;
  642.                     //obRect.TryDispose();
  643.                     obBrush = null;
  644.                 }
  645.             }
  646.  
  647.             //color = null;
  648.             //color.TryDispose();
  649.         }
  650.     }
  651.  
  652.     /// <summary>
  653.     /// Draws the vertical lines
  654.     /// </summary>
  655.     /// <param name="grfx"></param>
  656.     /// <remarks></remarks>
  657.  
  658.     public void DrawNetVertical(Graphics grfx)
  659.     {
  660.         if (shownHeaderList == null)
  661.             return;
  662.         if (shownHeaderList.Count == 0)
  663.             return;
  664.  
  665.         int index = 0;
  666.         int availableWidth = this.Width - 10 - barStartLeft - barStartRight;
  667.         Header lastHeader = null;
  668.  
  669.         foreach (Header header in shownHeaderList)
  670.         {
  671.             int headerLocationY = 0;
  672.  
  673.             if (lastHeader == null)
  674.             {
  675.                 headerLocationY = 0;
  676.             }
  677.             else if (header.Time.Hour < lastHeader.Time.Hour)
  678.             {
  679.                 headerLocationY = 0;
  680.             }
  681.             else
  682.             {
  683.                 headerLocationY = headerTimeStartTop;
  684.             }
  685.  
  686.             grfx.DrawLine(Pens.Bisque, barStartLeft + (index * widthPerItem), headerLocationY, barStartLeft + (index * widthPerItem), lastLineStop);
  687.             index += 1;
  688.  
  689.             lastHeader = header;
  690.         }
  691.  
  692.         grfx.DrawLine(lineColor, barStartLeft + (index * widthPerItem), headerTimeStartTop, barStartLeft + (index * widthPerItem), lastLineStop);
  693.     }
  694.  
  695.     /// <summary>
  696.     /// Draws the horizontal lines
  697.     /// </summary>
  698.     /// <param name="grfx"></param>
  699.     /// <remarks></remarks>
  700.  
  701.     public void DrawNetHorizontal(Graphics grfx)
  702.     {
  703.         if (shownHeaderList == null)
  704.             return;
  705.         if (shownHeaderList.Count == 0)
  706.             return;
  707.  
  708.         int index = 0;
  709.         int width = (widthPerItem * shownHeaderList.Count) + barStartLeft;
  710.  
  711.         // Last used index. Hopefully nobody will make a row named QQQ :o)
  712.         for (index = 0; index <= GetIndexChartBar("QQQQQQ"); index++)
  713.         {
  714.             foreach (ChartBarDate bar in bars)
  715.             {
  716.                 grfx.DrawLine(lineColor, 0, barStartTop + (barHeight * index) + (barSpace * index), width, barStartTop + (barHeight * index) + (barSpace * index));
  717.             }
  718.         }
  719.  
  720.         lastLineStop = barStartTop + (barHeight * (index - 1)) + (barSpace * (index - 1));
  721.     }
  722.  
  723.     // This is the position (in pixels, from top) of the last line. Used for drawing lines
  724.  
  725.  
  726.     private int lastLineStop = 0;
  727.     #endregion
  728.  
  729.     #region "Header list"
  730.  
  731.     /// <summary>
  732.     /// Gets the full header list, consisting of hours between the two dates set
  733.     /// </summary>
  734.     /// <returns></returns>
  735.     /// <remarks></remarks>
  736.  
  737.     private List<Header> GetFullHeaderList()
  738.     {
  739.         List<Header> result = new List<Header>();
  740.         System.DateTime newFromTime = new System.DateTime(FromDate.Year, FromDate.Month, FromDate.Day);
  741.         string item = null;
  742.  
  743.         TimeSpan interval = ToDate - FromDate;
  744.  
  745.         if (interval.TotalDays < 1)
  746.         {
  747.             var _with1 = newFromTime;
  748.             newFromTime = _with1.AddHours(FromDate.Hour);
  749.  
  750.             if (headerFromDate.Minute < 59 & headerFromDate.Minute > 29)
  751.             {
  752.                 newFromTime = _with1.AddMinutes(30);
  753.             }
  754.             else
  755.             {
  756.                 newFromTime = _with1.AddMinutes(0);
  757.             }
  758.  
  759.             while (newFromTime <= ToDate)
  760.             {
  761.                 item = newFromTime.Hour + ":";
  762.  
  763.                 if (newFromTime.Minute < 10)
  764.                 {
  765.                     item += "0" + newFromTime.Minute;
  766.                 }
  767.                 else
  768.                 {
  769.                     item += "" + newFromTime.Minute;
  770.                 }
  771.  
  772.                 Header header = new Header();
  773.  
  774.                 header.HeaderText = item;
  775.                 header.HeaderTextInsteadOfTime = "";
  776.                 header.Time = new System.DateTime(newFromTime.Year, newFromTime.Month, newFromTime.Day, newFromTime.Hour, newFromTime.Minute, 0);
  777.                 result.Add(header);
  778.  
  779.                 newFromTime = newFromTime.AddMinutes(5);
  780.                 // The minimum interval of time between the headers
  781.             }
  782.         }
  783.         else if (interval.TotalDays < 60)
  784.         {
  785.             while (newFromTime <= ToDate)
  786.             {
  787.                 Header header = new Header();
  788.  
  789.                 header.HeaderText = "";
  790.                 header.HeaderTextInsteadOfTime = "";
  791.                 header.Time = new System.DateTime(newFromTime.Year, newFromTime.Month, newFromTime.Day, 0, 0, 0);
  792.                 result.Add(header);
  793.  
  794.                 newFromTime = newFromTime.AddDays(1);
  795.                 // The minimum interval of time between the headers
  796.             }
  797.         }
  798.         else
  799.         {
  800.             while (newFromTime <= ToDate)
  801.             {
  802.                 Header header = new Header();
  803.  
  804.                 header.HeaderText = "";
  805.                 header.Time = new System.DateTime(newFromTime.Year, newFromTime.Month, newFromTime.Day, 0, 0, 0);
  806.                 header.HeaderTextInsteadOfTime = newFromTime.ToString("MMM");
  807.                 result.Add(header);
  808.  
  809.                 newFromTime = newFromTime.AddMonths(1);
  810.                 // The minimum interval of time between the headers
  811.             }
  812.         }
  813.  
  814.         return result;
  815.     }
  816.  
  817.     #endregion
  818.  
  819.     #region "Mouse Move"
  820.  
  821.     /// <summary>
  822.     /// Finds the current row and column based on mouse position
  823.     /// </summary>
  824.     /// <param name="sender"></param>
  825.     /// <param name="e"></param>
  826.     /// <remarks></remarks>
  827.  
  828.     private void GanttChart_MouseMove(System.Object sender, System.Windows.Forms.MouseEventArgs e)
  829.     {
  830.         if (shownHeaderList == null)
  831.             return;
  832.         if (shownHeaderList.Count == 0)
  833.             return;
  834.  
  835.         if (e.Button != System.Windows.Forms.MouseButtons.Left)
  836.         {
  837.             mouseHoverPart = MouseOverPart.Empty;
  838.  
  839.             // If bar has changed manually, but left mouse button is no longer pressed the BarChanged event will be raised
  840.  
  841.             if (AllowManualEditBar == true)
  842.             {
  843.                 if (barIsChanging >= 0)
  844.                 {
  845.                     if (BarChanged != null)
  846.                     {
  847.                         BarChanged(this, bars[barIsChanging].Value);
  848.                     }
  849.                     barIsChanging = -1;
  850.                 }
  851.             }
  852.         }
  853.         else if (e.Button == System.Windows.Forms.MouseButtons.Left)
  854.         {
  855.             if (AllowManualEditBar == true)
  856.             {
  857.                 if (barIsChanging >= 0)
  858.                 {
  859.                     if (BarChanging != null)
  860.                     {
  861.                         BarChanging(this, bars[barIsChanging].Value);
  862.                     }
  863.                 }
  864.             }
  865.         }
  866.  
  867.         mouseHoverBarIndex = -1;
  868.  
  869.         Point LocalMousePosition = default(Point);
  870.  
  871.         LocalMousePosition = this.PointToClient(Cursor.Position);
  872.  
  873.         // Finds pixels per minute
  874.  
  875.         TimeSpan timeBetween = shownHeaderList[1].Time - shownHeaderList[0].Time;
  876.         int minutesBetween = (timeBetween.Days * 1440) + (timeBetween.Hours * 60) + timeBetween.Minutes;
  877.         dynamic widthBetween = (shownHeaderList[1].StartLocation - shownHeaderList[0].StartLocation);
  878.         decimal perMinute = Convert.ToDecimal(widthBetween) / Convert.ToDecimal(minutesBetween);
  879.  
  880.         // Finds the time at mousepointer
  881.  
  882.         int minutesAtCursor = 0;
  883.  
  884.         if (LocalMousePosition.X > barStartLeft && perMinute > 0)
  885.         {
  886.             minutesAtCursor = Convert.ToInt32((LocalMousePosition.X - barStartLeft) / perMinute);
  887.             _mouseOverColumnValue = FromDate.AddMinutes(minutesAtCursor);
  888.         }
  889.         else
  890.         {
  891.             //_mouseOverColumnValue.TryDispose();
  892.         }
  893.  
  894.         // Finds the row at mousepointer
  895.  
  896.         string rowText = "";
  897.         object rowValue = null;
  898.         string columnText = "";
  899.  
  900.         // Tests to see if the mouse pointer is hovering above the scrollbar
  901.  
  902.         bool scrollBarStatusChanged = false;
  903.  
  904.         // Tests to see if the mouse is hovering over the scroll-area bottom-arrow
  905.  
  906.         if (LocalMousePosition.X > BottomPart.Left & LocalMousePosition.Y < BottomPart.Right & LocalMousePosition.Y < BottomPart.Bottom & LocalMousePosition.Y > BottomPart.Top)
  907.         {
  908.             if (mouseOverBottomPart == false)
  909.             {
  910.                 scrollBarStatusChanged = true;
  911.             }
  912.  
  913.             mouseOverBottomPart = true;
  914.         }
  915.         else
  916.         {
  917.             if (mouseOverBottomPart == false)
  918.             {
  919.                 scrollBarStatusChanged = true;
  920.             }
  921.  
  922.             mouseOverBottomPart = false;
  923.         }
  924.  
  925.         // Tests to see if the mouse is hovering over the scroll-area top-arrow
  926.  
  927.         if (LocalMousePosition.X > topPart.Left & LocalMousePosition.Y < topPart.Right & LocalMousePosition.Y < topPart.Bottom & LocalMousePosition.Y > topPart.Top)
  928.         {
  929.             if (mouseOverTopPart == false)
  930.             {
  931.                 scrollBarStatusChanged = true;
  932.             }
  933.  
  934.             mouseOverTopPart = true;
  935.         }
  936.         else
  937.         {
  938.             if (mouseOverTopPart == false)
  939.             {
  940.                 scrollBarStatusChanged = true;
  941.             }
  942.  
  943.             mouseOverTopPart = false;
  944.         }
  945.  
  946.         // Tests to see if the mouse is hovering over the scroll
  947.  
  948.         if (LocalMousePosition.X > scroll.Left & LocalMousePosition.Y < scroll.Right & LocalMousePosition.Y < scroll.Bottom & LocalMousePosition.Y > scroll.Top)
  949.         {
  950.             if (mouseOverScrollBar == false)
  951.             {
  952.                 scrollBarStatusChanged = true;
  953.             }
  954.  
  955.             mouseOverScrollBar = true;
  956.             mouseOverScrollBarArea = true;
  957.         }
  958.         else
  959.         {
  960.             if (mouseOverScrollBar == false)
  961.             {
  962.                 scrollBarStatusChanged = true;
  963.             }
  964.  
  965.             mouseOverScrollBar = false;
  966.             mouseOverScrollBarArea = false;
  967.         }
  968.  
  969.         // If the mouse is not above the scroll, test if it's over the scroll area (no need to test if it's not above the scroll)
  970.  
  971.         if (mouseOverScrollBarArea == false)
  972.         {
  973.             if (LocalMousePosition.X > scrollBarArea.Left & LocalMousePosition.Y < scrollBarArea.Right & LocalMousePosition.Y < scrollBarArea.Bottom & LocalMousePosition.Y > scrollBarArea.Top)
  974.             {
  975.                 mouseOverScrollBarArea = true;
  976.             }
  977.         }
  978.  
  979.  
  980.         // Tests to see if the mouse pointer is hovering above a bar
  981.  
  982.         int index = 0;
  983.  
  984.  
  985.         foreach (ChartBarDate bar in bars)
  986.         {
  987.             // If the bar is set to be hidden from mouse move, the current bar will be ignored
  988.  
  989.             if (bar.HideFromMouseMove == false)
  990.             {
  991.                 if (bar.EndValue == null)
  992.                 {
  993.                     bar.EndValue = System.DateTime.Now;
  994.                 }
  995.  
  996.                 // Mouse pointer needs to be inside the X and Y positions of the bar
  997.  
  998.                 if (LocalMousePosition.Y > bar.TopLocation.Left.Y & LocalMousePosition.Y < bar.BottomLocation.Left.Y)
  999.                 {
  1000.  
  1001.                     if (LocalMousePosition.X > bar.TopLocation.Left.X & LocalMousePosition.X < bar.TopLocation.Right.X)
  1002.                     {
  1003.                         // If the current bar is the one where the mouse is above, the rowText and rowValue needs to be set correctly
  1004.  
  1005.                         rowText = bar.Text;
  1006.                         rowValue = bar.Value;
  1007.                         mouseHoverBarIndex = index;
  1008.  
  1009.                         if (mouseHoverPart != MouseOverPart.BarLeftSide & mouseHoverPart != MouseOverPart.BarRightSide)
  1010.                         {
  1011.                             mouseHoverPart = MouseOverPart.Bar;
  1012.                         }
  1013.                     }
  1014.  
  1015.                     // If mouse pointer is near the edges of the bar it will open up for editing the bar
  1016.  
  1017.                     if (AllowManualEditBar == true)
  1018.                     {
  1019.                         int areaSize = 5;
  1020.  
  1021.                         if (e.Button == System.Windows.Forms.MouseButtons.Left)
  1022.                         {
  1023.                             areaSize = 50;
  1024.                         }
  1025.  
  1026.                         if (LocalMousePosition.X > bar.TopLocation.Left.X - areaSize & LocalMousePosition.X < bar.TopLocation.Left.X + areaSize & mouseHoverPart != MouseOverPart.BarRightSide)
  1027.                         {
  1028.                             this.Cursor = Cursors.VSplit;
  1029.                             mouseHoverPart = MouseOverPart.BarLeftSide;
  1030.                             mouseHoverBarIndex = index;
  1031.                         }
  1032.                         else if (LocalMousePosition.X > bar.TopLocation.Right.X - areaSize & LocalMousePosition.X < bar.TopLocation.Right.X + areaSize & mouseHoverPart != MouseOverPart.BarLeftSide)
  1033.                         {
  1034.                             this.Cursor = Cursors.VSplit;
  1035.                             mouseHoverPart = MouseOverPart.BarRightSide;
  1036.                             mouseHoverBarIndex = index;
  1037.                         }
  1038.                         else
  1039.                         {
  1040.                             this.Cursor = Cursors.Default;
  1041.                         }
  1042.                     }
  1043.                 }
  1044.             }
  1045.  
  1046.             index += 1;
  1047.         }
  1048.  
  1049.         // Sets the mouseover row value and text
  1050.  
  1051.         _mouseOverRowText = rowText;
  1052.         _mouseOverRowValue = rowValue;
  1053.  
  1054.         if (e.Button == System.Windows.Forms.MouseButtons.Left)
  1055.         {
  1056.             if (MouseDragged != null)
  1057.             {
  1058.                 MouseDragged(sender, e);
  1059.             }
  1060.  
  1061.         }
  1062.         else
  1063.         {
  1064.             // A simple test to see if the mousemovement has caused any changes to how it should be displayed
  1065.             // It only redraws if mouse moves from a bar to blank area or from blank area to a bar
  1066.             // This increases performance compared to having a redraw every time a mouse moves
  1067.  
  1068.             if ((_mouseOverRowValue == null & (rowValue != null)) | ((_mouseOverRowValue != null) & rowValue == null) | scrollBarStatusChanged == true)
  1069.             {
  1070.                 PaintChart();
  1071.             }
  1072.         }
  1073.     }
  1074.  
  1075.     /// <summary>
  1076.     /// Mouse leave event
  1077.     /// </summary>
  1078.     /// <param name="sender"></param>
  1079.     /// <param name="e"></param>
  1080.     /// <remarks></remarks>
  1081.  
  1082.     private void GanttChart_MouseLeave(System.Object sender, System.EventArgs e)
  1083.     {
  1084.         _mouseOverRowText = null;
  1085.         _mouseOverRowValue = null;
  1086.         mouseHoverPart = MouseOverPart.Empty;
  1087.  
  1088.         PaintChart();
  1089.     }
  1090.  
  1091.     /// <summary>
  1092.     /// Mouse drag event
  1093.     /// </summary>
  1094.     /// <param name="sender"></param>
  1095.     /// <param name="e"></param>
  1096.     /// <remarks></remarks>
  1097.  
  1098.     public void GanttChart_MouseDragged(object sender, System.Windows.Forms.MouseEventArgs e)
  1099.     {
  1100.         if (mouseOverScrollBarArea == true)
  1101.         {
  1102.             ScrollPositionY = e.Location.Y;
  1103.         }
  1104.  
  1105.         if (AllowManualEditBar == true)
  1106.         {
  1107.             if (mouseHoverBarIndex > -1)
  1108.             {
  1109.                 if (mouseHoverPart == MouseOverPart.BarLeftSide)
  1110.                 {
  1111.                     barIsChanging = mouseHoverBarIndex;
  1112.                     bars[mouseHoverBarIndex].StartValue = _mouseOverColumnValue;
  1113.                     PaintChart();
  1114.                 }
  1115.                 else if (mouseHoverPart == MouseOverPart.BarRightSide)
  1116.                 {
  1117.                     barIsChanging = mouseHoverBarIndex;
  1118.                     bars[mouseHoverBarIndex].EndValue = _mouseOverColumnValue;
  1119.                     PaintChart();
  1120.                 }
  1121.             }
  1122.         }
  1123.     }
  1124.  
  1125.  
  1126.     #endregion
  1127.  
  1128.     #region "ToolTipText"
  1129.  
  1130.     private List<string> _toolTipText = new List<string>();
  1131.  
  1132.     private string _toolTipTextTitle = "";
  1133.  
  1134.     private Point MyPoint = new Point(0, 0);
  1135.     /// <summary>
  1136.     /// The title to draw
  1137.     /// </summary>
  1138.     /// <value></value>
  1139.     /// <returns></returns>
  1140.     /// <remarks></remarks>
  1141.  
  1142.     public string ToolTipTextTitle
  1143.     {
  1144.         get { return _toolTipTextTitle; }
  1145.         set { _toolTipTextTitle = value; }
  1146.     }
  1147.  
  1148.     /// <summary>
  1149.     /// Gets or sets the ToolTipText lines
  1150.     /// </summary>
  1151.     /// <value></value>
  1152.     /// <returns></returns>
  1153.     /// <remarks>Don not use the add function directly on this, use ToolTipText = value</remarks>
  1154.  
  1155.     public List<string> ToolTipText
  1156.     {
  1157.         get
  1158.         {
  1159.             if (_toolTipText == null)
  1160.                 _toolTipText = new List<string>();
  1161.             return _toolTipText;
  1162.         }
  1163.         set
  1164.         {
  1165.             _toolTipText = value;
  1166.  
  1167.             Point LocalMousePosition = default(Point);
  1168.  
  1169.             LocalMousePosition = this.PointToClient(Cursor.Position);
  1170.  
  1171.  
  1172.             if (LocalMousePosition == MyPoint)
  1173.                 return;
  1174.  
  1175.             MyPoint = LocalMousePosition;
  1176.  
  1177.             ToolTip.SetToolTip(this, ".");
  1178.         }
  1179.     }
  1180.  
  1181.     /// <summary>
  1182.     /// Draws the ToolTip window
  1183.     /// </summary>
  1184.     /// <param name="sender"></param>
  1185.     /// <param name="e"></param>
  1186.     /// <remarks></remarks>
  1187.  
  1188.     private void ToolTipText_Draw(System.Object sender, System.Windows.Forms.DrawToolTipEventArgs e)
  1189.     {
  1190.         if (ToolTipText == null)
  1191.         {
  1192.             ToolTipText = new List<string>();
  1193.             return;
  1194.         }
  1195.  
  1196.         if (ToolTipText.Count == 0)
  1197.         {
  1198.             return;
  1199.         }
  1200.         else if (ToolTipText[0].Length == 0)
  1201.         {
  1202.             return;
  1203.         }
  1204.  
  1205.         int x = 0;
  1206.         int y = 0;
  1207.  
  1208.         e.Graphics.FillRectangle(Brushes.AntiqueWhite, e.Bounds);
  1209.         e.DrawBorder();
  1210.  
  1211.         int titleHeight = 14;
  1212.         int fontHeight = 12;
  1213.  
  1214.         // Draws the line just below the title
  1215.  
  1216.         e.Graphics.DrawLine(Pens.Black, 0, titleHeight, e.Bounds.Width, titleHeight);
  1217.  
  1218.         int lines = 1;
  1219.         string text = ToolTipTextTitle;
  1220.  
  1221.         // Draws the title
  1222.  
  1223.         using (Font font = new Font(e.Font, FontStyle.Bold))
  1224.         {
  1225.             x = Convert.ToInt32((e.Bounds.Width - e.Graphics.MeasureString(text, font).Width) / 2);
  1226.             y = Convert.ToInt32((titleHeight - e.Graphics.MeasureString(text, font).Height) / 2);
  1227.             e.Graphics.DrawString(text, font, Brushes.Black, x, y);
  1228.         }
  1229.  
  1230.         // Draws the lines
  1231.         for (int i = 0; i < ToolTipText.Count; i++)
  1232.         {
  1233.             Font font = new Font(e.Font, FontStyle.Regular);
  1234.  
  1235.             if (ToolTipText[i].Contains("[b]"))
  1236.             {
  1237.                 font = new Font(font.FontFamily, font.Size, FontStyle.Bold, font.Unit);
  1238.                 ToolTipText[i] = ToolTipText[i].Replace("[b]", "");
  1239.             }
  1240.  
  1241.             using (font)
  1242.             {
  1243.                 x = 5;
  1244.                 y = Convert.ToInt32((titleHeight - fontHeight - e.Graphics.MeasureString(ToolTipText[i], font).Height) / 2 + 10 + (lines * 14));
  1245.                 e.Graphics.DrawString(ToolTipText[i], font, Brushes.Black, x, y);
  1246.             }
  1247.  
  1248.             lines += 1;
  1249.         }
  1250.         //foreach (string str in ToolTipText)
  1251.         //{
  1252.         //    Font font = new Font(e.Font, FontStyle.Regular);
  1253.  
  1254.         //    if (str.Contains("[b]"))
  1255.         //    {
  1256.         //        font = new Font(font.FontFamily, font.Size, FontStyle.Bold, font.Unit);
  1257.         //        str = str.Replace("[b]", "");
  1258.         //    }
  1259.  
  1260.         //    using (font)
  1261.         //    {
  1262.         //        x = 5;
  1263.         //        y = Convert.ToInt32((titleHeight - fontHeight - e.Graphics.MeasureString(str, font).Height) / 2 + 10 + (lines * 14));
  1264.         //        e.Graphics.DrawString(str, font, Brushes.Black, x, y);
  1265.         //    }
  1266.  
  1267.         //    lines += 1;
  1268.         //}
  1269.     }
  1270.  
  1271.     /// <summary>
  1272.     /// Automatically resizes the ToolTip window
  1273.     /// </summary>
  1274.     /// <param name="sender"></param>
  1275.     /// <param name="e"></param>
  1276.     /// <remarks></remarks>
  1277.  
  1278.     private void ToolTipText_Popup(System.Object sender, System.Windows.Forms.PopupEventArgs e)
  1279.     {
  1280.         if (ToolTipText == null)
  1281.         {
  1282.             ToolTipText = new List<string>();
  1283.         }
  1284.  
  1285.         if (ToolTipText.Count == 0)
  1286.         {
  1287.             e.ToolTipSize = new Size(0, 0);
  1288.             return;
  1289.         }
  1290.         else if (ToolTipText[0].Length == 0)
  1291.         {
  1292.             e.ToolTipSize = new Size(0, 0);
  1293.             return;
  1294.         }
  1295.  
  1296.         // resizes the ToolTip window
  1297.  
  1298.         int height = 18 + (ToolTipText.Count * 15);
  1299.         e.ToolTipSize = new Size(200, height);
  1300.     }
  1301.  
  1302.     #endregion
  1303.  
  1304.     #region "ChartBar"
  1305.  
  1306.     private class ChartBarDate
  1307.     {
  1308.  
  1309.         internal class Location
  1310.         {
  1311.  
  1312.             private Point _right = new Point(0, 0);
  1313.  
  1314.             private Point _left = new Point(0, 0);
  1315.             public Point Right
  1316.             {
  1317.                 get { return _right; }
  1318.                 set { _right = value; }
  1319.             }
  1320.  
  1321.             public Point Left
  1322.             {
  1323.                 get { return _left; }
  1324.                 set { _left = value; }
  1325.             }
  1326.  
  1327.         }
  1328.  
  1329.         private System.DateTime _startValue;
  1330.  
  1331.         private System.DateTime _endValue;
  1332.         private Color _color;
  1333.  
  1334.         private Color _hoverColor;
  1335.         private string _text;
  1336.  
  1337.         private object _value;
  1338.  
  1339.         private int _rowIndex;
  1340.         private Location _topLocation = new Location();
  1341.  
  1342.         private Location _bottomLocation = new Location();
  1343.  
  1344.         private bool _hideFromMouseMove = false;
  1345.         public System.DateTime StartValue
  1346.         {
  1347.             get { return _startValue; }
  1348.             set { _startValue = value; }
  1349.         }
  1350.  
  1351.         public System.DateTime EndValue
  1352.         {
  1353.             get { return _endValue; }
  1354.             set { _endValue = value; }
  1355.         }
  1356.  
  1357.         public Color Color
  1358.         {
  1359.             get { return _color; }
  1360.             set { _color = value; }
  1361.         }
  1362.  
  1363.         public Color HoverColor
  1364.         {
  1365.             get { return _hoverColor; }
  1366.             set { _hoverColor = value; }
  1367.         }
  1368.  
  1369.         public string Text
  1370.         {
  1371.             get { return _text; }
  1372.             set { _text = value; }
  1373.         }
  1374.  
  1375.         public object Value
  1376.         {
  1377.             get { return _value; }
  1378.             set { _value = value; }
  1379.         }
  1380.  
  1381.         public int RowIndex
  1382.         {
  1383.             get { return _rowIndex; }
  1384.             set { _rowIndex = value; }
  1385.         }
  1386.  
  1387.         public bool HideFromMouseMove
  1388.         {
  1389.             get { return _hideFromMouseMove; }
  1390.             set { _hideFromMouseMove = value; }
  1391.         }
  1392.  
  1393.         internal Location TopLocation
  1394.         {
  1395.             get { return _topLocation; }
  1396.             set { _topLocation = value; }
  1397.         }
  1398.  
  1399.         internal Location BottomLocation
  1400.         {
  1401.             get { return _bottomLocation; }
  1402.             set { _bottomLocation = value; }
  1403.         }
  1404.  
  1405.     }
  1406.  
  1407.     #endregion
  1408.  
  1409.     #region "Headers"
  1410.  
  1411.     private class Header
  1412.     {
  1413.  
  1414.         private string _headerText;
  1415.         private int _startLocation;
  1416.         private string _headerTextInsteadOfTime = "";
  1417.  
  1418.         private System.DateTime _time;
  1419.         public string HeaderText
  1420.         {
  1421.             get { return _headerText; }
  1422.             set { _headerText = value; }
  1423.         }
  1424.  
  1425.         public int StartLocation
  1426.         {
  1427.             get { return _startLocation; }
  1428.             set { _startLocation = value; }
  1429.         }
  1430.  
  1431.         /// <summary>
  1432.         /// If this string is larger than 0, this will be used instead of Time
  1433.         /// </summary>
  1434.         /// <value></value>
  1435.         /// <returns></returns>
  1436.         /// <remarks></remarks>
  1437.  
  1438.         public string HeaderTextInsteadOfTime
  1439.         {
  1440.             get { return _headerTextInsteadOfTime; }
  1441.             set { _headerTextInsteadOfTime = value; }
  1442.         }
  1443.  
  1444.         /// <summary>
  1445.         /// Time to display
  1446.         /// </summary>
  1447.         /// <value></value>
  1448.         /// <returns></returns>
  1449.         /// <remarks></remarks>
  1450.  
  1451.         public System.DateTime Time
  1452.         {
  1453.             get { return _time; }
  1454.             set { _time = value; }
  1455.         }
  1456.  
  1457.     }
  1458.  
  1459.     #endregion
  1460.  
  1461.     #region "Resize"
  1462.  
  1463.     /// <summary>
  1464.     /// On resize the Gantt Chart is redrawn
  1465.     /// </summary>
  1466.     /// <param name="e"></param>
  1467.     /// <remarks></remarks>
  1468.  
  1469.     protected override void OnResize(System.EventArgs e)
  1470.     {
  1471.         base.OnResize(e);
  1472.  
  1473.         scrollPosition = 0;
  1474.  
  1475.         // Used for when the Gantt Chart is saved as an image
  1476.  
  1477.         if (lastLineStop > 0)
  1478.         {
  1479.             objBmp = new Bitmap(this.Width - barStartRight, lastLineStop, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  1480.             objGraphics = Graphics.FromImage(objBmp);
  1481.         }
  1482.  
  1483.         PaintChart();
  1484.     }
  1485.  
  1486.     #endregion
  1487.  
  1488.     #region "Scrollbar"
  1489.  
  1490.     private int barsViewable = -1;
  1491.     private int scrollPosition = 0;
  1492.     private Rectangle topPart;
  1493.     private Rectangle BottomPart;
  1494.     private Rectangle scroll;
  1495.  
  1496.     private Rectangle scrollBarArea;
  1497.     private bool mouseOverTopPart = false;
  1498.     private bool mouseOverBottomPart = false;
  1499.     private bool mouseOverScrollBar = false;
  1500.  
  1501.     private bool mouseOverScrollBarArea = false;
  1502.     /// <summary>
  1503.     /// Draws a scrollbar to the component, if there's a need for it
  1504.     /// </summary>
  1505.     /// <param name="grfx"></param>
  1506.     /// <remarks></remarks>
  1507.  
  1508.     private void DrawScrollBar(Graphics grfx)
  1509.     {
  1510.         barsViewable = (this.Height - barStartTop) / (barHeight + barSpace);
  1511.         int barCount = GetIndexChartBar("QQQWWW");
  1512.         if (barCount == 0)
  1513.             return;
  1514.  
  1515.         int maxHeight = this.Height - 30;
  1516.         decimal scrollHeight = (maxHeight / barCount) * barsViewable;
  1517.  
  1518.         // If the scroll area is filled there's no need to show the scrollbar
  1519.  
  1520.         if (scrollHeight >= maxHeight)
  1521.             return;
  1522.  
  1523.         decimal scrollSpeed = (maxHeight - scrollHeight) / (barCount - barsViewable);
  1524.  
  1525.         scrollBarArea = new Rectangle(this.Width - 20, 19, 12, maxHeight);
  1526.         scroll = new Rectangle(this.Width - 20, 19 + Convert.ToInt32((scrollPosition * scrollSpeed)), 12, Convert.ToInt32(scrollHeight));
  1527.  
  1528.         topPart = new Rectangle(this.Width - 20, 10, 12, 8);
  1529.         BottomPart = new Rectangle(this.Width - 20, this.Height - 10, 12, 8);
  1530.  
  1531.         Brush colorTopPart = null;
  1532.         Brush colorBottomPart = null;
  1533.         Brush colorScroll = null;
  1534.  
  1535.         if (mouseOverTopPart == true)
  1536.         {
  1537.             colorTopPart = Brushes.Black;
  1538.         }
  1539.         else
  1540.         {
  1541.             colorTopPart = Brushes.Gray;
  1542.         }
  1543.  
  1544.         if (mouseOverBottomPart == true)
  1545.         {
  1546.             colorBottomPart = Brushes.Black;
  1547.         }
  1548.         else
  1549.         {
  1550.             colorBottomPart = Brushes.Gray;
  1551.         }
  1552.  
  1553.         if (mouseOverScrollBar == true)
  1554.         {
  1555.             colorScroll = new LinearGradientBrush(scroll, Color.Bisque, Color.Gray, LinearGradientMode.Horizontal);
  1556.         }
  1557.         else
  1558.         {
  1559.             colorScroll = new LinearGradientBrush(scroll, Color.White, Color.Gray, LinearGradientMode.Horizontal);
  1560.         }
  1561.  
  1562.         // Draws the top and bottom part of the scrollbar
  1563.  
  1564.         grfx.DrawRectangle(Pens.Black, topPart);
  1565.         grfx.FillRectangle(Brushes.LightGray, topPart);
  1566.  
  1567.         grfx.DrawRectangle(Pens.Black, BottomPart);
  1568.         grfx.FillRectangle(Brushes.LightGray, BottomPart);
  1569.  
  1570.         // Draws arrows
  1571.  
  1572.         PointF[] points = new PointF[3];
  1573.         points[0] = new PointF(topPart.Left, topPart.Bottom - 1);
  1574.         points[1] = new PointF(topPart.Right, topPart.Bottom - 1);
  1575.         points[2] = new PointF((topPart.Left + topPart.Right) / 2, topPart.Top + 1);
  1576.  
  1577.         grfx.FillPolygon(colorTopPart, points);
  1578.  
  1579.         points[0] = new PointF(BottomPart.Left, BottomPart.Top + 1);
  1580.         points[1] = new PointF(BottomPart.Right, BottomPart.Top + 1);
  1581.         points[2] = new PointF((BottomPart.Left + BottomPart.Right) / 2, BottomPart.Bottom - 1);
  1582.  
  1583.         grfx.FillPolygon(colorBottomPart, points);
  1584.  
  1585.         // Draws the scroll area
  1586.  
  1587.         grfx.DrawRectangle(Pens.Black, scrollBarArea);
  1588.         grfx.FillRectangle(Brushes.DarkGray, scrollBarArea);
  1589.  
  1590.         // Draws the actual scrollbar
  1591.  
  1592.         grfx.DrawRectangle(Pens.Black, scroll);
  1593.         grfx.FillRectangle(colorScroll, scroll);
  1594.     }
  1595.  
  1596.     /// <summary>
  1597.     /// The Y-position of the center of the scroll
  1598.     /// </summary>
  1599.     /// <value></value>
  1600.     /// <returns></returns>
  1601.     /// <remarks></remarks>
  1602.  
  1603.     private int ScrollPositionY
  1604.     {
  1605.         get
  1606.         {
  1607.             if (scroll == null)
  1608.                 return -1;
  1609.             return ((scroll.Height / 2) + scroll.Location.Y) + 19;
  1610.         }
  1611.         set
  1612.         {
  1613.             int barCount = GetIndexChartBar("QQQWWW");
  1614.             int maxHeight = this.Height - 30;
  1615.             decimal scrollHeight = (maxHeight / barCount) * barsViewable;
  1616.             decimal scrollSpeed = (maxHeight - scrollHeight) / (barCount - barsViewable);
  1617.             int index = 0;
  1618.             dynamic distanceFromLastPosition = 9999;
  1619.  
  1620.             // Tests to see what scrollposition is the closest to the set position
  1621.  
  1622.             while (index < barCount)
  1623.             {
  1624.                 int newPositionTemp = Convert.ToInt32((index * scrollSpeed) + (scrollHeight / 2) + (30 / 2));
  1625.                 dynamic distanceFromCurrentPosition = newPositionTemp - value;
  1626.  
  1627.                 if (distanceFromLastPosition < 0)
  1628.                 {
  1629.                     if (distanceFromCurrentPosition < distanceFromLastPosition)
  1630.                     {
  1631.                         scrollPosition = index - 1;
  1632.                         PaintChart();
  1633.                         return;
  1634.                     }
  1635.                 }
  1636.                 else
  1637.                 {
  1638.                     if (distanceFromCurrentPosition > distanceFromLastPosition)
  1639.                     {
  1640.                         scrollPosition = index - 1;
  1641.  
  1642.                         // A precaution to make sure the scroll bar doesn't go too far down
  1643.  
  1644.                         if (scrollPosition + barsViewable > GetIndexChartBar("QQQWWW"))
  1645.                         {
  1646.                             scrollPosition = GetIndexChartBar("QQQWWW") - barsViewable;
  1647.                         }
  1648.  
  1649.                         PaintChart();
  1650.                         return;
  1651.                     }
  1652.                 }
  1653.  
  1654.                 distanceFromLastPosition = distanceFromCurrentPosition;
  1655.  
  1656.                 index += 1;
  1657.             }
  1658.         }
  1659.     }
  1660.  
  1661.     /// <summary>
  1662.     /// Scrolls one row up
  1663.     /// </summary>
  1664.     /// <remarks></remarks>
  1665.  
  1666.     public void ScrollOneup()
  1667.     {
  1668.         if (scrollPosition == 0)
  1669.             return;
  1670.  
  1671.         scrollPosition -= 1;
  1672.  
  1673.         PaintChart();
  1674.     }
  1675.  
  1676.     /// <summary>
  1677.     /// Scrolls one row down
  1678.     /// </summary>
  1679.     /// <remarks></remarks>
  1680.  
  1681.     public void ScrollOneDown()
  1682.     {
  1683.         if (scrollPosition + barsViewable >= GetIndexChartBar("QQQWWW"))
  1684.             return;
  1685.  
  1686.         scrollPosition += 1;
  1687.  
  1688.         PaintChart();
  1689.     }
  1690.  
  1691.     /// <summary>
  1692.     /// If the user clicks on the scrollbar, scrolling functions will be called
  1693.     /// </summary>
  1694.     /// <param name="sender"></param>
  1695.     /// <param name="e"></param>
  1696.     /// <remarks></remarks>
  1697.  
  1698.     private void GanttChart_Click(System.Object sender, System.Windows.Forms.MouseEventArgs e)
  1699.     {
  1700.         if (e.Button == System.Windows.Forms.MouseButtons.Left)
  1701.         {
  1702.             if (mouseOverBottomPart == true)
  1703.             {
  1704.                 ScrollOneDown();
  1705.             }
  1706.             else if (mouseOverTopPart == true)
  1707.             {
  1708.                 ScrollOneup();
  1709.             }
  1710.         }
  1711.     }
  1712.  
  1713.     /// <summary>
  1714.     /// When mousewheel is used, the scrollbar will scroll
  1715.     /// </summary>
  1716.     /// <param name="sender"></param>
  1717.     /// <param name="e"></param>
  1718.     /// <remarks></remarks>
  1719.  
  1720.     private void GanttChart_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
  1721.     {
  1722.         if (e.Delta > 0)
  1723.         {
  1724.             ScrollOneup();
  1725.         }
  1726.         else
  1727.         {
  1728.             ScrollOneDown();
  1729.         }
  1730.     }
  1731.  
  1732.     #endregion
  1733.  
  1734.     #region "Save"
  1735.  
  1736.     /// <summary>
  1737.     /// Saves the GanttChart to specified image file
  1738.     /// </summary>
  1739.     /// <param name="filePath"></param>
  1740.     /// <remarks></remarks>
  1741.  
  1742.     public void SaveImage(string filePath)
  1743.     {
  1744.         objGraphics.SmoothingMode = SmoothingMode.HighSpeed;
  1745.         objGraphics.Clear(this.BackColor);
  1746.  
  1747.         if (headerFromDate == null | headerToDate == null)
  1748.             return;
  1749.  
  1750.         DrawHeader(objGraphics, null);
  1751.         DrawNetHorizontal(objGraphics);
  1752.         DrawNetVertical(objGraphics);
  1753.         DrawBars(objGraphics, true);
  1754.  
  1755.         objBmp.Save(filePath);
  1756.     }
  1757.  
  1758.     #endregion
  1759.  
  1760.     private enum MouseOverPart
  1761.     {
  1762.  
  1763.         Empty,
  1764.         Bar,
  1765.         BarLeftSide,
  1766.         BarRightSide
  1767.  
  1768.     }
  1769.  
  1770. }