28 changed files with 2859 additions and 2 deletions
After Width: | Height: | Size: 822 B |
@ -0,0 +1,105 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{DEA91CB9-1011-4EE7-B8E1-72428F731789}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<RootNamespace>GanttChart</RootNamespace> |
|||
<AssemblyName>GanttChart</AssemblyName> |
|||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
<Deterministic>true</Deterministic> |
|||
<TargetFrameworkProfile /> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<PlatformTarget>AnyCPU</PlatformTarget> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<Prefer32Bit>false</Prefer32Bit> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<PlatformTarget>AnyCPU</PlatformTarget> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<Prefer32Bit>false</Prefer32Bit> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<StartupObject /> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core" /> |
|||
<Reference Include="System.Xml.Linq" /> |
|||
<Reference Include="System.Data.DataSetExtensions" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Deployment" /> |
|||
<Reference Include="System.Drawing" /> |
|||
<Reference Include="System.Windows.Forms" /> |
|||
<Reference Include="System.Xml" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="GanttChartBrushes.cs" /> |
|||
<Compile Include="GanttChartItemClickEventArgs.cs" /> |
|||
<Compile Include="GanttChartItemDoubleClickEventArgs.cs" /> |
|||
<Compile Include="GanttChartPropertyChangeEventArgs.cs" /> |
|||
<Compile Include="GanttChartRangeSelectedEventArgs.cs" /> |
|||
<Compile Include="GanttChartRowSelectedEventArgs.cs" /> |
|||
<Compile Include="GanttChartView.cs"> |
|||
<SubType>Component</SubType> |
|||
</Compile> |
|||
<Compile Include="GanttChartView.Events.cs"> |
|||
<SubType>Component</SubType> |
|||
</Compile> |
|||
<Compile Include="GanttChartView.Logic.cs"> |
|||
<SubType>Component</SubType> |
|||
</Compile> |
|||
<Compile Include="GanttChartView.Properties.cs"> |
|||
<SubType>Component</SubType> |
|||
</Compile> |
|||
<Compile Include="GanttChartView.Render.cs"> |
|||
<SubType>Component</SubType> |
|||
</Compile> |
|||
<Compile Include="GanttChartViewColumn.cs" /> |
|||
<Compile Include="GanttChartViewColumnGroup.cs" /> |
|||
<Compile Include="GanttChartViewItem.cs" /> |
|||
<Compile Include="GanttChartCollection.cs" /> |
|||
<Compile Include="GanttChartViewItemBlockType.cs" /> |
|||
<Compile Include="GanttChartViewRow.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
<Compile Include="TimeRange.cs" /> |
|||
<EmbeddedResource Include="Properties\Resources.resx"> |
|||
<Generator>ResXFileCodeGenerator</Generator> |
|||
<LastGenOutput>Resources.Designer.cs</LastGenOutput> |
|||
<SubType>Designer</SubType> |
|||
</EmbeddedResource> |
|||
<Compile Include="Properties\Resources.Designer.cs"> |
|||
<AutoGen>True</AutoGen> |
|||
<DependentUpon>Resources.resx</DependentUpon> |
|||
<DesignTime>True</DesignTime> |
|||
</Compile> |
|||
<None Include="Properties\Settings.settings"> |
|||
<Generator>SettingsSingleFileGenerator</Generator> |
|||
<LastGenOutput>Settings.Designer.cs</LastGenOutput> |
|||
</None> |
|||
<Compile Include="Properties\Settings.Designer.cs"> |
|||
<AutoGen>True</AutoGen> |
|||
<DependentUpon>Settings.settings</DependentUpon> |
|||
<DesignTimeSharedInput>True</DesignTimeSharedInput> |
|||
</Compile> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<EmbeddedResource Include="GanttChart.bmp" /> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
|||
</Project> |
@ -0,0 +1,197 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Drawing; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图笔刷
|
|||
/// </summary>
|
|||
class GanttChartBrushes: IDisposable |
|||
{ |
|||
GanttChartView View { get; set; } |
|||
public GanttChartBrushes(GanttChartView view) |
|||
{ |
|||
View = view; |
|||
this.GridBrush = new SolidBrush(view.GridColor); |
|||
|
|||
this.ColumnDateTextBrush = new SolidBrush(view.ColumnDateTextColor); |
|||
this.ColumnHourTextBrush = new SolidBrush(view.ColumnHourTextColor); |
|||
this.HeaderBackBrush = new SolidBrush(view.HeaderBackColor); |
|||
|
|||
this.BackBrush = new SolidBrush(view.BackColor); |
|||
this.ContentBackBrush = new SolidBrush(view.ContentBackColor); |
|||
|
|||
this.CurrentTimeLineBrush = new SolidBrush(view.CurrentTimeLineColor); |
|||
|
|||
this.ItemTextBrush = new SolidBrush(view.ItemTextColor); |
|||
this.ItemBackBrush = new SolidBrush(view.ItemBackColor); |
|||
this.ItemBorderBrush = new SolidBrush(view.ItemBorderColor); |
|||
this.ItemStartFlagBrush = new SolidBrush(view.ItemStartFlagColor); |
|||
this.ItemSubRangeBackBrush = new SolidBrush(view.ItemSubRangeBackColor); |
|||
this.ItemSelectionTextBrush = new SolidBrush(view.ItemSelectionTextColor); |
|||
this.ItemSelectionBackBrush = new SolidBrush(view.ItemSelectionBackColor); |
|||
this.ItemSelectionBorderBrush = new SolidBrush(view.ItemSelectionBorderColor); |
|||
this.ItemSelectionSubRangeBackBrush = new SolidBrush(view.ItemSelectionSubRangeBackColor); |
|||
this.ItemWarnningTextBrush = new SolidBrush(view.ItemWarnningTextColor); |
|||
|
|||
this.RowHeaderTextBrush = new SolidBrush(view.RowHeaderTextColor); |
|||
this.RowSelectionHeaderTextBrush = new SolidBrush(view.RowSelectionHeaderTextColor); |
|||
this.RowSelectionBorderBrush = new SolidBrush(view.RowSelectionBorderColor); |
|||
this.RowSelectionHeaderBackBrush = new SolidBrush(view.RowSelectionHeaderBackColor); |
|||
this.RowSelectionContentBackBrush = new SolidBrush(view.RowSelectionContentBackColor); |
|||
|
|||
this.TooltipTextBrush = new SolidBrush(view.TooltipTextColor); |
|||
this.TooltipBorderBrush = new SolidBrush(view.TooltipBorderColor); |
|||
this.TooltipBackBrush = new SolidBrush(view.TooltipBackColor); |
|||
|
|||
this.TimeRangeSelecetionBackBrush = new SolidBrush(view.TimeRangeSelecetionBackColor); |
|||
this.SelectionRectangleBackBrush = new SolidBrush(view.SelectionRectangleBackColor); |
|||
|
|||
this.GridPen = new Pen(this.GridBrush, 1); |
|||
this.CurrentTimeLinePen = new Pen(this.CurrentTimeLineBrush, 1); |
|||
this.ItemBorderPen = new Pen(this.ItemBorderBrush, 1); |
|||
this.ItemBackPen = new Pen(this.ItemBackBrush, 1); |
|||
this.ItemSelectionBorderPen = new Pen(this.ItemSelectionBorderBrush, 1); |
|||
this.RowSelectionBorderPen = new Pen(this.RowSelectionBorderBrush, 1); |
|||
this.TooltipBorderPen = new Pen(this.TooltipBorderBrush, 1); |
|||
this.ItemStartFlagPen = new Pen(this.ItemStartFlagBrush, 2); |
|||
this.ItemSubRangeBackPen = new Pen(this.ItemSubRangeBackBrush, 1); |
|||
this.ItemSelectionSubRangeBackPen = new Pen(this.ItemSelectionSubRangeBackBrush, 1); |
|||
} |
|||
public SolidBrush GridBrush { get; set; } |
|||
|
|||
public SolidBrush ColumnDateTextBrush { get; set; } |
|||
public SolidBrush ColumnHourTextBrush { get; set; } |
|||
public SolidBrush HeaderBackBrush { get; set; } |
|||
|
|||
public SolidBrush BackBrush { get; set; } |
|||
public SolidBrush ContentBackBrush { get; set; } |
|||
|
|||
public SolidBrush CurrentTimeLineBrush { get; set; } |
|||
|
|||
public SolidBrush ItemTextBrush { get; set; } |
|||
public SolidBrush ItemBackBrush { get; set; } |
|||
public SolidBrush ItemBorderBrush { get; set; } |
|||
public SolidBrush ItemStartFlagBrush { get; set; } |
|||
public SolidBrush ItemSubRangeBackBrush { get; set; } |
|||
public SolidBrush ItemSelectionTextBrush { get; set; } |
|||
public SolidBrush ItemSelectionBackBrush { get; set; } |
|||
public SolidBrush ItemSelectionBorderBrush { get; set; } |
|||
public SolidBrush ItemSelectionSubRangeBackBrush { get; set; } |
|||
public SolidBrush ItemWarnningTextBrush { get; set; } |
|||
|
|||
|
|||
public SolidBrush RowHeaderTextBrush { get; set; } |
|||
public SolidBrush RowSelectionHeaderTextBrush { get; set; } |
|||
public SolidBrush RowSelectionBorderBrush { get; set; } |
|||
public SolidBrush RowSelectionHeaderBackBrush { get; set; } |
|||
public SolidBrush RowSelectionContentBackBrush { get; set; } |
|||
|
|||
public SolidBrush TooltipTextBrush { get; set; } |
|||
public SolidBrush TooltipBorderBrush { get; set; } |
|||
public SolidBrush TooltipBackBrush { get; set; } |
|||
|
|||
public SolidBrush TimeRangeSelecetionBackBrush { get; set; } |
|||
public SolidBrush SelectionRectangleBackBrush { get; set; } |
|||
|
|||
public Pen GridPen { get; } |
|||
public Pen CurrentTimeLinePen { get; } |
|||
public Pen ItemBorderPen { get; } |
|||
public Pen ItemBackPen { get; } |
|||
public Pen ItemSelectionBorderPen { get; } |
|||
public Pen RowSelectionBorderPen { get; } |
|||
public Pen TooltipBorderPen { get; } |
|||
public Pen ItemStartFlagPen { get; } |
|||
public Pen ItemSubRangeBackPen { get; } |
|||
public Pen ItemSelectionSubRangeBackPen { get; } |
|||
|
|||
public void Refresh() |
|||
{ |
|||
this.GridBrush.Color = View.GridColor; |
|||
|
|||
this.ColumnDateTextBrush.Color = View.ColumnDateTextColor; |
|||
this.ColumnHourTextBrush.Color = View.ColumnHourTextColor; |
|||
this.HeaderBackBrush.Color = View.HeaderBackColor; |
|||
|
|||
this.ContentBackBrush.Color = View.ContentBackColor; |
|||
|
|||
this.CurrentTimeLineBrush.Color = View.CurrentTimeLineColor; |
|||
|
|||
this.ItemTextBrush.Color = View.ItemTextColor; |
|||
this.ItemBackBrush.Color = View.ItemBackColor; |
|||
this.ItemBorderBrush.Color = View.ItemBorderColor; |
|||
this.ItemStartFlagBrush.Color = View.ItemStartFlagColor; |
|||
this.ItemSubRangeBackBrush.Color = View.ItemSubRangeBackColor; |
|||
this.ItemSelectionTextBrush.Color = View.ItemSelectionTextColor; |
|||
this.ItemSelectionBackBrush.Color = View.ItemSelectionBackColor; |
|||
this.ItemSelectionBorderBrush.Color = View.ItemSelectionBorderColor; |
|||
this.ItemSelectionSubRangeBackBrush.Color = View.ItemSelectionSubRangeBackColor; |
|||
this.ItemWarnningTextBrush.Color = View.ItemWarnningTextColor; |
|||
|
|||
this.RowHeaderTextBrush.Color = View.RowHeaderTextColor; |
|||
this.RowSelectionHeaderTextBrush.Color = View.RowSelectionHeaderTextColor; |
|||
this.RowSelectionBorderBrush.Color = View.RowSelectionBorderColor; |
|||
this.RowSelectionHeaderBackBrush.Color = View.RowSelectionHeaderBackColor; |
|||
this.RowSelectionContentBackBrush.Color = View.RowSelectionContentBackColor; |
|||
|
|||
this.TooltipTextBrush.Color = View.TooltipTextColor; |
|||
this.TooltipBorderBrush.Color = View.TooltipBorderColor; |
|||
this.TooltipBackBrush.Color = View.TooltipBackColor; |
|||
|
|||
this.TimeRangeSelecetionBackBrush.Color = View.TimeRangeSelecetionBackColor; |
|||
this.SelectionRectangleBackBrush.Color = View.SelectionRectangleBackColor; |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
this.GridPen.Dispose(); |
|||
this.CurrentTimeLinePen.Dispose(); |
|||
this.ItemBorderPen.Dispose(); |
|||
this.ItemBackPen.Dispose(); |
|||
this.ItemSelectionBorderPen.Dispose(); |
|||
this.RowSelectionBorderPen.Dispose(); |
|||
this.TooltipBorderPen.Dispose(); |
|||
this.ItemStartFlagPen.Dispose(); |
|||
this.ItemSubRangeBackPen.Dispose(); |
|||
this.ItemSelectionSubRangeBackPen.Dispose(); |
|||
|
|||
this.BackBrush.Dispose(); |
|||
this.GridBrush.Dispose(); |
|||
|
|||
this.ColumnDateTextBrush.Dispose(); |
|||
this.ColumnHourTextBrush.Dispose(); |
|||
this.HeaderBackBrush.Dispose(); |
|||
|
|||
this.ContentBackBrush.Dispose(); |
|||
|
|||
this.CurrentTimeLineBrush.Dispose(); |
|||
|
|||
this.ItemTextBrush.Dispose(); |
|||
this.ItemBackBrush.Dispose(); |
|||
this.ItemBorderBrush.Dispose(); |
|||
this.ItemStartFlagBrush.Dispose(); |
|||
this.ItemSubRangeBackBrush.Dispose(); |
|||
this.ItemSelectionTextBrush.Dispose(); |
|||
this.ItemSelectionBackBrush.Dispose(); |
|||
this.ItemSelectionBorderBrush.Dispose(); |
|||
this.ItemSelectionSubRangeBackBrush.Dispose(); |
|||
this.ItemWarnningTextBrush.Dispose(); |
|||
|
|||
this.RowHeaderTextBrush.Dispose(); |
|||
this.RowSelectionHeaderTextBrush.Dispose(); |
|||
this.RowSelectionBorderBrush.Dispose(); |
|||
this.RowSelectionHeaderBackBrush.Dispose(); |
|||
this.RowSelectionContentBackBrush.Dispose(); |
|||
|
|||
this.TooltipTextBrush.Dispose(); |
|||
this.TooltipBorderBrush.Dispose(); |
|||
this.TooltipBackBrush.Dispose(); |
|||
|
|||
this.TimeRangeSelecetionBackBrush.Dispose(); |
|||
this.SelectionRectangleBackBrush.Dispose(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,71 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图像集合
|
|||
/// </summary>
|
|||
/// <typeparam name="T"></typeparam>
|
|||
public class GanttChartCollection<T> : ICollection<T> |
|||
{ |
|||
private List<T> Items; |
|||
internal bool IsChanged { get; set; } |
|||
internal DateTime StartDate { get; set; } |
|||
public GanttChartCollection() |
|||
{ |
|||
Items = new List<T>(); |
|||
} |
|||
public GanttChartCollection(ICollection<T> items):this() |
|||
{ |
|||
Items.AddRange(items); |
|||
IsChanged = true; |
|||
} |
|||
public int Count => Items.Count; |
|||
|
|||
bool ICollection<T>.IsReadOnly => false; |
|||
|
|||
public void Add(T item) |
|||
{ |
|||
Items.Add(item); |
|||
IsChanged = true; |
|||
} |
|||
|
|||
public void Clear() |
|||
{ |
|||
Items.Clear(); |
|||
IsChanged = false; |
|||
} |
|||
|
|||
public bool Contains(T item) => Items.Contains(item); |
|||
|
|||
public void CopyTo(T[] array, int arrayIndex) => Items.CopyTo(array, arrayIndex); |
|||
|
|||
public IEnumerator<T> GetEnumerator() => Items.GetEnumerator(); |
|||
|
|||
public bool Remove(T item) |
|||
{ |
|||
if (Items.Remove(item)) |
|||
{ |
|||
IsChanged = true; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return Items.GetEnumerator(); |
|||
} |
|||
public T this[int index] |
|||
{ |
|||
get |
|||
{ |
|||
return Items[index]; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图项单击事件参数
|
|||
/// </summary>
|
|||
public class GanttChartItemClickEventArgs : EventArgs |
|||
{ |
|||
/// <summary>
|
|||
/// 项
|
|||
/// </summary>
|
|||
public GanttChartViewItem Item { get; private set; } |
|||
/// <summary>
|
|||
/// 初始化
|
|||
/// </summary>
|
|||
/// <param name="item"></param>
|
|||
public GanttChartItemClickEventArgs(GanttChartViewItem item) |
|||
{ |
|||
Item = item; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图项双击事件参数
|
|||
/// </summary>
|
|||
public class GanttChartItemDoubleClickEventArgs : EventArgs |
|||
{ |
|||
/// <summary>
|
|||
/// 项
|
|||
/// </summary>
|
|||
public GanttChartViewItem Item { get; private set; } |
|||
/// <summary>
|
|||
/// 初始化
|
|||
/// </summary>
|
|||
/// <param name="item"></param>
|
|||
public GanttChartItemDoubleClickEventArgs(GanttChartViewItem item) |
|||
{ |
|||
Item = item; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,32 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图属性改变事件参数
|
|||
/// </summary>
|
|||
public class GanttChartPropertyChangeEventArgs : EventArgs |
|||
{ |
|||
/// <summary>
|
|||
/// 初始化
|
|||
/// </summary>
|
|||
/// <param name="name"></param>
|
|||
/// <param name="value"></param>
|
|||
public GanttChartPropertyChangeEventArgs(string name, object value) |
|||
{ |
|||
PropertyName = name; |
|||
PropertyValue = value; |
|||
} |
|||
/// <summary>
|
|||
/// 属性名
|
|||
/// </summary>
|
|||
public string PropertyName { get; set; } |
|||
/// <summary>
|
|||
/// 属性值
|
|||
/// </summary>
|
|||
public object PropertyValue { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,35 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图范围选择事件参数
|
|||
/// </summary>
|
|||
public class GanttChartRangeSelectedEventArgs : EventArgs |
|||
{ |
|||
/// <summary>
|
|||
/// 事件范围
|
|||
/// </summary>
|
|||
public TimeRange Range { get; private set; } |
|||
/// <summary>
|
|||
/// 初始化
|
|||
/// </summary>
|
|||
/// <param name="range"></param>
|
|||
public GanttChartRangeSelectedEventArgs(TimeRange range) |
|||
{ |
|||
Range = range; |
|||
} |
|||
/// <summary>
|
|||
/// 初始化
|
|||
/// </summary>
|
|||
/// <param name="startTime"></param>
|
|||
/// <param name="endTime"></param>
|
|||
public GanttChartRangeSelectedEventArgs(DateTime startTime, DateTime endTime) |
|||
{ |
|||
Range = new TimeRange { StartTime = startTime, EndTime = endTime }; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图行选中事件参数
|
|||
/// </summary>
|
|||
public class GanttChartRowSelectedEventArgs : EventArgs |
|||
{ |
|||
/// <summary>
|
|||
/// 行
|
|||
/// </summary>
|
|||
public GanttChartViewRow Row { get; private set; } |
|||
/// <summary>
|
|||
/// 初始化
|
|||
/// </summary>
|
|||
/// <param name="row"></param>
|
|||
public GanttChartRowSelectedEventArgs(GanttChartViewRow row) |
|||
{ |
|||
Row = row; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,410 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Drawing; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Windows.Forms; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图控件
|
|||
/// 该部分类主要处理事件
|
|||
/// </summary>
|
|||
public partial class GanttChartView |
|||
{ |
|||
private bool _IsShiftPress = false; |
|||
private bool _IsCtrlPress = false; |
|||
private bool _IsAltPress = false; |
|||
private bool _IsMouseDown = false; |
|||
private bool _IsAjustSize = false; |
|||
private bool _IsDragItem = false; |
|||
private bool _IsShowTooltip = false; |
|||
private Point _DragStartLocation = Point.Empty; |
|||
private Point _DragEndLocation = Point.Empty; |
|||
private Point _ShowTooltipPoint = Point.Empty; |
|||
private Rectangle _SelectionRange = Rectangle.Empty; |
|||
private GanttChartViewItem _DragItem = null; |
|||
private GanttChartViewItem _ShowTooltipItem = null; |
|||
public event EventHandler<GanttChartPropertyChangeEventArgs> PropertyChanged; |
|||
public event EventHandler<GanttChartItemClickEventArgs> ItemClick; |
|||
public event EventHandler<GanttChartItemDoubleClickEventArgs> ItemDoubleClick; |
|||
public event EventHandler<GanttChartRowSelectedEventArgs> RowSelected; |
|||
public event EventHandler<GanttChartRangeSelectedEventArgs> RangeSelected; |
|||
|
|||
/// <summary>
|
|||
/// 初始化事件
|
|||
/// </summary>
|
|||
protected void InitEvent() |
|||
{ |
|||
_VScrollBar.Scroll += new ScrollEventHandler(VScrollBar_Scroll); |
|||
_HScrollBar.Scroll += new ScrollEventHandler(HScrollBar_Scroll); |
|||
_ContentControl.Paint += OnContentControlPaint; |
|||
_ContentControl.MouseDown += OnMouseDown; |
|||
_ContentControl.MouseUp += OnMouseUp; |
|||
_ContentControl.MouseMove += OnMouseMove; |
|||
_ContentControl.MouseClick += OnMouseClick; |
|||
_ContentControl.MouseDoubleClick += OnMouseDoubleClick; |
|||
} |
|||
/// <summary>
|
|||
/// 销毁事件
|
|||
/// </summary>
|
|||
protected void DisposeEvent() |
|||
{ |
|||
|
|||
} |
|||
/// <summary>
|
|||
/// 键盘按下事件
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
protected override void OnKeyDown(KeyEventArgs e) |
|||
{ |
|||
_IsShiftPress = e.Shift; |
|||
_IsCtrlPress = e.Control; |
|||
_IsAltPress = e.Alt; |
|||
base.OnKeyDown(e); |
|||
} |
|||
/// <summary>
|
|||
/// 键盘弹起事件
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
protected override void OnKeyUp(KeyEventArgs e) |
|||
{ |
|||
_IsShiftPress = e.Shift; |
|||
_IsCtrlPress = e.Control; |
|||
_IsAltPress = e.Alt; |
|||
base.OnKeyUp(e); |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标单击事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
protected void OnMouseClick(object sender, MouseEventArgs e) |
|||
{ |
|||
if (_DragStartLocation != Point.Empty && e.X != _DragStartLocation.X && _DragStartLocation.Y != e.Y) |
|||
{ |
|||
return; |
|||
} |
|||
if (IsHoverRowHeader(e.Location) || IsHoverRow(e.Location)) |
|||
{ |
|||
_SelectionRow = GetRow(e.Location); |
|||
Invalidate(); |
|||
RowSelected?.Invoke(this, new GanttChartRowSelectedEventArgs(_SelectionRow)); |
|||
} |
|||
if (IsHoverItem(e.Location)) |
|||
{ |
|||
_SelectionItem = GetItem(e.Location); |
|||
Invalidate(); |
|||
ItemClick?.Invoke(this, new GanttChartItemClickEventArgs(_SelectionItem)); |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标双击事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
protected void OnMouseDoubleClick(object sender, MouseEventArgs e) |
|||
{ |
|||
if (IsHoverItem(e.Location)) |
|||
{ |
|||
_SelectionItem = GetItem(e.Location); |
|||
Invalidate(); |
|||
if(ItemDoubleClick != null) |
|||
{ |
|||
if (_IsShowTooltip) |
|||
{ |
|||
_IsShowTooltip = false; |
|||
_ShowTooltipItem = null; |
|||
_ShowTooltipPoint = Point.Empty; |
|||
} |
|||
ItemDoubleClick(this, new GanttChartItemDoubleClickEventArgs(_SelectionItem)); |
|||
} |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标滚动事件
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
protected override void OnMouseWheel(MouseEventArgs e) |
|||
{ |
|||
if (_IsShowTooltip) |
|||
{ |
|||
_IsShowTooltip = false; |
|||
_ShowTooltipItem = null; |
|||
_ShowTooltipPoint = Point.Empty; |
|||
} |
|||
//int i = e.Delta > 0 ? -1 : 1;
|
|||
var scrollbar = _IsShiftPress ? _HScrollBar : (ScrollBar)_VScrollBar; |
|||
var h = scrollbar.Value - (int)(e.Delta * MouseWheelSensitivity); |
|||
if (h > scrollbar.Maximum) |
|||
{ |
|||
h = scrollbar.Maximum; |
|||
} |
|||
if (h < scrollbar.Minimum) |
|||
{ |
|||
h = scrollbar.Minimum; |
|||
} |
|||
scrollbar.Value = h; |
|||
Invalidate(); |
|||
base.OnMouseWheel(e); |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标按下事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
protected void OnMouseDown(object sender, MouseEventArgs e) |
|||
{ |
|||
if (_SelectionRow != null || _SelectionItem != null || _DragItem != null) |
|||
{ |
|||
_SelectionRow = null; |
|||
_SelectionItem = null; |
|||
_DragItem = null; |
|||
Invalidate(); |
|||
} |
|||
_IsMouseDown = e.Button == MouseButtons.Left && true; |
|||
if (_IsMouseDown) |
|||
{ |
|||
_SelectionRange = Rectangle.Empty; |
|||
_SelectionTimeRange = null; |
|||
_DragStartLocation = e.Location; |
|||
if (IsHoverDateSplitLine(e.Location) && !IsHoverItem(e.Location)) |
|||
{ |
|||
_IsAjustSize = true; |
|||
} |
|||
else if (IsHoverItem(e.Location)) |
|||
{ |
|||
_IsDragItem = true; |
|||
_DragItem = GetItem(e.Location); |
|||
} |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 控件创建事件
|
|||
/// </summary>
|
|||
protected override void OnCreateControl() |
|||
{ |
|||
this.Brushes = new GanttChartBrushes(this); |
|||
_HScrollBar.Width = this.Width - VScrollWidth; |
|||
_VScrollBar.Height = this.Height - HScrollHeight; |
|||
AdjustScrollbar(); |
|||
base.OnCreateControl(); |
|||
} |
|||
/// <summary>
|
|||
/// 控件大小变化事件
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
protected override void OnSizeChanged(EventArgs e) |
|||
{ |
|||
_HScrollBar.Width = this.Width - VScrollWidth; |
|||
_VScrollBar.Height = this.Height - HScrollHeight; |
|||
AdjustScrollbar(); |
|||
Invalidate(); |
|||
base.OnSizeChanged(e); |
|||
} |
|||
/// <summary>
|
|||
/// 控件绘制事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
private void OnContentControlPaint(object sender, PaintEventArgs e) |
|||
{ |
|||
int bottom = ColumnHeight + ItemHeight + RowSpacing * 2; |
|||
if (Rows != null && Rows.Any()) |
|||
{ |
|||
var last = Rows.Last(); |
|||
bottom = last.Bottom; |
|||
} |
|||
DrawBack(e.Graphics, bottom); |
|||
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; |
|||
DrawHeader(e.Graphics, bottom); |
|||
DrawColumnHeader(e.Graphics); |
|||
DrawTimeLine(e.Graphics, bottom); |
|||
|
|||
DrawSelectingRectangle(e.Graphics); |
|||
|
|||
DrawSelectionRange(e.Graphics); |
|||
|
|||
DrawRows(e.Graphics, bottom); |
|||
|
|||
DrawItemTooltip(e.Graphics); |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标弹起事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
protected void OnMouseUp(object sender, MouseEventArgs e) |
|||
{ |
|||
if (_IsMouseDown) |
|||
{ |
|||
if (_IsAjustSize) |
|||
{ |
|||
_IsAjustSize = false; |
|||
var w = e.X - _DragStartLocation.X + DateWidth; |
|||
if (w < MinDateWidth) |
|||
{ |
|||
DateWidth = MinDateWidth; |
|||
} |
|||
else |
|||
{ |
|||
DateWidth = (w / 48 + (w % 48 == 0 ? 0 : 1)) * 48; |
|||
} |
|||
if(Rows != null) |
|||
{ |
|||
Rows.IsChanged = true; |
|||
} |
|||
AdjustScrollbar(); |
|||
Invalidate(); |
|||
} |
|||
else if (_IsDragItem) |
|||
{ |
|||
_IsDragItem = false; |
|||
//TODO:触发Drag事件
|
|||
Invalidate(); |
|||
} |
|||
else if(!_DragStartLocation.IsEmpty && e.X != _DragStartLocation.X && e.Y != _DragStartLocation.Y && _DragStartLocation.X > RowHeaderWidth && _DragStartLocation.Y > ColumnHeight) |
|||
{ |
|||
_DragEndLocation = e.Location; |
|||
var row = GetRow(_DragStartLocation); |
|||
if (row != null) |
|||
{ |
|||
var width = Math.Abs(_DragEndLocation.X - _DragStartLocation.X); |
|||
if (_DragEndLocation.X < RowHeaderWidth) |
|||
{ |
|||
width -= RowHeaderWidth - _DragEndLocation.X; |
|||
} |
|||
else if (_DragEndLocation.X > ((int)(EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value) |
|||
{ |
|||
width = ((int)(EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value - _DragStartLocation.X; |
|||
} |
|||
var start = new Point(Math.Min(_DragStartLocation.X, Math.Max(_DragEndLocation.X, RowHeaderWidth)), row.Top + 1); |
|||
_SelectionRange = new Rectangle(start, new Size(width, row.Bottom - row.Top - 2)); |
|||
|
|||
Invalidate(); |
|||
var mw = DateWidth / 24f / 60f; |
|||
var ts = StartDate.AddMinutes((int)((_DragStartLocation.X - RowHeaderWidth + _HScrollBar.Value) / mw)); |
|||
var te = StartDate.AddMinutes((int)((_DragEndLocation.X - RowHeaderWidth + _HScrollBar.Value) / mw)); |
|||
if (te < ts) |
|||
{ |
|||
var tt = te; |
|||
te = ts; |
|||
ts = tt; |
|||
} |
|||
_SelectionTimeRange = new TimeRange { StartTime = ts, EndTime = te }; |
|||
RangeSelected?.Invoke(this, new GanttChartRangeSelectedEventArgs(ts, te)); |
|||
} |
|||
} |
|||
} |
|||
_IsMouseDown = false; |
|||
_DragStartLocation = Point.Empty; |
|||
_DragEndLocation = Point.Empty; |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标移动事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
protected void OnMouseMove(object sender, MouseEventArgs e) |
|||
{ |
|||
if (_IsMouseDown) |
|||
{ |
|||
if (_IsShowTooltip) |
|||
{ |
|||
_IsShowTooltip = false; |
|||
_ShowTooltipItem = null; |
|||
_ShowTooltipPoint = Point.Empty; |
|||
|
|||
Invalidate(); |
|||
} |
|||
if (_IsDragItem) |
|||
{ |
|||
|
|||
} |
|||
else if (_DragStartLocation.X > RowHeaderWidth && _DragStartLocation.Y > ColumnHeight) |
|||
{ |
|||
//TODO: 画选择框
|
|||
_DragEndLocation = e.Location; |
|||
Invalidate(); |
|||
} |
|||
return; |
|||
} |
|||
else if (IsHoverDateSplitLine(e.Location) && !IsHoverItem(e.Location)) |
|||
{ |
|||
Cursor = Cursors.VSplit; |
|||
} |
|||
//else if (IsHoverRowHeader(e))
|
|||
//{
|
|||
// Cursor = DefaultCursor;
|
|||
//}
|
|||
else if (IsHoverItem(e.Location)) |
|||
{ |
|||
Cursor = Cursors.Hand; |
|||
//TODO:显示Tooltip
|
|||
if (!_IsShowTooltip || GetItem(e.Location) != _ShowTooltipItem) |
|||
{ |
|||
_IsShowTooltip = true; |
|||
_ShowTooltipItem = GetItem(e.Location); |
|||
_ShowTooltipPoint = ComputeTooltipLocation(e.Location); |
|||
|
|||
Invalidate(); |
|||
return; |
|||
} |
|||
else |
|||
{ |
|||
return; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
Cursor = DefaultCursor; |
|||
} |
|||
if (_IsShowTooltip) |
|||
{ |
|||
_IsShowTooltip = false; |
|||
_ShowTooltipItem = null; |
|||
_ShowTooltipPoint = Point.Empty; |
|||
|
|||
Invalidate(); |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 横向滚动事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
private void HScrollBar_Scroll(object sender, ScrollEventArgs e) |
|||
{ |
|||
Invalidate(); |
|||
} |
|||
/// <summary>
|
|||
/// 纵向滚动事件
|
|||
/// </summary>
|
|||
/// <param name="sender"></param>
|
|||
/// <param name="e"></param>
|
|||
private void VScrollBar_Scroll(object sender, ScrollEventArgs e) |
|||
{ |
|||
Invalidate(); |
|||
} |
|||
/// <summary>
|
|||
/// 属性改变事件
|
|||
/// </summary>
|
|||
/// <param name="name"></param>
|
|||
/// <param name="value"></param>
|
|||
private void OnPropertyChanged(string name, object value) |
|||
{ |
|||
this.Brushes?.Refresh(); |
|||
var args = new GanttChartPropertyChangeEventArgs(name, value); |
|||
PropertyChanged?.Invoke(this, args); |
|||
if(name == nameof(BlockType)) |
|||
{ |
|||
Rows.IsChanged = true; |
|||
} |
|||
AdjustScrollbar(); |
|||
Invalidate(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,217 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Drawing; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Windows.Forms; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图控件
|
|||
/// 该部分类处理甘特图逻辑
|
|||
/// </summary>
|
|||
public partial class GanttChartView |
|||
{ |
|||
/// <summary>
|
|||
/// 鼠标是否经过日分割线
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
/// <returns></returns>
|
|||
private bool IsHoverDateSplitLine(Point e) |
|||
{ |
|||
var t = (e.X + _HScrollBar.Value - RowHeaderWidth + this.DateWidth) % this.DateWidth; |
|||
return e.X > this.RowHeaderWidth + 3 && e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && (this.DateWidth - 2 <= t || t <= 1); |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标是否经过行标题
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
/// <returns></returns>
|
|||
private bool IsHoverRowHeader(Point e) |
|||
{ |
|||
return e.X <= this.RowHeaderWidth && e.Y > this.ColumnHeight; |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标是否经过行
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
/// <returns></returns>
|
|||
private bool IsHoverRow(Point e) |
|||
{ |
|||
var y = e.Y + _VScrollBar.Value; |
|||
return e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && e.Y > this.ColumnHeight && Rows != null ? Rows.Any(r=>r.Top <= y && r.Bottom >= y) : false; |
|||
} |
|||
/// <summary>
|
|||
/// 鼠标是否经过项
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
/// <returns></returns>
|
|||
private bool IsHoverItem(Point e) |
|||
{ |
|||
if(e.X > this.RowHeaderWidth && e.Y > this.ColumnHeight && Rows != null) |
|||
{ |
|||
var row = GetRow(e); |
|||
if (row != null && row.Items != null && row.Items.Any()) |
|||
{ |
|||
var x = e.X + _HScrollBar.Value; |
|||
var y = e.Y + _VScrollBar.Value; |
|||
return row.Items.Any(r=>r.Left<=x && x <= r.Left + Math.Max(r.Width, r.TextWidth) && r.Top <= y && y <= r.Top + ItemHeight); |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
/// <summary>
|
|||
/// 获取项
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
/// <returns></returns>
|
|||
private GanttChartViewItem GetItem(Point e) |
|||
{ |
|||
if (e.X > this.RowHeaderWidth && e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && e.Y > this.ColumnHeight && Rows != null) |
|||
{ |
|||
var row = GetRow(e); |
|||
if (row != null && row.Items != null && row.Items.Any()) |
|||
{ |
|||
var x = e.X + _HScrollBar.Value; |
|||
var y = e.Y + _VScrollBar.Value; |
|||
return row.Items.OrderBy(r=>r.Left).LastOrDefault(r => r.Left <= x && x <= r.Left + Math.Max(r.Width, r.TextWidth) && r.Top <= y && y <= r.Top + ItemHeight); |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
/// <summary>
|
|||
/// 获取行
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
/// <returns></returns>
|
|||
private GanttChartViewRow GetRow(Point e) |
|||
{ |
|||
if (e.X < ((EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth + RowHeaderWidth - _HScrollBar.Value && e.Y > this.ColumnHeight && e.Y + _VScrollBar.Value < (Rows == null || !Rows.Any() ? 0 : Rows.Max(r=>r.Bottom)) && Rows != null) |
|||
{ |
|||
var y = e.Y + _VScrollBar.Value; |
|||
return Rows.FirstOrDefault(r => r.Top <= y && r.Bottom >= y); |
|||
} |
|||
return null; |
|||
} |
|||
/// <summary>
|
|||
/// 计算所有行和项的大小
|
|||
/// </summary>
|
|||
private void ComputeRowsAndItemsSize() |
|||
{ |
|||
var minuteWidth = DateWidth / 24f / 60f; |
|||
var currentRowY = ColumnHeight; |
|||
foreach (var row in Rows) |
|||
{ |
|||
row.Top = currentRowY; |
|||
var currentItemY = currentRowY + RowSpacing; |
|||
row.Bottom = currentRowY; |
|||
if(row.Items != null) |
|||
{ |
|||
var beforeTop = row.Top + RowSpacing; |
|||
var beforeRight = 0; |
|||
var items = row.Items.OrderBy(r => r.StartTime).ToList(); |
|||
for ( int i = 0; i < items.Count; i++) |
|||
{ |
|||
var item = items[i]; |
|||
if (item.EndTime >= StartTime && item.StartTime <= EndTime && item.EndTime >= item.StartTime) |
|||
{ |
|||
item.Left = (int)((item.StartTime - StartTime).TotalMinutes * minuteWidth) + RowHeaderWidth; |
|||
item.Width = (int)((item.EndTime - item.StartTime).TotalMinutes * minuteWidth); |
|||
item.TextWidth = TextRenderer.MeasureText(item.Title, ItemTextFont, System.Drawing.Size.Empty).Width; |
|||
if (item.Left < beforeRight || BlockType == GanttChartViewItemBlockType.Block && i > 0) |
|||
{ |
|||
var its = items.Take(i).GroupBy(r=>r.Top).Select(r=>r.OrderByDescending(p => p.Left + p.TextWidth).First()); |
|||
if(BlockType == GanttChartViewItemBlockType.Return && its.Any(r=>r.Left + r.TextWidth < item.Left)) |
|||
{ |
|||
var it = its.First(r => r.Left + r.TextWidth < item.Left); |
|||
item.Top = it.Top; |
|||
beforeTop = it.Top; |
|||
} |
|||
else |
|||
{ |
|||
if(BlockType == GanttChartViewItemBlockType.Return && its.Any()) |
|||
{ |
|||
beforeTop = its.Max(r => r.Top); |
|||
} |
|||
item.Top = beforeTop + ItemHeight + ItemSpacing; |
|||
beforeTop += ItemHeight + ItemSpacing; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (i > 0) |
|||
{ |
|||
if (BlockType == GanttChartViewItemBlockType.Return && beforeTop != row.Top + RowSpacing) |
|||
{ |
|||
beforeTop = row.Top + RowSpacing; |
|||
} |
|||
} |
|||
item.Top = beforeTop; |
|||
} |
|||
if (BlockType == GanttChartViewItemBlockType.Compact) |
|||
{ |
|||
beforeRight = item.Left + item.Width; |
|||
} |
|||
else |
|||
{ |
|||
beforeRight = item.Left + Math.Max(item.TextWidth, item.Width); |
|||
} |
|||
if (item.Ranges != null && item.Ranges.Any()) |
|||
{ |
|||
var subs = item.Ranges.OrderBy(r => r.StartTime); |
|||
foreach (var sub in subs) |
|||
{ |
|||
sub.Left = item.Left + (int)((sub.StartTime - item.StartTime).TotalMinutes * minuteWidth); |
|||
sub.Width = (int)((sub.EndTime - sub.StartTime).TotalMinutes * minuteWidth); |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
//row.Items.Remove(item);
|
|||
//i--;
|
|||
} |
|||
} |
|||
} |
|||
if (row.Items == null || !row.Items.Any(r=>r.Left > 0)) |
|||
{ |
|||
row.Bottom = row.Top + ItemHeight + RowSpacing * 2; |
|||
} |
|||
else |
|||
{ |
|||
row.Bottom = Math.Max(row.Items.Max(r => r.Top), ColumnHeight + RowSpacing) + ItemHeight + RowSpacing; |
|||
} |
|||
currentRowY = row.Bottom; |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 计算提示框的位置
|
|||
/// </summary>
|
|||
/// <param name="e"></param>
|
|||
/// <returns></returns>
|
|||
private Point ComputeTooltipLocation(Point e) |
|||
{ |
|||
var size = TooltipOuterSize; |
|||
var x = e.X; |
|||
if (e.X + size.Width > _ContentControl.Width) |
|||
{ |
|||
var t = e.X - size.Width; |
|||
if (t < 0 && 0 - t < (e.X + size.Width) - _ContentControl.Width || t >= 0) |
|||
{ |
|||
x = t; |
|||
} |
|||
} |
|||
var y = _ShowTooltipItem.Top - _VScrollBar.Value + ItemHeight + ItemSpacing; |
|||
if(y + size.Height > _ContentControl.Height) |
|||
{ |
|||
var t = _ShowTooltipItem.Top - _VScrollBar.Value - ItemSpacing - size.Height; |
|||
if (t < 0 && 0 - t < (y + size.Height) - _ContentControl.Height || t >= 0) |
|||
{ |
|||
y = t; |
|||
} |
|||
} |
|||
return new Point(x, y); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,756 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel; |
|||
using System.Drawing; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Windows.Forms; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图控件
|
|||
/// 该部分类主要是甘特图的属性
|
|||
/// </summary>
|
|||
public partial class GanttChartView |
|||
{ |
|||
#region Fonts
|
|||
private Font _ColumnDateTextFont = DefaultFont; |
|||
|
|||
/// <summary>
|
|||
/// 日期字体
|
|||
/// </summary>
|
|||
public Font ColumnDateTextFont |
|||
{ |
|||
get { return _ColumnDateTextFont; } |
|||
set { _ColumnDateTextFont = value; OnPropertyChanged(nameof(ColumnDateTextFont), value); } |
|||
} |
|||
|
|||
private Font _ColumnHourTextFont = DefaultFont; |
|||
|
|||
/// <summary>
|
|||
/// 时间字体
|
|||
/// </summary>
|
|||
public Font ColumnHourTextFont |
|||
{ |
|||
get { return _ColumnHourTextFont; } |
|||
set { _ColumnHourTextFont = value; OnPropertyChanged(nameof(ColumnHourTextFont), value); } |
|||
} |
|||
|
|||
private Font _RowHeaderTextFont = DefaultFont; |
|||
|
|||
/// <summary>
|
|||
/// 行标题字体
|
|||
/// </summary>
|
|||
public Font RowHeaderTextFont |
|||
{ |
|||
get { return _RowHeaderTextFont; } |
|||
set { _RowHeaderTextFont = value; OnPropertyChanged(nameof(RowHeaderTextFont), value); } |
|||
} |
|||
|
|||
private Font _ItemTextFont = DefaultFont; |
|||
|
|||
/// <summary>
|
|||
/// 项字体
|
|||
/// </summary>
|
|||
public Font ItemTextFont |
|||
{ |
|||
get { return _ItemTextFont; } |
|||
set { _ItemTextFont = value; OnPropertyChanged(nameof(ItemTextFont), value); } |
|||
} |
|||
|
|||
private Font _TooltipTextFont = DefaultFont; |
|||
|
|||
/// <summary>
|
|||
/// 提示文字字体
|
|||
/// </summary>
|
|||
public Font TooltipTextFont |
|||
{ |
|||
get { return _TooltipTextFont; } |
|||
set { _TooltipTextFont = value; OnPropertyChanged(nameof(TooltipTextFont), value); } |
|||
} |
|||
#endregion
|
|||
#region Colors
|
|||
private Color _GridColor = Color.FromArgb(210, 210, 210); |
|||
|
|||
/// <summary>
|
|||
/// 网格颜色
|
|||
/// </summary>
|
|||
public Color GridColor |
|||
{ |
|||
get { return _GridColor; } |
|||
set { _GridColor = value; OnPropertyChanged(nameof(GridColor), value); } |
|||
} |
|||
|
|||
private Color _ColumnDateTextColor = Color.FromArgb(102, 102, 102); |
|||
|
|||
/// <summary>
|
|||
/// 日期文字颜色
|
|||
/// </summary>
|
|||
public Color ColumnDateTextColor |
|||
{ |
|||
get { return _ColumnDateTextColor; } |
|||
set { _ColumnDateTextColor = value; OnPropertyChanged(nameof(ColumnDateTextColor), value); } |
|||
} |
|||
|
|||
private Color _ColumnHourTextColor = Color.FromArgb(102, 102, 102); |
|||
|
|||
/// <summary>
|
|||
/// 小时文字颜色
|
|||
/// </summary>
|
|||
public Color ColumnHourTextColor |
|||
{ |
|||
get { return _ColumnHourTextColor; } |
|||
set { _ColumnHourTextColor = value; OnPropertyChanged(nameof(ColumnHourTextColor), value); } |
|||
} |
|||
|
|||
private Color _HeaderBackColor = Color.FromArgb(247, 247, 247); |
|||
|
|||
/// <summary>
|
|||
/// 标题背景颜色
|
|||
/// </summary>
|
|||
public Color HeaderBackColor |
|||
{ |
|||
get { return _HeaderBackColor; } |
|||
set { _HeaderBackColor = value; OnPropertyChanged(nameof(HeaderBackColor), value); } |
|||
} |
|||
|
|||
private Color _ContentBackColor = Color.White; |
|||
|
|||
/// <summary>
|
|||
/// 内容背景颜色
|
|||
/// </summary>
|
|||
public Color ContentBackColor |
|||
{ |
|||
get { return _ContentBackColor; } |
|||
set { _ContentBackColor = value; OnPropertyChanged(nameof(ContentBackColor), value); } |
|||
} |
|||
|
|||
private Color _CurrentTimeLineColor = Color.Red; |
|||
|
|||
/// <summary>
|
|||
/// 当前时间线颜色
|
|||
/// </summary>
|
|||
public Color CurrentTimeLineColor |
|||
{ |
|||
get { return _CurrentTimeLineColor; } |
|||
set { _CurrentTimeLineColor = value; OnPropertyChanged(nameof(CurrentTimeLineColor), value); } |
|||
} |
|||
|
|||
private Color _ItemTextColor = Color.FromArgb(51, 51, 51); |
|||
|
|||
/// <summary>
|
|||
/// 项文字颜色
|
|||
/// </summary>
|
|||
public Color ItemTextColor |
|||
{ |
|||
get { return _ItemTextColor; } |
|||
set { _ItemTextColor = value; OnPropertyChanged(nameof(ItemTextColor), value); } |
|||
} |
|||
|
|||
private Color _ItemBackColor = Color.FromArgb(190, 190, 190); |
|||
|
|||
/// <summary>
|
|||
/// 项背景颜色
|
|||
/// </summary>
|
|||
public Color ItemBackColor |
|||
{ |
|||
get { return _ItemBackColor; } |
|||
set { _ItemBackColor = value; OnPropertyChanged(nameof(ItemBackColor), value); } |
|||
} |
|||
|
|||
private Color _ItemBorderColor = Color.FromArgb(18, 170, 11); |
|||
|
|||
/// <summary>
|
|||
/// 项边框颜色
|
|||
/// </summary>
|
|||
public Color ItemBorderColor |
|||
{ |
|||
get { return _ItemBorderColor; } |
|||
set { _ItemBorderColor = value; OnPropertyChanged(nameof(ItemBorderColor), value); } |
|||
} |
|||
|
|||
private Color _ItemStartFlagColor = Color.Red; |
|||
|
|||
/// <summary>
|
|||
/// 项首标志颜色
|
|||
/// </summary>
|
|||
public Color ItemStartFlagColor |
|||
{ |
|||
get { return _ItemStartFlagColor; } |
|||
set { _ItemStartFlagColor = value; OnPropertyChanged(nameof(ItemStartFlagColor), value); } |
|||
} |
|||
|
|||
private Color _ItemSubRangeBackColor = Color.FromArgb(153, 201, 255); |
|||
|
|||
/// <summary>
|
|||
/// 项时间范围背景颜色
|
|||
/// </summary>
|
|||
public Color ItemSubRangeBackColor |
|||
{ |
|||
get { return _ItemSubRangeBackColor; } |
|||
set { _ItemSubRangeBackColor = value; OnPropertyChanged(nameof(ItemSubRangeBackColor), value); } |
|||
} |
|||
|
|||
private Color _ItemSelectionTextColor = Color.FromArgb(18, 170, 11); |
|||
|
|||
/// <summary>
|
|||
/// 选中项文字颜色
|
|||
/// </summary>
|
|||
public Color ItemSelectionTextColor |
|||
{ |
|||
get { return _ItemSelectionTextColor; } |
|||
set { _ItemSelectionTextColor = value; OnPropertyChanged(nameof(ItemSelectionTextColor), value); } |
|||
} |
|||
|
|||
private Color _ItemSelectionBackColor = Color.FromArgb(229, 249, 229); |
|||
|
|||
/// <summary>
|
|||
/// 选中项背景颜色
|
|||
/// </summary>
|
|||
public Color ItemSelectionBackColor |
|||
{ |
|||
get { return _ItemSelectionBackColor; } |
|||
set { _ItemSelectionBackColor = value; OnPropertyChanged(nameof(ItemSelectionBackColor), value); } |
|||
} |
|||
|
|||
private Color _ItemSelectionBorderColor = Color.FromArgb(18, 170, 11); |
|||
|
|||
/// <summary>
|
|||
/// 选中项边框颜色
|
|||
/// </summary>
|
|||
public Color ItemSelectionBorderColor |
|||
{ |
|||
get { return _ItemSelectionBorderColor; } |
|||
set { _ItemSelectionBorderColor = value; OnPropertyChanged(nameof(ItemSelectionBorderColor), value); } |
|||
} |
|||
|
|||
private Color _ItemSelectionSubRangeBackColor = Color.FromArgb(153, 201, 255); |
|||
|
|||
/// <summary>
|
|||
/// 选中项时间范围背景颜色
|
|||
/// </summary>
|
|||
public Color ItemSelectionSubRangeBackColor |
|||
{ |
|||
get { return _ItemSelectionSubRangeBackColor; } |
|||
set { _ItemSelectionSubRangeBackColor = value; OnPropertyChanged(nameof(ItemSelectionSubRangeBackColor), value); } |
|||
} |
|||
|
|||
private Color _RowHeaderTextColor = Color.FromArgb(102, 102, 102); |
|||
|
|||
/// <summary>
|
|||
/// 行标题文字颜色
|
|||
/// </summary>
|
|||
public Color RowHeaderTextColor |
|||
{ |
|||
get { return _RowHeaderTextColor; } |
|||
set { _RowHeaderTextColor = value; OnPropertyChanged(nameof(RowHeaderTextColor), value); } |
|||
} |
|||
|
|||
private Color _RowSelectionHeaderTextColor = Color.FromArgb(102, 102, 102); |
|||
|
|||
/// <summary>
|
|||
/// 选中行标题文字颜色
|
|||
/// </summary>
|
|||
public Color RowSelectionHeaderTextColor |
|||
{ |
|||
get { return _RowSelectionHeaderTextColor; } |
|||
set { _RowSelectionHeaderTextColor = value; OnPropertyChanged(nameof(RowSelectionHeaderTextColor), value); } |
|||
} |
|||
|
|||
private Color _RowSelectionBorderColor = Color.FromArgb(247, 247, 247); |
|||
|
|||
/// <summary>
|
|||
/// 选中行边框颜色
|
|||
/// </summary>
|
|||
public Color RowSelectionBorderColor |
|||
{ |
|||
get { return _RowSelectionBorderColor; } |
|||
set { _RowSelectionBorderColor = value; OnPropertyChanged(nameof(RowSelectionBorderColor), value); } |
|||
} |
|||
|
|||
private Color _RowSelectionHeaderBackColor = Color.FromArgb(247, 247, 247); |
|||
|
|||
/// <summary>
|
|||
/// 选中行标题背景颜色
|
|||
/// </summary>
|
|||
public Color RowSelectionHeaderBackColor |
|||
{ |
|||
get { return _RowSelectionHeaderBackColor; } |
|||
set { _RowSelectionHeaderBackColor = value; OnPropertyChanged(nameof(RowSelectionHeaderBackColor), value); } |
|||
} |
|||
|
|||
private Color _RowSelectionContentBackColor = Color.FromArgb(247, 247, 247); |
|||
|
|||
/// <summary>
|
|||
/// 选中行内容背景颜色
|
|||
/// </summary>
|
|||
public Color RowSelectionContentBackColor |
|||
{ |
|||
get { return _RowSelectionContentBackColor; } |
|||
set { _RowSelectionContentBackColor = value; OnPropertyChanged(nameof(RowSelectionContentBackColor), value); } |
|||
} |
|||
|
|||
private Color _TooltipTextColor = Color.FromArgb(237, 237, 237); |
|||
|
|||
/// <summary>
|
|||
/// 提示文字颜色
|
|||
/// </summary>
|
|||
public Color TooltipTextColor |
|||
{ |
|||
get { return _TooltipTextColor; } |
|||
set { _TooltipTextColor = value; OnPropertyChanged(nameof(TooltipTextColor), value); } |
|||
} |
|||
|
|||
private Color _TooltipBorderColor = Color.FromArgb(102, 0, 0, 0); |
|||
|
|||
/// <summary>
|
|||
/// 提示边框颜色
|
|||
/// </summary>
|
|||
public Color TooltipBorderColor |
|||
{ |
|||
get { return _TooltipBorderColor; } |
|||
set { _TooltipBorderColor = value; OnPropertyChanged(nameof(TooltipBorderColor), value); } |
|||
} |
|||
|
|||
private Color _TooltipBackColor = Color.FromArgb(102, 0, 0, 0); |
|||
|
|||
/// <summary>
|
|||
/// 提示背景颜色
|
|||
/// </summary>
|
|||
public Color TooltipBackColor |
|||
{ |
|||
get { return _TooltipBackColor; } |
|||
set { _TooltipBackColor = value; OnPropertyChanged(nameof(TooltipBackColor), value); } |
|||
} |
|||
|
|||
private Color _TimeRangeSelecetionBackColor = Color.FromArgb(153, 201, 255); |
|||
|
|||
/// <summary>
|
|||
/// 选中时间范围背景颜色
|
|||
/// </summary>
|
|||
public Color TimeRangeSelecetionBackColor |
|||
{ |
|||
get { return _TimeRangeSelecetionBackColor; } |
|||
set { _TimeRangeSelecetionBackColor = value; OnPropertyChanged(nameof(TimeRangeSelecetionBackColor), value); } |
|||
} |
|||
|
|||
private Color _SelectionRectangleBackColor = Color.FromArgb(80, 210, 210, 210); |
|||
|
|||
/// <summary>
|
|||
/// 选择框背景颜色
|
|||
/// </summary>
|
|||
public Color SelectionRectangleBackColor |
|||
{ |
|||
get { return _SelectionRectangleBackColor; } |
|||
set { _SelectionRectangleBackColor = value; OnPropertyChanged(nameof(SelectionRectangleBackColor), value); } |
|||
} |
|||
|
|||
private Color _ItemWarnningTextColor = Color.Red; |
|||
|
|||
/// <summary>
|
|||
/// 项警告文字颜色
|
|||
/// </summary>
|
|||
public Color ItemWarnningTextColor |
|||
{ |
|||
get { return _ItemWarnningTextColor; } |
|||
set { _ItemWarnningTextColor = value; OnPropertyChanged(nameof(ItemWarnningTextColor), value); } |
|||
} |
|||
#endregion
|
|||
#region Mouse
|
|||
private float _MouseWheelSensitivity = 0.5f; |
|||
|
|||
/// <summary>
|
|||
/// 鼠标滚轮灵敏度
|
|||
/// </summary>
|
|||
[DefaultValue(0.5f)] |
|||
public float MouseWheelSensitivity |
|||
{ |
|||
get { return _MouseWheelSensitivity; } |
|||
set { _MouseWheelSensitivity = value; OnPropertyChanged(nameof(MouseWheelSensitivity), value); } |
|||
} |
|||
#endregion
|
|||
#region Size
|
|||
private int _ItemHeight = 30; |
|||
|
|||
/// <summary>
|
|||
/// 项高度
|
|||
/// </summary>
|
|||
[DefaultValue(30)] |
|||
public int ItemHeight |
|||
{ |
|||
get { return _ItemHeight; } |
|||
set { _ItemHeight = value; OnPropertyChanged(nameof(ItemHeight), value); } |
|||
} |
|||
|
|||
private int _RowHeaderWidth = 150; |
|||
|
|||
/// <summary>
|
|||
/// 行标题宽度
|
|||
/// </summary>
|
|||
[DefaultValue(150)] |
|||
public int RowHeaderWidth |
|||
{ |
|||
get { return _RowHeaderWidth; } |
|||
set { _RowHeaderWidth = value; OnPropertyChanged(nameof(RowHeaderWidth), value); } |
|||
} |
|||
|
|||
private int _RowHeight = 100; |
|||
|
|||
/// <summary>
|
|||
/// 行高
|
|||
/// </summary>
|
|||
[DefaultValue(100)] |
|||
public int RowHeight |
|||
{ |
|||
get { return _RowHeight; } |
|||
set { _RowHeight = value; OnPropertyChanged(nameof(RowHeight), value); } |
|||
} |
|||
|
|||
private int _ColumnDateHeight = 30; |
|||
|
|||
/// <summary>
|
|||
/// 日期高度
|
|||
/// </summary>
|
|||
[DefaultValue(30)] |
|||
public int ColumnDateHeight |
|||
{ |
|||
get { return _ColumnDateHeight; } |
|||
set { _ColumnDateHeight = value; OnPropertyChanged(nameof(ColumnDateHeight), value); } |
|||
} |
|||
|
|||
private int _ColumnHourHeight = 30; |
|||
|
|||
/// <summary>
|
|||
/// 小时高度
|
|||
/// </summary>
|
|||
[DefaultValue(30)] |
|||
public int ColumnHourHeight |
|||
{ |
|||
get { return _ColumnHourHeight; } |
|||
set { _ColumnHourHeight = value; OnPropertyChanged(nameof(ColumnHourHeight), value); } |
|||
} |
|||
|
|||
private int _DateWidth = MinDateWidth; |
|||
|
|||
/// <summary>
|
|||
/// 日期宽度
|
|||
/// </summary>
|
|||
[DefaultValue(MinDateWidth)] |
|||
public int DateWidth |
|||
{ |
|||
get { return _DateWidth; } |
|||
set { _DateWidth = value; OnPropertyChanged(nameof(DateWidth), value); } |
|||
} |
|||
|
|||
private int _HScrollHeight = 15; |
|||
|
|||
/// <summary>
|
|||
/// 横向滚动条高度
|
|||
/// </summary>
|
|||
[DefaultValue(15)] |
|||
public int HScrollHeight |
|||
{ |
|||
get { return _HScrollHeight; } |
|||
set { _HScrollHeight = value; OnPropertyChanged(nameof(HScrollHeight), value); } |
|||
} |
|||
|
|||
private int _VScrollWidth = 15; |
|||
|
|||
/// <summary>
|
|||
/// 纵向滚动条宽度
|
|||
/// </summary>
|
|||
[DefaultValue(15)] |
|||
public int VScrollWidth |
|||
{ |
|||
get { return _VScrollWidth; } |
|||
set { _VScrollWidth = value; OnPropertyChanged(nameof(VScrollWidth), value); } |
|||
} |
|||
|
|||
private int _ItemSpacing = 2; |
|||
|
|||
/// <summary>
|
|||
/// 项的行间距
|
|||
/// </summary>
|
|||
[DefaultValue(2)] |
|||
public int ItemSpacing |
|||
{ |
|||
get { return _ItemSpacing; } |
|||
set { _ItemSpacing = value; OnPropertyChanged(nameof(ItemSpacing), value); } |
|||
} |
|||
|
|||
private int _RowSpacing = 5; |
|||
|
|||
/// <summary>
|
|||
/// 行间距
|
|||
/// </summary>
|
|||
[DefaultValue(5)] |
|||
public int RowSpacing |
|||
{ |
|||
get { return _RowSpacing; } |
|||
set { _RowSpacing = value; OnPropertyChanged(nameof(RowSpacing), value); } |
|||
} |
|||
#endregion
|
|||
#region Control
|
|||
private bool _IsFixedRowHeight = false; |
|||
|
|||
/// <summary>
|
|||
/// 是否固定行高
|
|||
/// </summary>
|
|||
[DefaultValue(false)] |
|||
public bool IsFixedRowHeight |
|||
{ |
|||
get { return _IsFixedRowHeight; } |
|||
set { _IsFixedRowHeight = value; OnPropertyChanged(nameof(IsFixedRowHeight), value); } |
|||
} |
|||
|
|||
private bool _EnableEdit = false; |
|||
|
|||
/// <summary>
|
|||
/// 启用编辑
|
|||
/// </summary>
|
|||
[DefaultValue(false)] |
|||
public bool EnableEdit |
|||
{ |
|||
get { return _EnableEdit; } |
|||
set { _EnableEdit = value; OnPropertyChanged(nameof(EnableEdit), value); } |
|||
} |
|||
|
|||
private bool _AllowItemNotWrap = true; |
|||
|
|||
/// <summary>
|
|||
/// 允许项文字换行
|
|||
/// </summary>
|
|||
[DefaultValue(true)] |
|||
public bool AllowItemNotWrap |
|||
{ |
|||
get { return _AllowItemNotWrap; } |
|||
set { _AllowItemNotWrap = value; OnPropertyChanged(nameof(AllowItemNotWrap), value); } |
|||
} |
|||
|
|||
private bool _IsShowItemBorder = false; |
|||
|
|||
/// <summary>
|
|||
/// 是否显示项边框
|
|||
/// </summary>
|
|||
[DefaultValue(false)] |
|||
public bool IsShowItemBorder |
|||
{ |
|||
get { return _IsShowItemBorder; } |
|||
set { _IsShowItemBorder = value; OnPropertyChanged(nameof(IsShowItemBorder), value); } |
|||
} |
|||
|
|||
private bool _AllowHeaderNotWrap = true; |
|||
|
|||
/// <summary>
|
|||
/// 允许行标题文字换行
|
|||
/// </summary>
|
|||
[DefaultValue(true)] |
|||
public bool AllowHeaderNotWrap |
|||
{ |
|||
get { return _AllowHeaderNotWrap; } |
|||
set { _AllowHeaderNotWrap = value; OnPropertyChanged(nameof(AllowHeaderNotWrap), value); } |
|||
} |
|||
|
|||
private GanttChartViewItemBlockType _BlockType = GanttChartViewItemBlockType.TextOverBlock; |
|||
|
|||
/// <summary>
|
|||
/// 项换行模式
|
|||
/// </summary>
|
|||
public GanttChartViewItemBlockType BlockType |
|||
{ |
|||
get { return _BlockType; } |
|||
set { _BlockType = value; OnPropertyChanged(nameof(BlockType), value); } |
|||
} |
|||
|
|||
private bool _IsShowSelectionBorder = false; |
|||
|
|||
/// <summary>
|
|||
/// 显示行选中高亮边框
|
|||
/// </summary>
|
|||
[DefaultValue(false)] |
|||
public bool IsShowSelectionBorder |
|||
{ |
|||
get { return _IsShowSelectionBorder; } |
|||
set { _IsShowSelectionBorder = value; OnPropertyChanged(nameof(IsShowSelectionBorder), value); } |
|||
} |
|||
|
|||
private bool _AllowSelectRange = false; |
|||
|
|||
/// <summary>
|
|||
/// 允许选中时间范围
|
|||
/// </summary>
|
|||
[DefaultValue(false)] |
|||
public bool AllowSelectRange |
|||
{ |
|||
get { return _AllowSelectRange; } |
|||
set { _AllowSelectRange = value; OnPropertyChanged(nameof(AllowSelectRange), value); } |
|||
} |
|||
|
|||
private Func<GanttChartViewItem, GanttChartViewItem, bool> _SelectionItemSameComparator = null; |
|||
|
|||
/// <summary>
|
|||
/// 选择项的同类项比较器
|
|||
/// </summary>
|
|||
public Func<GanttChartViewItem, GanttChartViewItem, bool> SelectionItemSameComparator |
|||
{ |
|||
get { return _SelectionItemSameComparator; } |
|||
set { _SelectionItemSameComparator = value; } |
|||
} |
|||
#endregion
|
|||
#region DataSource
|
|||
private DateTime _StartDate = DateTime.Today; |
|||
|
|||
/// <summary>
|
|||
/// 开始日期
|
|||
/// </summary>
|
|||
public DateTime StartDate |
|||
{ |
|||
get { return _StartDate; } |
|||
set { _StartDate = value; OnPropertyChanged(nameof(StartDate), value); } |
|||
} |
|||
|
|||
private DateTime _EndDate = DateTime.Today.AddDays(1); |
|||
|
|||
/// <summary>
|
|||
/// 结束日期
|
|||
/// </summary>
|
|||
public DateTime EndDate |
|||
{ |
|||
get { return _EndDate; } |
|||
set { _EndDate = value; OnPropertyChanged(nameof(EndDate), value); } |
|||
} |
|||
|
|||
private GanttChartCollection<GanttChartViewRow> _Rows = new GanttChartCollection<GanttChartViewRow>(); |
|||
|
|||
/// <summary>
|
|||
/// 行集合
|
|||
/// </summary>
|
|||
public GanttChartCollection<GanttChartViewRow> Rows |
|||
{ |
|||
get { return _Rows; } |
|||
set { _Rows = value; OnPropertyChanged(nameof(Rows), value); } |
|||
} |
|||
|
|||
private GanttChartViewRow _SelectionRow = null; |
|||
|
|||
/// <summary>
|
|||
/// 选中的行
|
|||
/// </summary>
|
|||
public GanttChartViewRow SelectionRow |
|||
{ |
|||
get { return _SelectionRow; } |
|||
set { _SelectionRow = value; OnPropertyChanged(nameof(SelectionRow), value); } |
|||
} |
|||
|
|||
private GanttChartViewItem _SelectionItem = null; |
|||
|
|||
/// <summary>
|
|||
/// 选中的项
|
|||
/// </summary>
|
|||
public GanttChartViewItem SelectionItem |
|||
{ |
|||
get { return _SelectionItem; } |
|||
set { _SelectionItem = value; OnPropertyChanged(nameof(SelectionItem), value); } |
|||
} |
|||
|
|||
private TimeRange _SelectionTimeRange = null; |
|||
|
|||
/// <summary>
|
|||
/// 选中的时间范围
|
|||
/// </summary>
|
|||
public TimeRange SelectionTimeRange |
|||
{ |
|||
get { return _SelectionTimeRange; } |
|||
set { _SelectionTimeRange = value; OnPropertyChanged(nameof(SelectionTimeRange), value); } |
|||
} |
|||
|
|||
private DateTime _DateSplitTime = DateTime.MinValue; |
|||
|
|||
/// <summary>
|
|||
/// 日分割时间
|
|||
/// </summary>
|
|||
public DateTime DateSplitTime |
|||
{ |
|||
get { return _DateSplitTime; } |
|||
set { _DateSplitTime = value; OnPropertyChanged(nameof(DateSplitTime), value); } |
|||
} |
|||
|
|||
private string _DateTimeShowText = "时间"; |
|||
|
|||
/// <summary>
|
|||
/// 时间显示文本
|
|||
/// </summary>
|
|||
[DefaultValue("时间")] |
|||
public string DateTimeShowText |
|||
{ |
|||
get { return _DateTimeShowText; } |
|||
set { _DateTimeShowText = value; OnPropertyChanged(nameof(DateTimeShowText), value); } |
|||
} |
|||
|
|||
private string _RowTitleShowText = "资源"; |
|||
|
|||
/// <summary>
|
|||
/// 行头显示文本
|
|||
/// </summary>
|
|||
[DefaultValue("资源")] |
|||
public string RowTitleShowText |
|||
{ |
|||
get { return _RowTitleShowText; } |
|||
set { _RowTitleShowText = value; OnPropertyChanged(nameof(RowTitleShowText), value); } |
|||
} |
|||
#endregion
|
|||
|
|||
#region ReadOnly
|
|||
public int ColumnHeight |
|||
{ |
|||
get { return ColumnDateHeight + ColumnHourHeight; } |
|||
} |
|||
|
|||
public int TotalDays |
|||
{ |
|||
get |
|||
{ |
|||
return (int)(EndDate.Date - StartDate.Date).TotalDays + 1; |
|||
} |
|||
} |
|||
public DateTime StartTime |
|||
{ |
|||
get |
|||
{ |
|||
return StartDate.Date.Add(DateSplitTime - DateSplitTime.Date); |
|||
} |
|||
} |
|||
public DateTime EndTime |
|||
{ |
|||
get |
|||
{ |
|||
return EndDate.Date.Add(DateSplitTime - DateSplitTime.Date); |
|||
} |
|||
} |
|||
private Size TooltipSize |
|||
{ |
|||
get |
|||
{ |
|||
var size = TextRenderer.MeasureText(_ShowTooltipItem.Tooltip, TooltipTextFont, Size.Empty); |
|||
size.Height = size.Height + (int)((_ShowTooltipItem.Tooltip.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Length - 1) * 1.7); |
|||
return size; |
|||
} |
|||
} |
|||
private Size TooltipOuterSize |
|||
{ |
|||
get |
|||
{ |
|||
var size = TooltipSize; |
|||
size.Width += RowSpacing * 2; |
|||
size.Height += RowSpacing * 2; |
|||
return size; |
|||
} |
|||
} |
|||
#endregion
|
|||
|
|||
#region Const
|
|||
private const int MinDateWidth = 3 * 48; |
|||
#endregion
|
|||
} |
|||
} |
@ -0,0 +1,409 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Drawing; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Windows.Forms; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图控件
|
|||
/// 该部分类用于处理甘特图的绘制渲染
|
|||
/// </summary>
|
|||
public partial class GanttChartView |
|||
{ |
|||
/// <summary>
|
|||
/// 画背景
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="bottom"></param>
|
|||
protected virtual void DrawBack(Graphics graphics, int bottom) |
|||
{ |
|||
graphics.FillRectangle(this.Brushes.BackBrush, _ContentControl.DisplayRectangle); |
|||
var range = new RectangleF(new PointF(0, 0), new SizeF(TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value, bottom - _VScrollBar.Value)); |
|||
graphics.SetClip(range); |
|||
graphics.FillRectangle(this.Brushes.HeaderBackBrush, range); |
|||
range = new RectangleF(new PointF(0, ColumnHeight), new SizeF(TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value, bottom - ColumnHeight - _VScrollBar.Value)); |
|||
graphics.FillRectangle(this.Brushes.ContentBackBrush, range); |
|||
if (_SelectionRow != null) |
|||
{ |
|||
var selectionHeader = new Rectangle(1, _SelectionRow.Top + 1 - _VScrollBar.Value, RowHeaderWidth - 2, (int)(_SelectionRow.Bottom - _SelectionRow.Top - 1)); |
|||
var selectionContent = new Rectangle(RowHeaderWidth, _SelectionRow.Top + 1 - _VScrollBar.Value, (int)(TotalDays * DateWidth - _HScrollBar.Value - 1), selectionHeader.Height); |
|||
graphics.FillRectangle(this.Brushes.RowSelectionHeaderBackBrush, selectionHeader); |
|||
graphics.FillRectangle(this.Brushes.RowSelectionContentBackBrush, selectionContent); |
|||
} |
|||
graphics.ResetClip(); |
|||
} |
|||
/// <summary>
|
|||
/// 画没有数据
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="bottom"></param>
|
|||
protected virtual void DrawNonData(Graphics graphics, int bottom) |
|||
{ |
|||
|
|||
} |
|||
/// <summary>
|
|||
/// 画提示框
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
protected virtual void DrawItemTooltip(Graphics graphics) |
|||
{ |
|||
if (!_IsShowTooltip) return; |
|||
var size = TooltipSize; |
|||
var border = new Rectangle(_ShowTooltipPoint, new Size(size.Width + RowSpacing * 2, size.Height + RowSpacing * 2)); |
|||
var content = new Point(_ShowTooltipPoint.X + RowSpacing, _ShowTooltipPoint.Y + RowSpacing); |
|||
graphics.FillRectangle(this.Brushes.TooltipBackBrush, border); |
|||
graphics.DrawRectangle(this.Brushes.TooltipBorderPen, border); |
|||
graphics.DrawString(_ShowTooltipItem.Tooltip, TooltipTextFont, this.Brushes.TooltipTextBrush, content); |
|||
//TextRenderer.DrawText(graphics, _ShowTooltipItem.Tooltip, TooltipTextFont, content, TooltipTextColor);
|
|||
} |
|||
/// <summary>
|
|||
/// 画选中范围
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
protected virtual void DrawSelectionRange(Graphics graphics) |
|||
{ |
|||
if (!AllowSelectRange || _SelectionRange.IsEmpty) return; |
|||
graphics.FillRectangle(this.Brushes.TimeRangeSelecetionBackBrush, _SelectionRange); |
|||
} |
|||
/// <summary>
|
|||
/// 画选中的矩形
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
protected virtual void DrawSelectingRectangle(Graphics graphics) |
|||
{ |
|||
if (!AllowSelectRange || _DragStartLocation.IsEmpty || _DragEndLocation.IsEmpty || _DragStartLocation == _DragEndLocation || _DragStartLocation.X <= RowHeaderWidth || _DragStartLocation.Y <= ColumnHeight) return; |
|||
var row = GetRow(_DragStartLocation); |
|||
if (row == null) return; |
|||
var start = new Point(Math.Min(_DragStartLocation.X, Math.Max(_DragEndLocation.X, RowHeaderWidth)), Math.Min(_DragStartLocation.Y, Math.Max(_DragEndLocation.Y, row.Top))); |
|||
var height = Math.Abs(Math.Min(_DragEndLocation.Y, row.Bottom - _VScrollBar.Value) - _DragStartLocation.Y); |
|||
var width = Math.Abs(_DragEndLocation.X - _DragStartLocation.X); |
|||
if (_DragEndLocation.Y < row.Top) |
|||
{ |
|||
height -= row.Top - _DragEndLocation.Y; |
|||
} |
|||
if (_DragEndLocation.X < RowHeaderWidth) |
|||
{ |
|||
width -= RowHeaderWidth - _DragEndLocation.X; |
|||
} |
|||
else if(_DragEndLocation.X > TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value) |
|||
{ |
|||
width = TotalDays * DateWidth + RowHeaderWidth - _HScrollBar.Value - _DragStartLocation.X; |
|||
} |
|||
var rect = new RectangleF(start, new SizeF(width, height)); |
|||
graphics.FillRectangle(this.Brushes.SelectionRectangleBackBrush, rect); |
|||
} |
|||
/// <summary>
|
|||
/// 画项的时间范围
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="item"></param>
|
|||
/// <param name="sub"></param>
|
|||
protected virtual void DrawItemTimeRange(Graphics graphics, GanttChartViewItem item, TimeRange sub) |
|||
{ |
|||
var width = sub.Width; |
|||
var right = sub.Left + sub.Width; |
|||
if (right == item.Left + item.Width) |
|||
{ |
|||
width = width - 2; |
|||
if(width < 1) |
|||
{ |
|||
return; |
|||
} |
|||
} |
|||
if (item == _SelectionItem) |
|||
{ |
|||
graphics.FillRectangle(this.Brushes.ItemSelectionSubRangeBackBrush, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight); |
|||
graphics.DrawRectangle(this.Brushes.ItemSelectionSubRangeBackPen, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight); |
|||
} |
|||
else |
|||
{ |
|||
graphics.FillRectangle(this.Brushes.ItemSubRangeBackBrush, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight); |
|||
graphics.DrawRectangle(this.Brushes.ItemSubRangeBackPen, sub.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, width, ItemHeight); |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 画项
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="titleFormat"></param>
|
|||
/// <param name="item"></param>
|
|||
/// <param name="range"></param>
|
|||
protected virtual void DrawItem(Graphics graphics, StringFormat titleFormat, GanttChartViewItem item, RectangleF range) |
|||
{ |
|||
var clip = new RectangleF(range.X, (range.Y < ColumnHeight ? ColumnHeight : range.Y) + 1, range.Width, (range.Y < ColumnHeight ? (range.Height - (ColumnHeight - range.Y)) : range.Height) - 2); |
|||
graphics.SetClip(clip); |
|||
if (item.Ranges != null && item.Ranges.Any()) |
|||
{ |
|||
graphics.FillRectangle(this.Brushes.ItemBackBrush, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight); |
|||
graphics.DrawRectangle(this.Brushes.ItemBackPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight); |
|||
var subs = item.Ranges.OrderBy(r => r.StartTime); |
|||
foreach (var sub in subs) |
|||
{ |
|||
DrawItemTimeRange(graphics, item, sub); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
graphics.FillRectangle(this.Brushes.ItemSubRangeBackBrush, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight); |
|||
graphics.DrawRectangle(this.Brushes.ItemSubRangeBackPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight); |
|||
} |
|||
if (item == _SelectionItem) |
|||
{ |
|||
var textBrush = item.IsWarnning ? this.Brushes.ItemWarnningTextBrush : this.Brushes.ItemSelectionTextBrush; |
|||
graphics.DrawLine(this.Brushes.ItemStartFlagPen, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight / 2, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight); |
|||
graphics.DrawRectangle(this.Brushes.ItemSelectionBorderPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight); |
|||
graphics.DrawString(item.Title, ItemTextFont, textBrush, new RectangleF(item.Left - _HScrollBar.Value + 2, item.Top - _VScrollBar.Value + 1, 0, ItemHeight - 2), titleFormat); |
|||
} |
|||
else if(_SelectionItem != null && SelectionItemSameComparator != null && SelectionItemSameComparator(item, _SelectionItem)) |
|||
{ |
|||
var textBrush = item.IsWarnning ? this.Brushes.ItemWarnningTextBrush : this.Brushes.ItemSelectionTextBrush; |
|||
graphics.DrawLine(this.Brushes.ItemStartFlagPen, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight / 2, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight); |
|||
if (IsShowItemBorder) |
|||
graphics.DrawRectangle(this.Brushes.ItemBorderPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight); |
|||
graphics.DrawString(item.Title, ItemTextFont, textBrush, new RectangleF(item.Left - _HScrollBar.Value + 2, item.Top - _VScrollBar.Value + 1, 0, ItemHeight - 2), titleFormat); |
|||
} |
|||
else |
|||
{ |
|||
var textBrush = item.IsWarnning ? this.Brushes.ItemWarnningTextBrush : this.Brushes.ItemTextBrush; |
|||
graphics.DrawLine(this.Brushes.ItemStartFlagPen, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight / 2, item.Left - _HScrollBar.Value + 1, item.Top - _VScrollBar.Value + ItemHeight); |
|||
if (IsShowItemBorder) |
|||
graphics.DrawRectangle(this.Brushes.ItemBorderPen, item.Left - _HScrollBar.Value, item.Top - _VScrollBar.Value, Math.Max(item.Width - 2, 2), ItemHeight); |
|||
graphics.DrawString(item.Title, ItemTextFont, textBrush, new RectangleF(item.Left - _HScrollBar.Value + 2, item.Top - _VScrollBar.Value + 1, 0, ItemHeight - 2), titleFormat); |
|||
} |
|||
graphics.ResetClip(); |
|||
} |
|||
/// <summary>
|
|||
/// 画行
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="headerFormat"></param>
|
|||
/// <param name="titleFormat"></param>
|
|||
/// <param name="row"></param>
|
|||
/// <param name="range"></param>
|
|||
/// <param name="rowRect"></param>
|
|||
protected virtual void DrawRow(Graphics graphics, StringFormat headerFormat, StringFormat titleFormat, GanttChartViewRow row, RectangleF range, RectangleF rowRect) |
|||
{ |
|||
graphics.SetClip(range); |
|||
var drawY = rowRect.Y + RowSpacing; |
|||
var drawHeight = rowRect.Height - RowSpacing * 2; |
|||
if (drawHeight > (_ContentControl.Height - ColumnHeight) / 4) |
|||
{ |
|||
drawY = Math.Max(rowRect.Y, ColumnHeight); |
|||
drawHeight = Math.Min(rowRect.Bottom - RowSpacing, _ContentControl.Height) - drawY; |
|||
} |
|||
graphics.DrawString(row.Title, RowHeaderTextFont, this.Brushes.RowHeaderTextBrush, new RectangleF(rowRect.X + RowSpacing, drawY, RowHeaderWidth - RowSpacing * 2, drawHeight), headerFormat); |
|||
graphics.ResetClip(); |
|||
if(row.Items != null) |
|||
{ |
|||
var items = row.Items.OrderBy(r=>r.StartTime); |
|||
foreach (var item in items) |
|||
{ |
|||
if (item.Left + item.Width - _HScrollBar.Value > RowHeaderWidth) |
|||
{ |
|||
if (item.Left - _HScrollBar.Value < range.Right) |
|||
{ |
|||
DrawItem(graphics, titleFormat, item, new RectangleF(RowHeaderWidth + 1, rowRect.Y + 1, rowRect.Width - RowHeaderWidth - 2, rowRect.Height - 2)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
graphics.SetClip(range); |
|||
graphics.DrawLine(this.Brushes.GridPen, 0, row.Bottom - _VScrollBar.Value, rowRect.Width, row.Bottom - _VScrollBar.Value); |
|||
if (_SelectionRow == row && IsShowSelectionBorder) |
|||
{ |
|||
var selectionRect = new Rectangle(1, row.Top + 1, (int)(range.Width - 3), (int)(row.Bottom - row.Top - 2)); |
|||
graphics.DrawRectangle(this.Brushes.RowSelectionBorderPen, selectionRect); |
|||
} |
|||
graphics.ResetClip(); |
|||
} |
|||
/// <summary>
|
|||
/// 画所有行
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="bottom"></param>
|
|||
protected virtual void DrawRows(Graphics graphics, int bottom) |
|||
{ |
|||
var range = new RectangleF(0, ColumnHeight, RowHeaderWidth + TotalDays * DateWidth - _HScrollBar.Value, bottom - _VScrollBar.Value + 1); |
|||
graphics.DrawLine(this.Brushes.GridPen, RowHeaderWidth, ColumnDateHeight, range.Width - 1, ColumnDateHeight); |
|||
graphics.SetClip(range); |
|||
graphics.DrawLine(this.Brushes.GridPen, 0, ColumnHeight, range.Width - 1, ColumnHeight); |
|||
if (Rows == null || !Rows.Any()) |
|||
{ |
|||
DrawNonData(graphics, bottom); |
|||
graphics.DrawLine(this.Brushes.GridPen, 0, bottom, range.Width - 1, bottom); |
|||
return; |
|||
} |
|||
graphics.ResetClip(); |
|||
var headerFormat = new StringFormat(); |
|||
headerFormat.Alignment = StringAlignment.Near; |
|||
headerFormat.LineAlignment = StringAlignment.Center; |
|||
var titleFormat = new StringFormat(); |
|||
titleFormat.Alignment = StringAlignment.Near; |
|||
titleFormat.LineAlignment = StringAlignment.Center; |
|||
|
|||
titleFormat.FormatFlags = BlockType == GanttChartViewItemBlockType.Compact ? StringFormatFlags.LineLimit : StringFormatFlags.NoWrap; |
|||
foreach (var row in Rows) |
|||
{ |
|||
if (row.Bottom - _VScrollBar.Value > ColumnHeight) |
|||
{ |
|||
var rowRect = new RectangleF(new PointF(0, row.Top - _VScrollBar.Value), new SizeF(range.Width, row.Bottom - row.Top + 1)); |
|||
if (!range.IntersectsWith(rowRect)) break; |
|||
DrawRow(graphics, headerFormat, titleFormat, row, range, rowRect); |
|||
} |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 画列
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="format"></param>
|
|||
/// <param name="date"></param>
|
|||
/// <param name="range"></param>
|
|||
/// <param name="startX"></param>
|
|||
/// <param name="width"></param>
|
|||
/// <param name="cellHour"></param>
|
|||
protected virtual void DrawColumn(Graphics graphics, StringFormat format, DateTime date, RectangleF range, int startX, int width, int cellHour) |
|||
{ |
|||
var offsetMinutes = (int)(DateSplitTime - DateSplitTime.Date).TotalMinutes % (60 * cellHour); |
|||
var offset = (int)(offsetMinutes / 60f * width); |
|||
startX = startX - offset; |
|||
var dt = date.AddMinutes(-offsetMinutes); |
|||
for (DateTime i = dt; i < dt.AddDays(1); i = i.AddHours(cellHour)) |
|||
{ |
|||
var rectangle = new RectangleF(startX, ColumnDateHeight + 1, 0, ColumnHourHeight - 2); |
|||
if (range.IntersectsWith(rectangle) && (offset != 0 || date.Hour != i.Hour)) |
|||
{ |
|||
graphics.DrawString(i.Hour == 0 ? "0" : i.Hour.ToString("##00"), ColumnDateTextFont, this.Brushes.ColumnHourTextBrush, rectangle, format); |
|||
//graphics.DrawLine(this.Brushes.GridPen, rectangle.X, ColumnDateHeight, rectangle.X, ColumnDateHeight + ColumnHourHeight / 5);
|
|||
graphics.DrawLine(this.Brushes.GridPen, rectangle.X, ColumnDateHeight + ColumnHourHeight / 5 * 4, rectangle.X, ColumnDateHeight + ColumnHourHeight - 1); |
|||
} |
|||
startX += width * cellHour; |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 画列头
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
protected virtual void DrawColumnHeader(Graphics graphics) |
|||
{ |
|||
var range = new RectangleF(new PointF(RowHeaderWidth + 1, 1), new SizeF(TotalDays * DateWidth - 1, _ContentControl.Height - 2)); |
|||
graphics.SetClip(range); |
|||
int cellHour = GetCellHours(); |
|||
var format = new StringFormat(); |
|||
format.Alignment = StringAlignment.Center; |
|||
format.LineAlignment = StringAlignment.Center; |
|||
format.FormatFlags = StringFormatFlags.LineLimit; |
|||
var x = RowHeaderWidth; |
|||
for (var i = StartTime; i <= EndTime; i = i.AddDays(1)) |
|||
{ |
|||
var dx = x - _HScrollBar.Value; |
|||
var rectangle = new RectangleF(dx + 1, 1, DateWidth - 1, ColumnDateHeight - 2); |
|||
if (rectangle.Right > RowHeaderWidth) |
|||
{ |
|||
if (!range.IntersectsWith(rectangle)) |
|||
{ |
|||
x += DateWidth; |
|||
continue; |
|||
} |
|||
graphics.DrawString(i.ToString("yyyy-MM-dd") + " 星期" + ("日一二三四五六"[(int)i.DayOfWeek]), ColumnDateTextFont, this.Brushes.ColumnDateTextBrush, rectangle, format); |
|||
DrawColumn(graphics, format, i, range, (int)rectangle.X - 1, DateWidth / 24, cellHour); |
|||
} |
|||
x += DateWidth; |
|||
} |
|||
graphics.ResetClip(); |
|||
} |
|||
/// <summary>
|
|||
/// 画行头
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="bottom"></param>
|
|||
protected virtual void DrawHeader(Graphics graphics, int bottom) |
|||
{ |
|||
var range = new RectangleF(new PointF(0, 0), new SizeF(RowHeaderWidth + TotalDays * DateWidth, bottom - _VScrollBar.Value)); |
|||
graphics.SetClip(range); |
|||
graphics.DrawLine(this.Brushes.GridPen, range.X, range.Y, range.X + RowHeaderWidth, range.Y + ColumnHeight); |
|||
graphics.DrawString(this.DateTimeShowText, this.ColumnDateTextFont, this.Brushes.ColumnDateTextBrush, |
|||
new Rectangle(0, 0, RowHeaderWidth - RowSpacing, ColumnDateHeight), |
|||
new StringFormat { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Center }); |
|||
graphics.DrawString(this.RowTitleShowText, this.RowHeaderTextFont, this.Brushes.RowHeaderTextBrush, |
|||
new Rectangle(RowSpacing, ColumnDateHeight, RowHeaderWidth - RowSpacing, ColumnHourHeight - RowSpacing), |
|||
new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Far }); |
|||
graphics.ResetClip(); |
|||
} |
|||
/// <summary>
|
|||
/// 画时间线
|
|||
/// </summary>
|
|||
/// <param name="graphics"></param>
|
|||
/// <param name="bottom"></param>
|
|||
protected virtual void DrawTimeLine(Graphics graphics, int bottom) |
|||
{ |
|||
var range = new RectangleF(new PointF(0, 0), new SizeF(RowHeaderWidth + TotalDays * DateWidth, bottom - _VScrollBar.Value)); |
|||
graphics.SetClip(range); |
|||
graphics.DrawRectangle(this.Brushes.GridPen, _ContentControl.DisplayRectangle); |
|||
var x = RowHeaderWidth - 1; |
|||
if(StartTime == DateTime.Today.Add(DateSplitTime - DateSplitTime.Date)) |
|||
{ |
|||
graphics.DrawLine(this.Brushes.CurrentTimeLinePen, x, 0, x, _ContentControl.Height); |
|||
} |
|||
else |
|||
{ |
|||
graphics.DrawLine(this.Brushes.GridPen, x, 0, x, _ContentControl.Height); |
|||
} |
|||
for (var i = StartTime; i <= EndTime; i = i.AddDays(1)) |
|||
{ |
|||
x += DateWidth; |
|||
var dx = x - _HScrollBar.Value; |
|||
if (dx + 1 > RowHeaderWidth) |
|||
{ |
|||
if (dx + 1 > _ContentControl.Width) break; |
|||
if(i.AddDays(1) == DateTime.Today.Add(DateSplitTime - DateSplitTime.Date)) |
|||
{ |
|||
graphics.DrawLine(this.Brushes.CurrentTimeLinePen, dx, 0, dx, _ContentControl.Height); |
|||
} |
|||
else |
|||
{ |
|||
graphics.DrawLine(this.Brushes.GridPen, dx, 0, dx, _ContentControl.Height); |
|||
} |
|||
} |
|||
} |
|||
graphics.ResetClip(); |
|||
} |
|||
/// <summary>
|
|||
/// 计算单元格小时
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
private int GetCellHours() |
|||
{ |
|||
var halfHourWidth = DateWidth / 48; |
|||
int cellHour; |
|||
if (halfHourWidth >= 12) |
|||
{ |
|||
cellHour = 1; |
|||
} |
|||
else if (halfHourWidth >= 6) |
|||
{ |
|||
cellHour = 2; |
|||
} |
|||
else if (halfHourWidth >= 4) |
|||
{ |
|||
cellHour = 3; |
|||
} |
|||
else if (halfHourWidth >= 3) |
|||
{ |
|||
cellHour = 4; |
|||
} |
|||
else if (halfHourWidth >= 2) |
|||
{ |
|||
cellHour = 6; |
|||
} |
|||
else |
|||
{ |
|||
cellHour = 12; |
|||
} |
|||
return cellHour; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,137 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Drawing; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Windows.Forms; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图控件
|
|||
/// </summary>
|
|||
[ToolboxBitmap(typeof(GanttChartView), "GanttChart.GanttChartView.bmp")] |
|||
public partial class GanttChartView: Control |
|||
{ |
|||
#region Private Members
|
|||
private HScrollBar _HScrollBar; |
|||
private VScrollBar _VScrollBar; |
|||
|
|||
private TableLayoutPanel _Table; |
|||
private Control _ContentControl; |
|||
|
|||
private GanttChartBrushes Brushes; |
|||
#endregion
|
|||
|
|||
#region ctor
|
|||
public GanttChartView() |
|||
{ |
|||
_Table = new TableLayoutPanel(); |
|||
_Table.ColumnCount = 2; |
|||
_Table.RowCount = 2; |
|||
_Table.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); |
|||
_Table.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, VScrollWidth)); |
|||
_Table.RowStyles.Add(new RowStyle(SizeType.AutoSize)); |
|||
_Table.RowStyles.Add(new RowStyle(SizeType.Absolute, HScrollHeight)); |
|||
|
|||
_ContentControl = new GanttChartCanvas(); |
|||
_ContentControl.Dock = DockStyle.Fill; |
|||
_ContentControl.Margin = new Padding(0); |
|||
_Table.Controls.Add(_ContentControl, 0, 0); |
|||
|
|||
_HScrollBar = new HScrollBar(); |
|||
_HScrollBar.Value = 0; |
|||
_HScrollBar.Height = HScrollHeight; |
|||
_HScrollBar.SmallChange = 1; |
|||
_HScrollBar.LargeChange = 2; |
|||
//_HScrollBar.Dock = DockStyle.Fill;
|
|||
_HScrollBar.Visible = true; |
|||
_Table.Controls.Add(_HScrollBar, 0, 1); |
|||
|
|||
|
|||
_VScrollBar = new VScrollBar(); |
|||
_VScrollBar.Value = 0; |
|||
_VScrollBar.Width = VScrollWidth; |
|||
_VScrollBar.SmallChange = 1; |
|||
_VScrollBar.LargeChange = 2; |
|||
//_VScrollBar.Dock = DockStyle.Fill;
|
|||
_VScrollBar.Visible = true; |
|||
_Table.Controls.Add(_VScrollBar, 1, 0); |
|||
|
|||
_Table.Dock = DockStyle.Fill; |
|||
Controls.Add(_Table); |
|||
|
|||
InitEvent(); |
|||
} |
|||
|
|||
#endregion
|
|||
/// <summary>
|
|||
/// 调整滚动条
|
|||
/// </summary>
|
|||
private void AdjustScrollbar() |
|||
{ |
|||
var bottom = ItemHeight + RowSpacing * 2; |
|||
if (Rows != null && Rows.Any()) |
|||
{ |
|||
if (StartDate != Rows.StartDate || Rows.IsChanged) |
|||
{ |
|||
ComputeRowsAndItemsSize(); |
|||
Rows.IsChanged = false; |
|||
Rows.StartDate = StartDate; |
|||
} |
|||
var last = Rows.Last(); |
|||
bottom = last.Bottom; |
|||
} |
|||
if (IsFixedRowHeight) |
|||
{ |
|||
var h = ColumnHeight + (Rows?.Count ?? 0) * RowHeight + 200; |
|||
if(h > Height - HScrollHeight) |
|||
{ |
|||
_VScrollBar.Maximum = h - Height + HScrollHeight + 1; |
|||
} |
|||
else |
|||
{ |
|||
_VScrollBar.Maximum = 0; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
_VScrollBar.Maximum = bottom - Height + HScrollHeight + 1 + 200; |
|||
} |
|||
_VScrollBar.Minimum = 0; |
|||
|
|||
_HScrollBar.Maximum = ((int)(EndDate.Date - StartDate.Date).TotalDays + 1) * DateWidth - Width + RowHeaderWidth + VScrollWidth + 1 + 200; |
|||
_HScrollBar.Minimum = 0; |
|||
|
|||
_VScrollBar.Enabled = _VScrollBar.Maximum > 0; |
|||
_HScrollBar.Enabled = _HScrollBar.Maximum > 0; |
|||
} |
|||
/// <summary>
|
|||
/// 重绘
|
|||
/// </summary>
|
|||
public new void Invalidate() |
|||
{ |
|||
base.Invalidate(); |
|||
_ContentControl.Invalidate(); |
|||
} |
|||
/// <summary>
|
|||
/// 销毁
|
|||
/// </summary>
|
|||
/// <param name="disposing"></param>
|
|||
protected override void Dispose(bool disposing) |
|||
{ |
|||
this.Brushes?.Dispose(); |
|||
base.Dispose(disposing); |
|||
} |
|||
class GanttChartCanvas : Control |
|||
{ |
|||
public GanttChartCanvas() |
|||
{ |
|||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true); |
|||
SetStyle(ControlStyles.ResizeRedraw, true); |
|||
SetStyle(ControlStyles.Selectable, true); |
|||
} |
|||
protected override void OnPaintBackground(PaintEventArgs pevent) { } |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
public class GanttChartViewColumn |
|||
{ |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
public class GanttChartViewColumnGroup |
|||
{ |
|||
} |
|||
} |
@ -0,0 +1,42 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图项
|
|||
/// </summary>
|
|||
public class GanttChartViewItem : TimeRange |
|||
{ |
|||
/// <summary>
|
|||
/// 项的时间范围集合
|
|||
/// </summary>
|
|||
public ICollection<TimeRange> Ranges { get; set; } |
|||
/// <summary>
|
|||
/// 标题
|
|||
/// </summary>
|
|||
public string Title { get; set; } |
|||
/// <summary>
|
|||
/// 提示内容
|
|||
/// </summary>
|
|||
public string Tooltip { get; set; } |
|||
/// <summary>
|
|||
/// 顶部位置
|
|||
/// </summary>
|
|||
internal int Top { get; set; } |
|||
/// <summary>
|
|||
/// 文本宽度
|
|||
/// </summary>
|
|||
internal int TextWidth { get; set; } |
|||
/// <summary>
|
|||
/// 数据
|
|||
/// </summary>
|
|||
public object Data { get; set; } |
|||
/// <summary>
|
|||
/// 是否警告
|
|||
/// </summary>
|
|||
public bool IsWarnning { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图项的换行模式
|
|||
/// </summary>
|
|||
public enum GanttChartViewItemBlockType |
|||
{ |
|||
/// <summary>
|
|||
/// 紧凑
|
|||
/// </summary>
|
|||
Compact, |
|||
/// <summary>
|
|||
/// 文字超过换行
|
|||
/// </summary>
|
|||
TextOverBlock, |
|||
/// <summary>
|
|||
/// 强制换行
|
|||
/// </summary>
|
|||
Block, |
|||
/// <summary>
|
|||
/// 回归
|
|||
/// </summary>
|
|||
Return |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 甘特图行
|
|||
/// </summary>
|
|||
public class GanttChartViewRow |
|||
{ |
|||
/// <summary>
|
|||
/// 标题
|
|||
/// </summary>
|
|||
public string Title { get; set; } |
|||
/// <summary>
|
|||
/// 顶部
|
|||
/// </summary>
|
|||
internal int Top { get; set; } |
|||
/// <summary>
|
|||
/// 按钮
|
|||
/// </summary>
|
|||
internal int Bottom { get; set; } |
|||
/// <summary>
|
|||
/// 项集合
|
|||
/// </summary>
|
|||
public List<GanttChartViewItem> Items { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,36 @@ |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
// 有关程序集的一般信息由以下
|
|||
// 控制。更改这些特性值可修改
|
|||
// 与程序集关联的信息。
|
|||
[assembly: AssemblyTitle("GanttChart")] |
|||
[assembly: AssemblyDescription("")] |
|||
[assembly: AssemblyConfiguration("")] |
|||
[assembly: AssemblyCompany("")] |
|||
[assembly: AssemblyProduct("GanttChart")] |
|||
[assembly: AssemblyCopyright("Copyright © 2019")] |
|||
[assembly: AssemblyTrademark("")] |
|||
[assembly: AssemblyCulture("")] |
|||
|
|||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
|||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
|||
//请将此类型的 ComVisible 特性设置为 true。
|
|||
[assembly: ComVisible(false)] |
|||
|
|||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
|||
[assembly: Guid("dea91cb9-1011-4ee7-b8e1-72428f731789")] |
|||
|
|||
// 程序集的版本信息由下列四个值组成:
|
|||
//
|
|||
// 主版本
|
|||
// 次版本
|
|||
// 生成号
|
|||
// 修订号
|
|||
//
|
|||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
|||
//通过使用 "*",如下所示:
|
|||
// [assembly: AssemblyVersion("1.0.*")]
|
|||
[assembly: AssemblyVersion("1.0.0.0")] |
|||
[assembly: AssemblyFileVersion("1.0.0.0")] |
@ -0,0 +1,63 @@ |
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 此代码由工具生成。
|
|||
// 运行时版本:4.0.30319.42000
|
|||
//
|
|||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
|||
// 重新生成代码,这些更改将会丢失。
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
namespace GanttChart.Properties { |
|||
using System; |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
|||
/// </summary>
|
|||
// 此类是由 StronglyTypedResourceBuilder
|
|||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
|||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
|||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
|||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] |
|||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
|||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] |
|||
internal class Resources { |
|||
|
|||
private static global::System.Resources.ResourceManager resourceMan; |
|||
|
|||
private static global::System.Globalization.CultureInfo resourceCulture; |
|||
|
|||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] |
|||
internal Resources() { |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
|||
/// </summary>
|
|||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] |
|||
internal static global::System.Resources.ResourceManager ResourceManager { |
|||
get { |
|||
if (object.ReferenceEquals(resourceMan, null)) { |
|||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GanttChart.Properties.Resources", typeof(Resources).Assembly); |
|||
resourceMan = temp; |
|||
} |
|||
return resourceMan; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 重写当前线程的 CurrentUICulture 属性,对
|
|||
/// 使用此强类型资源类的所有资源查找执行重写。
|
|||
/// </summary>
|
|||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] |
|||
internal static global::System.Globalization.CultureInfo Culture { |
|||
get { |
|||
return resourceCulture; |
|||
} |
|||
set { |
|||
resourceCulture = value; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,117 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<root> |
|||
<!-- |
|||
Microsoft ResX Schema |
|||
|
|||
Version 2.0 |
|||
|
|||
The primary goals of this format is to allow a simple XML format |
|||
that is mostly human readable. The generation and parsing of the |
|||
various data types are done through the TypeConverter classes |
|||
associated with the data types. |
|||
|
|||
Example: |
|||
|
|||
... ado.net/XML headers & schema ... |
|||
<resheader name="resmimetype">text/microsoft-resx</resheader> |
|||
<resheader name="version">2.0</resheader> |
|||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> |
|||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> |
|||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> |
|||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> |
|||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> |
|||
<value>[base64 mime encoded serialized .NET Framework object]</value> |
|||
</data> |
|||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> |
|||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> |
|||
<comment>This is a comment</comment> |
|||
</data> |
|||
|
|||
There are any number of "resheader" rows that contain simple |
|||
name/value pairs. |
|||
|
|||
Each data row contains a name, and value. The row also contains a |
|||
type or mimetype. Type corresponds to a .NET class that support |
|||
text/value conversion through the TypeConverter architecture. |
|||
Classes that don't support this are serialized and stored with the |
|||
mimetype set. |
|||
|
|||
The mimetype is used for serialized objects, and tells the |
|||
ResXResourceReader how to depersist the object. This is currently not |
|||
extensible. For a given mimetype the value must be set accordingly: |
|||
|
|||
Note - application/x-microsoft.net.object.binary.base64 is the format |
|||
that the ResXResourceWriter will generate, however the reader can |
|||
read any of the formats listed below. |
|||
|
|||
mimetype: application/x-microsoft.net.object.binary.base64 |
|||
value : The object must be serialized with |
|||
: System.Serialization.Formatters.Binary.BinaryFormatter |
|||
: and then encoded with base64 encoding. |
|||
|
|||
mimetype: application/x-microsoft.net.object.soap.base64 |
|||
value : The object must be serialized with |
|||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter |
|||
: and then encoded with base64 encoding. |
|||
|
|||
mimetype: application/x-microsoft.net.object.bytearray.base64 |
|||
value : The object must be serialized into a byte array |
|||
: using a System.ComponentModel.TypeConverter |
|||
: and then encoded with base64 encoding. |
|||
--> |
|||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> |
|||
<xsd:element name="root" msdata:IsDataSet="true"> |
|||
<xsd:complexType> |
|||
<xsd:choice maxOccurs="unbounded"> |
|||
<xsd:element name="metadata"> |
|||
<xsd:complexType> |
|||
<xsd:sequence> |
|||
<xsd:element name="value" type="xsd:string" minOccurs="0" /> |
|||
</xsd:sequence> |
|||
<xsd:attribute name="name" type="xsd:string" /> |
|||
<xsd:attribute name="type" type="xsd:string" /> |
|||
<xsd:attribute name="mimetype" type="xsd:string" /> |
|||
</xsd:complexType> |
|||
</xsd:element> |
|||
<xsd:element name="assembly"> |
|||
<xsd:complexType> |
|||
<xsd:attribute name="alias" type="xsd:string" /> |
|||
<xsd:attribute name="name" type="xsd:string" /> |
|||
</xsd:complexType> |
|||
</xsd:element> |
|||
<xsd:element name="data"> |
|||
<xsd:complexType> |
|||
<xsd:sequence> |
|||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
|||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> |
|||
</xsd:sequence> |
|||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> |
|||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> |
|||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> |
|||
</xsd:complexType> |
|||
</xsd:element> |
|||
<xsd:element name="resheader"> |
|||
<xsd:complexType> |
|||
<xsd:sequence> |
|||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
|||
</xsd:sequence> |
|||
<xsd:attribute name="name" type="xsd:string" use="required" /> |
|||
</xsd:complexType> |
|||
</xsd:element> |
|||
</xsd:choice> |
|||
</xsd:complexType> |
|||
</xsd:element> |
|||
</xsd:schema> |
|||
<resheader name="resmimetype"> |
|||
<value>text/microsoft-resx</value> |
|||
</resheader> |
|||
<resheader name="version"> |
|||
<value>2.0</value> |
|||
</resheader> |
|||
<resheader name="reader"> |
|||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
|||
</resheader> |
|||
<resheader name="writer"> |
|||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
|||
</resheader> |
|||
</root> |
@ -0,0 +1,26 @@ |
|||
//------------------------------------------------------------------------------
|
|||
// <auto-generated>
|
|||
// 此代码由工具生成。
|
|||
// 运行时版本:4.0.30319.42000
|
|||
//
|
|||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
|||
// 重新生成代码,这些更改将会丢失。
|
|||
// </auto-generated>
|
|||
//------------------------------------------------------------------------------
|
|||
|
|||
namespace GanttChart.Properties { |
|||
|
|||
|
|||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] |
|||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")] |
|||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { |
|||
|
|||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); |
|||
|
|||
public static Settings Default { |
|||
get { |
|||
return defaultInstance; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,7 @@ |
|||
<?xml version='1.0' encoding='utf-8'?> |
|||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"> |
|||
<Profiles> |
|||
<Profile Name="(Default)" /> |
|||
</Profiles> |
|||
<Settings /> |
|||
</SettingsFile> |
@ -0,0 +1,30 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace GanttChart |
|||
{ |
|||
/// <summary>
|
|||
/// 时间范围
|
|||
/// </summary>
|
|||
public class TimeRange |
|||
{ |
|||
/// <summary>
|
|||
/// 开始时间
|
|||
/// </summary>
|
|||
public DateTime StartTime { get; set; } |
|||
/// <summary>
|
|||
/// 结束时间
|
|||
/// </summary>
|
|||
public DateTime EndTime { get; set; } |
|||
/// <summary>
|
|||
/// 左边
|
|||
/// </summary>
|
|||
internal int Left { get; set; } |
|||
/// <summary>
|
|||
/// 宽度
|
|||
/// </summary>
|
|||
internal int Width { get; set; } |
|||
} |
|||
} |
Loading…
Reference in new issue