init: 导入项目到 meswork Gitea

This commit is contained in:
XingCheng3
2026-05-29 10:07:05 +08:00
commit ad9a4106fb
3582 changed files with 460312 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
namespace Braincase.GanttChart
{
partial class Chart
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// Chart
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "Chart";
this.Size = new System.Drawing.Size(469, 439);
this.ResumeLayout(false);
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
<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" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</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" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,410 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
namespace Braincase.GanttChart
{
/// <summary>
/// Passive data class holding schedule information
/// </summary>
[Serializable]
public class Task
{
/// <summary>
/// Initialize a new task to hold schedule information
/// </summary>
public Task()
{
Complete = 0.0f;
Start = 0;
End = 1;
Duration = 1;
Slack = 0;
TagValue = "1";
BackFill = Brushes.MediumSlateBlue;
}
/// <summary>
/// Get or set Task background color
/// </summary>
public Brush BackFill { get; set; }
/// <summary>
/// Get or set the Name of this Task
/// </summary>
public string Name { get; set; }
/// <summary>
/// Indicate whether this task is collapsed such that sub tasks are hidden from view. Only groups can be collasped.
/// </summary>
public bool IsCollapsed { get; set; }
/// <summary>
/// Get or set the pecentage complete of this task, expressed in float between 0.0 and 1.0f.
/// </summary>
public float Complete { get; internal set; }
public string ID { get; internal set; }
/// <summary>
/// Task类型 1:工艺路径规划2零件是否可见3机器人4信号点
/// </summary>
public int Type { get; internal set; }
/// <summary>
/// 变量代码
/// </summary>
public string TagID { get; internal set; }
/// <summary>
/// 变量值
/// </summary>
public string TagValue { get; internal set; }
/// <summary>
/// 变量值
/// </summary>
public int TagFrom { get; internal set; }
/// <summary>
/// 变量值
/// </summary>
public string OpName { get; internal set; }
/// <summary>
/// 拷贝变量值
/// </summary>
public string TagIDCopyFrom { get; internal set; }
/// <summary>
/// 模型代码
/// </summary>
public int ModelCode { get; internal set; }
/// <summary>
/// 模型是否可见
/// </summary>
public int Visible { get; internal set; }
/// <summary>
/// 机器人脚本
/// </summary>
public string ScriptText { get; internal set; }
/// <summary>
/// Get the start time of this Task relative to the project start
/// </summary>
public float Start { get; internal set; }
/// <summary>
/// Get the end time of this Task relative to the project start
/// </summary>
public float End { get; internal set; }
/// <summary>
/// Get the duration of this Task
/// </summary>
public float Duration { get; internal set; }
/// <summary>
/// Get the amount of slack (free float)
/// </summary>
public float Slack { get; internal set; }
/// <summary>
/// Convert this Task to a descriptive string
/// </summary>
/// <returns></returns>
public override string ToString()
{
// return string.Format("[Name = {0}, Start = {1}, End = {2}, Duration = {3}, Complete = {4}, TagID = {5}, TagValue = {6}, ModelCode = {7}]", Name, Start, End, Duration, Complete, TagID, TagValue, ModelCode);
return string.Format("[ID = {0}, TagID = {1},Name = {2}, TagValue = {3},StartTime = {4}, KeepTime = {5},EndTime = {6}]", ID, TagID, Name, TagValue, Start, Duration, End);
}
}
/// <summary>
/// Time scale in which the time units represent
/// </summary>
public enum TimeScale
{
/// <summary>
/// Unit time in Days
/// </summary>
Day,
/// <summary>
/// Unit time in Weeks
/// </summary>
Week,
/// <summary>
/// Unit time in Others
/// </summary>
Other
}
/// <summary>
/// ProjectManager interface
/// </summary>
/// <typeparam name="T">Task class type</typeparam>
/// <typeparam name="R">Resource class type</typeparam>
public interface IProjectManager<T, R>
where T : Task
where R : class
{
/// <summary>
/// Add task to project manager
/// </summary>
/// <param name="task"></param>
void Add(T task);
/// <summary>
/// Delete task from project manager
/// </summary>
/// <param name="task"></param>
void Delete(T task);
/// <summary>
/// Group the member task under the group task. Group task cannot have relations.
/// </summary>
/// <param name="group"></param>
/// <param name="member"></param>
void Group(T group, T member);
/// <summary>
/// Ungroup member task from group task. If there are no more task under group, group will become a normal task.
/// </summary>
/// <param name="group"></param>
/// <param name="member"></param>
void Ungroup(T group, T member);
/// <summary>
/// Split the specified task into consecutive parts part1 and part2.
/// </summary>
/// <param name="task">The regular task to split which has duration of at least 2 to make two parts of 1 time unit duration each.</param>
/// <param name="part1">New Task part (1) of the split task, with the start time of the original task and the specified duration value.</param>
/// <param name="part2">New Task part (2) of the split task, starting 1 time unit after part (1) ends and having the remaining of the duration of the origina task.</param>
/// <param name="duration">The duration of part (1) will be set to the specified duration value but will also be adjusted to approperiate value if necessary.</param>
void Split(T task, T part1, T part2, float duration);
/// <summary>
/// Split the specified part and obtain another part from it.
/// </summary>
/// <param name="part">The task part to split which has duration of at least 2 to make two parts of 1 time unit duration each. Its duration will be set to the specified duration value.</param>
/// <param name="another">New Task part of the original part, starting 1 time unit after it ends and having the remaining of the duration of the original part.</param>
/// <param name="duration">The duration of part (1) will be set to the specified duration value but will also be adjusted to approperiate value if necessary.</param>
void Split(T part, T another, float duration);
/// <summary>
/// Join part1 and part2 in a split task into a single part represented by part1, and part2 will be deleted from the ProjectManager.
/// The resulting part will have a duration total of the two parts. Schedule of other parts will be packed according to direction of join.
/// If the join will result in only one part remaining, the split task will merge instead.
/// </summary>
/// <param name="part1">The part to keep in the ProjectManager after the join completes successfully.</param>
/// <param name="part2">The part to join into part1 and be deleted afterwards from the ProjectManager.</param>
void Join(T part1, T part2);
/// <summary>
/// Merge all the parts of the splitted task back into one task, having duration equal to sum of total duration of individual task parts, and aggregating the resources onto the resulting task.
/// </summary>
/// <param name="split">The split Task to merge</param>
void Merge(T split);
/// <summary>
/// Get the parts of the split task
/// </summary>
/// <param name="split"></param>
/// <returns></returns>
IEnumerable<T> PartsOf(T split);
/// <summary>
/// Get the split task that the specified part belogs to.
/// </summary>
/// <param name="part"></param>
/// <returns></returns>
T SplitTaskOf(T part);
/// <summary>
/// Get whether the specified task is a split task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
bool IsSplit(T task);
/// <summary>
/// Get whether the specified task is a part of a split task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
bool IsPart(T task);
/// <summary>
/// Ungroup all member task under the specfied group task. The specified group task will become a normal task.
/// </summary>
/// <param name="group"></param>
void Ungroup(T group);
/// <summary>
/// Move the specified task by offset positions in the task enumeration
/// </summary>
/// <param name="task"></param>
/// <param name="offset"></param>
void Move(T task, int offset);
/// <summary>
/// Set a relation between the precedent and dependant task
/// </summary>
/// <param name="precedent"></param>
/// <param name="dependant"></param>
void Relate(T precedent, T dependant);
/// <summary>
/// Unset the relation between the precedent and dependant task, if any.
/// </summary>
/// <param name="precedent"></param>
/// <param name="dependant"></param>
void Unrelate(T precedent, T dependant);
/// <summary>
/// Remove all dependant task from specified precedent task
/// </summary>
/// <param name="precedent"></param>
void Unrelate(T precedent);
/// <summary>
/// Enumerate through all tasks that is a precedent, having dependants.
/// </summary>
IEnumerable<T> Precedents { get; }
/// <summary>
/// Enumerate through all the tasks in the ProjectManager.
/// If there are no change to groups and no add/delete tasks, the order between consecutive calls is preserved.
/// </summary>
IEnumerable<T> Tasks { get; }
/// <summary>
/// Set the start time of the specified task.
/// </summary>
/// <param name="task"></param>
/// <param name="start">Number of timescale units after ProjectManager.Start</param>
void SetStart(T task, float start);
/// <summary>
/// Set the end time of the specified task. Duration is automatically adjusted to satisfy.
/// </summary>
/// <param name="task"></param>
/// <param name="end">Number of timescale units after ProjectManager.Start</param>
void SetEnd(T task, float end);
/// <summary>
/// Set the duration of the specified task from start to end.
/// </summary>
/// <param name="task"></param>
/// <param name="duration">Number of timescale units between ProjectManager.Start</param>
void SetDuration(T task, float duration);
/// <summary>
/// Set the percentage complete of the specified task from 0.0f to 1.0f.
/// No effect on group tasks as they will get the aggregated percentage complete of all child tasks
/// </summary>
/// <param name="task"></param>
/// <param name="complete"></param>
void SetComplete(T task, float complete);
/// <summary>
/// Set whether to collapse the specified group task. No effect on regular tasks.
/// </summary>
/// <param name="group"></param>
/// <param name="collasped"></param>
void SetCollapse(T group, bool collasped);
/// <summary>
/// Set the "now" time. Its value is the number of timescale units after the start time.
/// </summary>
int Now { get; }
/// <summary>
/// Set the start date of the project.
/// </summary>
DateTime Start { get; set; }
/// <summary>
/// Get the zero-based index of the specified task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
int IndexOf(T task);
/// <summary>
/// Enumerate through parent group and grandparent groups of the specified task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
IEnumerable<T> AncestorsOf(T task);
/// <summary>
/// Enumerate through all the children and grandchildren of the specified group
/// </summary>
/// <param name="group"></param>
/// <returns></returns>
IEnumerable<T> DecendantsOf(T group);
/// <summary>
/// Enumerate through all the direct children of the specified group
/// </summary>
/// <param name="group"></param>
/// <returns></returns>
IEnumerable<T> ChildrenOf(T group);
/// <summary>
/// Enumerate through all the direct precedents and indirect precedents of the specified task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
IEnumerable<T> PrecedentsOf(T task);
/// <summary>
/// Enumerate through all the direct dependants and indirect dependants of the specified task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
IEnumerable<T> DependantsOf(T task);
/// <summary>
/// Enumerate through all the direct precedents of the specified task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
IEnumerable<T> DirectPrecedentsOf(T task);
/// <summary>
/// Enumerate through all the direct dependants of the specified task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
IEnumerable<T> DirectDependantsOf(T task);
/// <summary>
/// Enumerate through all the critical paths. Each path is an enumerable of tasks, starting from the final task of each path.
/// </summary>
IEnumerable<IEnumerable<T>> CriticalPaths { get; }
/// <summary>
/// Get the parent group of the specified task
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
T ParentOf(T task);
/// <summary>
/// Get whether the specified task is a group
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
bool IsGroup(T task);
/// <summary>
/// Get whether the specified task is a member
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
bool IsMember(T task);
/// <summary>
/// Get whether the specified task has relations, either has dependants or has precedents connecting to it.
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
bool HasRelations(T task);
/// <summary>
/// Assign the specified resource to the specified task
/// </summary>
/// <param name="task"></param>
/// <param name="resource"></param>
void Assign(T task, R resource);
/// <summary>
/// Unassign the specified resource from the specfied task
/// </summary>
/// <param name="task"></param>
/// <param name="resource"></param>
void Unassign(T task, R resource);
/// <summary>
/// Unassign all resources from the specified task
/// </summary>
/// <param name="task"></param>
void Unassign(T task);
/// <summary>
/// Unassign the specified resource from all tasks that has this resource assigned
/// </summary>
/// <param name="resource"></param>
void Unassign(R resource);
/// <summary>
/// Enumerate through all the resources that has been assigned to some task.
/// </summary>
IEnumerable<R> Resources { get; }
/// <summary>
/// Enumerate through all the resources that has been assigned to the specified task.
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
IEnumerable<R> ResourcesOf(T task);
/// <summary>
/// Enumerate through all the tasks that has the specified resource assigned to it.
/// </summary>
/// <param name="resource"></param>
/// <returns></returns>
IEnumerable<T> TasksOf(R resource);
}
}

View File

@@ -0,0 +1,216 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Braincase.GanttChart
{
/// <summary>
/// 绘制播放滑动条
/// </summary>
public partial class Chart
{
public enum ControlState//按钮状态
{
Normal,
Hover,
Pressed,
Focused,
}
private ControlState _controlState = ControlState.Normal;
private ControlState MouseState
{
get { return _controlState; }
set
{
if (_controlState != value)
{
_controlState = value;
base.Invalidate();
}
}
}
private bool isMouseDown = false;
/// <summary>
/// 确定拖拽范围
/// </summary>
RectangleF PlayMaskRectDragDrop;
private int _minValue = 0;
private int _maxValue = 100;
private int _currValue = 0;
private int offset = 0;//轨道距离两头的余量.
private Size _sliderSize = new Size(1, 20);//滑块大小
public int Value
{
get { return this._currValue; }
set
{
this._currValue = value;
}
}
/// <summary>
/// Occurs when a Task is being dragged by the mouse
/// </summary>
public event EventHandler<MouseEventArgs> PlaySliderMouseDrag = null;
private void OnMouseMove_PlaySlider(MouseEventArgs e)
{
if (!this.isMouseDown)
{
this.MouseState = this.IsInSliderArea(e.Location) ? ControlState.Hover : this.MouseState = ControlState.Normal;
}
else
{
if (e.Button == MouseButtons.Left)
{
this.MouseState = ControlState.Pressed;
this.ChangeValue(e.Location);
PlaySliderMouseDrag(this, e);
//OnPlaySliderMouseDrop
}
}
}
private void OnMouseDown_PlaySlider(MouseEventArgs e)
{
base.Focus();
if (e.Button == MouseButtons.Left)
{
if (this.IsInSliderArea(e.Location))//滑块内.
{
this.isMouseDown = true;
this.MouseState = ControlState.Pressed;
}
}
}
private void OnMouseUp_PlaySlider(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left )
{
this.isMouseDown = false;
this.MouseState = this.IsInSliderArea(e.Location) ? ControlState.Hover : ControlState.Normal;
}
}
protected override void OnMouseLeave(EventArgs e)
{
if (!this.isMouseDown)
{
this.MouseState = ControlState.Normal;
}
base.OnMouseLeave(e);
}
protected override void OnMouseCaptureChanged(EventArgs e)
{
if (!base.Capture)//未捕获鼠标
{
isMouseDown = false;
}
base.OnMouseCaptureChanged(e);
}
//单击或滑动改变值
private void ChangeValue(Point mouse )
{
//_mProject.NowIndex
// int NowIndex;
var point = _mViewport.DeviceToWorldCoord(mouse);
_maxValue = (int)_mProject.MaxPlayLenth;;
//if (point.X <= this.ClientRectangle.X + offset + this._sliderSize.Width / 2f)
if (point.X <= _minValue + offset + this._sliderSize.Width / 2f)
{
this.Value = this._minValue;
return;
}
//if (point.X >= this.ClientRectangle.Right - offset - this._sliderSize.Width / 2f)
if (point.X >= _maxValue - offset - this._sliderSize.Width / 2f)
{
this.Value = this._maxValue;
return;
}
float len = point.X - this._sliderSize.Width / 2f - offset;
var percent = len / (_maxValue - this._sliderSize.Width - 2 * offset);
//var percent = len / (this.ClientRectangle.Width - this._sliderSize.Width - 2 * offset);
var v = this._minValue + (int)((this._maxValue - this._minValue) * percent);
if (v > this._maxValue) { v = this._maxValue; }
if (v < this._minValue) { v = this._minValue; }
this.Value = v;
_mProject.NowIndexXf = v;
_mProject.NowIndex = (int)(_mProject.AllCountFrame* percent);
}
protected virtual void OnPlaySliderMouseDrop(TaskDragDropEventArgs e)
{
this.Invalidate();
}
//鼠标落点是否在滑块内
private bool IsInSliderArea(Point point)
{
var chartcoord = _mViewport.DeviceToWorldCoord(point);
return PlayMaskRectDragDrop.Contains(chartcoord);
}
/// <summary>
/// 绘制播放线
/// </summary>
/// <param name="graphics"></param>
private void OnPaint_PlaySlider(Graphics graphics)
{
//正常播放
DrawPlayLine(graphics);
}
/// <summary>
/// 绘制播放线
/// </summary>
/// <param name="graphics"></param>
private void DrawPlayLine(Graphics graphics)
{
try
{
if (float.NaN == _mProject.NowIndexXf) return;
float xf1 = _mProject.NowIndexXf;
Pen pen = new Pen(Color.Red);
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
pen.Width = 1;
graphics.DrawLine(pen, new PointF(xf1, _mViewport.Y), new PointF(xf1, _mViewport.Rectangle.Bottom));
Color color = System.Drawing.Color.FromArgb(((int)(((byte)(34)))), ((int)(((byte)(54)))), ((int)(((byte)(82)))));
Brush brushes = new SolidBrush(color);
PointF[] point = new PointF[3];
float h0 = 6f;
PlayMaskRectDragDrop = new Rectangle((int)(xf1 - h0), (int)_mViewport.Y, (int)(2 * h0), (int)(_mViewport.Y + 2 * h0));
point[0] = new PointF(xf1 - h0, _mViewport.Y);
point[1] = new PointF(xf1 + h0, _mViewport.Y);
point[2] = new PointF(xf1, _mViewport.Y + 2.0f * h0);
graphics.FillPolygon(brushes, point);
}
catch
{
}
//graphics.DrawRectangle(new Pen(Color.Red), PlayMaskRectDragDrop);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,494 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Braincase.GanttChart
{
/// <summary>
/// IViewport moves in world coordinate and projects models to device coordinate space
/// </summary>
public interface IViewport
{
/// <summary>
/// Get the projection matrix to transform world coordinates to device coordinates
/// </summary>
Matrix Projection { get; }
/// <summary>
/// Get the rectangle boundary in world coordinates to be captured and projected onto viewport
/// </summary>
RectangleF Rectangle { get; }
/// <summary>
/// Request viewport to recalculate its get properties.
/// </summary>
void Resize();
/// <summary>
/// Convert device coordinates to world coordinates
/// </summary>
/// <param name="screencoord"></param>
/// <returns></returns>
PointF DeviceToWorldCoord(Point screencoord);
/// <summary>
/// Convert device coordinates to world coordinates
/// </summary>
/// <param name="screencoord"></param>
/// <returns></returns>
PointF DeviceToWorldCoord(PointF screencoord);
/// <summary>
/// Convert world coordinates to device coordinates
/// </summary>
/// <param name="worldcoord"></param>
/// <returns></returns>
PointF WorldToDeviceCoord(PointF worldcoord);
/// <summary>
/// Get or set the world height
/// </summary>
float WorldHeight { get; set; }
/// <summary>
/// Get or set the world width
/// </summary>
float WorldWidth { get; set; }
/// <summary>
/// Get or set the X world-coordinate of the position of the viewport.
/// This is also the same as the IViewport.Rectangle.Left.
/// </summary>
float X { get; set; }
/// <summary>
/// Get or set the Y world-coordinate of the position of the viewport.
/// This is also the same as the IViewport.Rectangle.Top.
/// </summary>
float Y { get; set; }
}
/// <summary>
/// IViewport for printing to file
/// </summary>
class PrintViewport : IViewport
{
public PrintViewport(Graphics graphics,
float worldWidth, float worldHeight,
int deviceWidth, int deviceHeight,
int marginLeft, int marginTop)
{
WorldWidth = worldWidth;
WorldHeight = worldHeight;
_mDeviceWidth = deviceWidth;
_mDeviceHeight = deviceHeight;
_mMarginTop = marginTop;
_mMarginLeft = marginLeft;
}
/// <summary>
/// Get or set viewport X world coordinate
/// </summary>
public float X { get; set; }
/// <summary>
/// Get or set viewport Y world coordinate
/// </summary>
public float Y { get; set; }
/// <summary>
/// Get or set scaling factor between 0.0f and 1.0f (obviously, scale of zero would mean you can't see anything)
/// </summary>
public float Scale { get { return _mScale; } set { _mScale = value; } }
/// <summary>
/// Get or set width of the world
/// </summary>
public float WorldWidth { get; set; }
/// <summary>
/// Get or set height of the world
/// </summary>
public float WorldHeight { get; set; }
/// <summary>
/// Get the projection matrix for transforming models into viewport
/// </summary>
public Matrix Projection
{
get
{
Matrix matrix = new Matrix();
matrix.Translate(this._mMarginLeft, this._mMarginTop);
matrix.Scale(_mScale, _mScale);
matrix.Translate(-this.X, -this.Y);
return matrix;
}
}
/// <summary>
/// Get the rectangle bounds of the viewport in world coordinate
/// </summary>
public RectangleF Rectangle
{
get { return new RectangleF(this.X, this.Y, _mDeviceWidth / _mScale, _mDeviceHeight / _mScale); }
}
/// <summary>
/// Resize the viewport, recalculating and correcting dimensions
/// </summary>
public void Resize()
{
}
/// <summary>
/// Convert view coordinates to world coordinate
/// </summary>
/// <param name="screencoord"></param>
/// <returns></returns>
public PointF DeviceToWorldCoord(Point screencoord)
{
return new PointF(screencoord.X + X, screencoord.Y + Y);
}
/// <summary>
/// Convert view coordinates to world coordinate
/// </summary>
/// <param name="screencoord"></param>
/// <returns></returns>
public PointF DeviceToWorldCoord(PointF screencoord)
{
return new PointF(screencoord.X + X, screencoord.Y + Y);
}
/// <summary>
/// Convert world coordinates to view coordinate
/// </summary>
/// <param name="worldcoord"></param>
/// <returns></returns>
public PointF WorldToDeviceCoord(PointF worldcoord)
{
return new PointF(worldcoord.X - X, worldcoord.Y - Y);
}
int _mDeviceWidth, _mDeviceHeight;
int _mMarginLeft, _mMarginTop;
float _mScale = 1.0f;
}
/// <summary>
/// An IViewport that is placed over a world coordinate system and provides methods to transform between world and view coordinates
/// </summary>
class ControlViewport : IViewport
{
/// <summary>
/// Construct a Viewport
/// </summary>
/// <param name="view"></param>
public ControlViewport(Control view)
{
_mDevice = view;
_mhScroll = new HScrollBar();
_mvScroll = new VScrollBar();
_mScrollHolePatch = new UserControl();
WorldWidth = view.Width;
WorldHeight = view.Height;
_mDevice.Controls.Add(_mhScroll);
_mDevice.Controls.Add(_mvScroll);
_mDevice.Controls.Add(_mScrollHolePatch);
_mhScroll.Scroll += (s, e) => X = e.NewValue;
_mvScroll.Scroll += (s, e) => Y = e.NewValue;
_mDevice.Resize += (s, e) => this.Resize();
_mDevice.MouseWheel += (s, e) => Y -= e.Delta > 0 ? WheelDelta : -WheelDelta;
WheelDelta = _mvScroll.LargeChange;
_RecalculateMatrix();
_RecalculateRectangle();
}
/// <summary>
/// Identity Matrix
/// </summary>
public static readonly Matrix Identity = new Matrix(1, 0, 0, 1, 0, 0);
/// <summary>
/// Get or set the number of pixels to scroll on each click of the mouse
/// </summary>
public int WheelDelta { get; set; }
/// <summary>
/// Get the Rectangle area in world coordinates where the Viewport is currently viewing over
/// </summary>
public RectangleF Rectangle
{
get
{
return _mRectangle;
}
}
/// <summary>
/// Get the projection transformation matrix required for drawing models in the world projected into view
/// </summary>
public Matrix Projection
{
get
{
return _mMatrix;
}
}
/// <summary>
/// Resize the Viewport according to the view control and world dimensions, which ever larger and add scrollbars where approperiate
/// </summary>
public void Resize()
{
if (WorldWidth <= _mDevice.Width)
{
_mhScroll.Hide();
}
else
{
_mhScroll.Show();
_mhScroll.Maximum = (int)(WorldWidth - _mDevice.Width);
_mhScroll.Dock = DockStyle.None;
_mhScroll.Location = new Point(0, _mDevice.Height - _mhScroll.Height);
_mhScroll.Width = _mDevice.Width - _mvScroll.Width;
}
if (WorldHeight <= _mDevice.Height)
{
_mvScroll.Hide();
}
else
{
_mvScroll.Show();
_mvScroll.Maximum = (int)(WorldHeight - _mDevice.Height);
_mvScroll.Dock = DockStyle.None;
_mvScroll.Location = new Point(_mDevice.Width - _mvScroll.Width, 0);
_mvScroll.Height = _mDevice.Height - _mhScroll.Height;
}
_mScrollHolePatch.Location = new Point(_mhScroll.Right, _mvScroll.Bottom);
_mScrollHolePatch.Size = new Size(_mvScroll.Width, _mhScroll.Height);
_RecalculateRectangle();
_RecalculateMatrix();
_mDevice.Invalidate();
}
/// <summary>
/// Convert view coordinates to world coordinates
/// </summary>
/// <param name="screencoord"></param>
/// <returns></returns>
public PointF DeviceToWorldCoord(Point screencoord)
{
return new PointF(screencoord.X + X, screencoord.Y + Y);
}
/// <summary>
/// Convert view coordinates to world coordinates
/// </summary>
/// <param name="screencoord"></param>
/// <returns></returns>
public PointF DeviceToWorldCoord(PointF screencoord)
{
return new PointF(screencoord.X + X, screencoord.Y + Y);
}
/// <summary>
/// Convert world coordinates to view coordinates
/// </summary>
/// <param name="worldcoord"></param>
/// <returns></returns>
public PointF WorldToDeviceCoord(PointF worldcoord)
{
return new PointF(worldcoord.X - X, worldcoord.Y - Y);
}
/// <summary>
/// Get or set the world width
/// </summary>
public float WorldWidth
{
get { return _mWorldWidth; }
set
{
if (!value.Equals(_mWorldWidth))
{
if (value < _mDevice.Width) value = _mDevice.Width;
_mWorldWidth = value;
Resize();
}
}
}
/// <summary>
/// Get or set the world height
/// </summary>
public float WorldHeight
{
get { return _mWorldHeight; }
set
{
if (!value.Equals(_mWorldHeight))
{
if (value < _mDevice.Height) value = _mDevice.Height;
_mWorldHeight = value;
Resize();
}
}
}
/// <summary>
/// Get or set the world X coordinate of the Viewport location, represented by the top left corner of the Viewport Rectangle
/// </summary>
public float X
{
get { return _mhScroll.Value; }
set
{
if (!((int)value).Equals(_mhScroll.Value))
{
if (value > _mhScroll.Maximum) value = _mhScroll.Maximum;
else if (value < 0) value = 0;
_mhScroll.Value = (int)value;
_RecalculateRectangle();
_RecalculateMatrix();
_mDevice.Invalidate();
}
}
}
/// <summary>
/// Get or set the wordl Y coordinate of the Viewport location, represented by the top left corner of the Viewport Rectangle
/// </summary>
public float Y
{
get { return _mvScroll.Value; }
set
{
if (!((int)value).Equals(_mvScroll.Value))
{
if (value > _mvScroll.Maximum) value = _mvScroll.Maximum;
else if (value < 0) value = 0;
_mvScroll.Value = (int)value;
_RecalculateRectangle();
_RecalculateMatrix();
_mDevice.Invalidate();
}
}
}
private void _RecalculateRectangle()
{
_mRectangle = new RectangleF(X, Y, _mDevice.Width, _mDevice.Height);
}
private void _RecalculateMatrix()
{
_mMatrix = new Matrix();
_mMatrix.Translate(-X, -Y);
}
Control _mDevice;
HScrollBar _mhScroll;
VScrollBar _mvScroll;
UserControl _mScrollHolePatch;
RectangleF _mRectangle = RectangleF.Empty;
Matrix _mMatrix = new Matrix();
float _mWorldHeight, _mWorldWidth;
}
/// <summary>
/// IViewport for printing to image. The full chart in the world is printed as-is.
/// </summary>
class ImageViewport : IViewport
{
private float _mScale;
public ImageViewport(float scale, float worldWidth, float worldHeight)
{
_mScale = scale;
WorldWidth = worldWidth;
WorldHeight = worldHeight;
}
/// <summary>
/// Get the projection matrix to transform world coordinates to device coordinates
/// </summary>
public Matrix Projection
{
get
{
Matrix projection = new Matrix();
projection.Scale(_mScale, _mScale);
return projection;
}
}
/// <summary>
/// The device rectangle boundary in the world to capture and project onto device is the same rectangle of the world for ImageViewport
/// So that the entire world is projected onto the ImageViewport
/// </summary>
public RectangleF Rectangle
{
get
{
return new RectangleF(0, 0, this.WorldWidth, this.WorldHeight);
}
}
public void Resize()
{
}
/// <summary>
/// The device and world coordinates are the same for ImageViewport
/// </summary>
public PointF DeviceToWorldCoord(Point screencoord)
{
return screencoord;
}
/// <summary>
/// The device and world coordinates are the same for ImageViewport
/// </summary>
public PointF DeviceToWorldCoord(PointF screencoord)
{
return screencoord;
}
/// <summary>
/// The device and world coordinates are the same for ImageViewport
/// </summary>
public PointF WorldToDeviceCoord(PointF worldcoord)
{
return worldcoord;
}
/// <summary>
/// Get or set the world height
/// </summary>
public float WorldHeight { get; set; }
/// <summary>
/// Get or set the world width
/// </summary>
public float WorldWidth { get; set; }
/// <summary>
/// No effect for ImageViewport. X and Y world-coordinate offset is always at (0,0).
/// </summary>
public float X { get; set; }
/// <summary>
/// No effect for ImageViewport. X and Y world-coordinate offset is always at (0,0).
/// </summary>
public float Y { get; set; }
}
}