using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.Configuration.Assemblies;
using System.Threading;
using System.Xml.Serialization;
using System.Xml;
using CategoryTheory;
using MathGraph;
namespace DiagramUI
{
/// <summary>
/// The associated with Arrow control
/// </summary>
[Serializable()]
public class ArrowLabel : NamedComponent, ISerializable, IArrowLabel
{
/// <summary>
/// Width
/// </summary>
const int width = 40;
/// <summary>
/// Height
/// </summary>
const int height = 40;
/// <summary>
/// Height of caption
/// </summary>
const int captionHeight = 20;
/// <summary>
/// The base triangle for arrow drawing
/// </summary>
private static int[] triangle = new int[]{0, 0, -10, 4, -10, -4};
/// <summary>
/// The label of source object
/// </summary>
private IObjectLabel source;
/// <summary>
/// The label of target object
/// </summary>
private IObjectLabel target;
/// <summary>
/// The pair of correspond object label
/// </summary>
private ObjectsPair pair;
/// <summary>
/// Matrix for arrow triangle drawing
/// </summary>
private Matrix matrix;
/// <summary>
/// Pen for border drawing
/// </summary>
private Pen borderPen;
/// <summary>
/// The associated arrow
/// </summary>
private ICategoryArrow arrow;
/// <summary>
/// Pen for arrow line drawing
/// </summary>
private Pen linePen;
/// <summary>
/// The brush for arrow triangle drawing
/// </summary>
private Brush triangleBrush;
/// <summary>
/// The triangle vertices
/// </summary>
private PointF[] trianglePoints;
/// <summary>
/// The number of source object
/// </summary>
private object sourceNumber;
/// <summary>
/// The number of target object
/// </summary>
private object targetNumber;
/// <summary>
/// Brush for text foreground drawing
/// </summary>
new private Brush textBrush;
/// <summary>
/// Constructor
/// </summary>
private ArrowLabel()
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="button">Associated button</param>
/// <param name="arrow">Associated arrow</param>
/// <param name="source">Associated source</param>
/// <param name="target">Associated target</param>
public ArrowLabel(PaletteButton button, ICategoryArrow arrow,
IObjectLabel source, IObjectLabel target) : base(button)
{
this.arrow = arrow;
this.source = source;
this.target = target;
Initialize();
}
/// <summary>
/// Serialization constructor
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
public ArrowLabel(SerializationInfo info, StreamingContext context) : base(info, context)
{
arrow = (ICategoryArrow)info.GetValue("Arrow", typeof(object));
sourceNumber = (int)info.GetValue("SourceNumber", typeof(int));
targetNumber = (int)info.GetValue("TargetNumber", typeof(int));
}
/// <summary>
/// ISerializable interface implementation
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
new public void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Arrow", arrow);
info.AddValue("SourceNumber", sourceNumber);
info.AddValue("TargetNumber", targetNumber);
}
/// <summary>
/// Desktop
/// </summary>
new public PanelDesktop Desktop
{
get
{
return Parent as PanelDesktop;
}
}
/// <summary>
/// Removes itself
/// </summary>
/// <param name="removeForm">The "should remove properties editor" flag</param>
public void Remove(bool removeForm)
{
Desktop.Tools.RemoveArrowNode(this);
RemoveFromComponent();
pair.Remove(this);
pair.Refresh();
if (removeForm)
{
RemoveForm();
}
if (Arrow is IRemovableObject)
{
IRemovableObject obj = Arrow as IRemovableObject;
obj.RemoveObject();
}
arrow = null;
GC.Collect();
}
/// <summary>
/// Updates associated forms
/// </summary>
public override void UpdateForms()
{
UpdateForm();
}
/// <summary>
/// The selected flag
/// </summary>
public override bool Selected
{
get
{
return selected;
}
set
{
if (value)
{
}
if (selected != value)
{
selected = value;
Refresh();
}
}
}
/// <summary>
/// The label associated with arrow source
/// </summary>
public virtual IObjectLabel Source
{
get
{
return source;
}
set
{
source = value;
}
}
/// <summary>
/// The label associated with arrow target
/// </summary>
public virtual IObjectLabel Target
{
get
{
return target;
}
set
{
target = value;
}
}
/// <summary>
/// The number of source object
/// </summary>
public object SourceNumber
{
get
{
return sourceNumber;
}
set
{
sourceNumber = value;
}
}
/// <summary>
/// The number of target object
/// </summary>
public object TargetNumber
{
get
{
return targetNumber;
}
set
{
targetNumber = value;
}
}
/// <summary>
/// The associated arrow
/// </summary>
public ICategoryArrow Arrow
{
get
{
return arrow;
}
set
{
arrow = value;
}
}
/// <summary>
/// Initialization
/// </summary>
public void Initialize()
{
Paint += new PaintEventHandler(onPaint);
initNamedEventHandlers();
captionEditor.Visible = false;
imagePosition = new PointF(5, 20);
Width = width;
Height = height;
Rectangle r = new Rectangle();
r.Width = Width;
r.Height = captionHeight;
EditorRectangle = r;
textBrush = new SolidBrush(Color.White);
borderPen = new Pen(Color.Black);
linePen = new Pen(Color.Black);
matrix = new Matrix();
trianglePoints = new PointF[3];
textBrush = new SolidBrush(Color.Black);
for (int i = 0; i < 3; i++)
{
trianglePoints[i] = new PointF(0, 0);
}
triangleBrush = new SolidBrush(Color.Black);
}
/// <summary>
/// The pair of associated objects labels
/// </summary>
public ObjectsPair Pair
{
set
{
if (!value.Belongs(source, target))
{
throw new Exception("");
}
pair = value;
}
}
/// <summary>
/// Draws itself
/// </summary>
/// <param name="g">Graphics to draw</param>
public void Draw(Graphics g)
{
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
int x3 = 0;
int y3 = 0;
Panel p = null;
if (Source is Panel)
{
p = Source as Panel;
}
else
{
p = ContainerObjectLabel.GetPanel(Source);
}
x1 = p.Left + p.Width / 2;
y1 = p.Top + p.Height / 2;
x2 = Left + Width / 2;
y2 = Top + Height / 2;
if (Target is Panel)
{
p = Target as Panel;
}
else
{
p = ContainerObjectLabel.GetPanel(Target);
}
x3 = p.Left + p.Width / 2;
y3 = p.Top + p.Height / 2;
g.DrawLine(linePen, x1, y1, x2, y2);
g.DrawLine(linePen, x2, y2, x3, y3);
for (int i = 0; i < 3; i++)
{
trianglePoints[i].X = triangle[2 * i];
trianglePoints[i].Y = triangle[2 * i + 1];
}
matrix.Reset();
float dx = x3 - x2;
float dy = y3 - y2;
double s = Math.Sqrt(dx * dx + dy * dy);
if (s == 0)
{
return;
}
double angle = 180 * Math.Atan2(dy / s, dx / s) / Math.PI;
matrix.Translate(x2 + dx / 2, y2 + dy / 2);
matrix.RotateAt((float)angle, trianglePoints[0]);
matrix.TransformPoints(trianglePoints);
g.FillPolygon(triangleBrush, trianglePoints);
}
/// <summary>
/// Creates correspond xml
/// </summary>
/// <param name="doc">document to create element</param>
/// <returns>The created element</returns>
public XmlElement CreateXml(XmlDocument doc)
{
XmlElement element = doc.CreateElement("ArrowLabel");
XmlAttribute attrName = doc.CreateAttribute("Name");
attrName.Value = ComponentName;
element.Attributes.Append(attrName);
if (Arrow is IXmlElementCreator)
{
IXmlElementCreator c = Arrow as IXmlElementCreator;
XmlElement child = c.CreateXml(doc);
element.AppendChild(child);
}
return element;
}
/// <summary>
/// The on paint event handler
/// </summary>
/// <param name="sender">The sender</param>
/// <param name="e">The event handler arguments</param>
protected void onPaint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawRectangle(borderPen, 0, 0, Width - 1, Height - 1);
g.DrawString(ComponentName, font, textBrush, 5F, 5F);
}
#region IArrowLabel Members
IObjectLabel IArrowLabel.Source
{
get
{
return source;
}
set
{
source = value as ObjectLabel;
}
}
IObjectLabel IArrowLabel.Target
{
get
{
return target;
}
set
{
target = value as ObjectLabel;
}
}
#endregion
#region INamedComponent Members
public override string Name
{
get
{
return ComponentName;
}
}
public override int Kind
{
get
{
return kind;
}
}
public override string Type
{
get
{
return type;
}
}
void INamedComponent.Remove()
{
// TODO: Add ArrowLabel.DiagramUI.INamedComponent.Remove implementation
}
public override int X
{
get
{
return Left;
}
set
{
Left = value;
}
}
public override int Y
{
get
{
return Top;
}
set
{
Top = value;
}
}
IDesktop INamedComponent.Desktop
{
get
{
return Parent as IDesktop;
}
set
{
}
}
#endregion
}
}