200 lines
7.3 KiB
C#
200 lines
7.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Drawing;
|
|
using System.Xml;
|
|
|
|
namespace EduNetworkBuilder
|
|
{
|
|
/// <summary>
|
|
/// For drawing shapes on a network. Rectangles, circles. Filled or not
|
|
/// </summary>
|
|
[Serializable]
|
|
public class NetShape
|
|
{
|
|
public NetShapeType MyShape = NetShapeType.none;
|
|
public Rectangle InArea;
|
|
public Color LineColor = Color.Empty;
|
|
public Color FillColor = Color.Empty;
|
|
public string Name = "";
|
|
int DragSize = 15;
|
|
|
|
public NetShape(NetShapeType What, Rectangle Where, Color fillcolor, Color linecolor)
|
|
{
|
|
MyShape = What;
|
|
InArea = Where;
|
|
FillColor = fillcolor;
|
|
LineColor = linecolor;
|
|
}
|
|
public NetShape(XmlNode what)
|
|
{
|
|
Load(what);
|
|
}
|
|
|
|
|
|
public bool Equals(NetShape CompareWith)
|
|
{
|
|
if (MyShape != CompareWith.MyShape) return false;
|
|
if (InArea != CompareWith.InArea) return false;
|
|
if (LineColor != CompareWith.LineColor) return false;
|
|
if (FillColor != CompareWith.FillColor) return false;
|
|
if (Name != CompareWith.Name) return false;
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// Draw the specified shape on the image
|
|
/// </summary>
|
|
/// <param name="baseImage"></param>
|
|
public void Draw(Image baseImage, bool InShapeEditMode = false)
|
|
{
|
|
Graphics G = Graphics.FromImage(baseImage);
|
|
Pen trimPen = new Pen(LineColor);
|
|
Brush coloredBrush = new SolidBrush(FillColor);
|
|
switch(MyShape)
|
|
{
|
|
case NetShapeType.circle:
|
|
if(FillColor != Color.Empty)
|
|
G.FillEllipse(coloredBrush,InArea);
|
|
if (LineColor != Color.Empty)
|
|
G.DrawEllipse(trimPen, InArea);
|
|
break;
|
|
case NetShapeType.rectangle:
|
|
if (FillColor != Color.Empty)
|
|
G.FillRectangle(coloredBrush, InArea);
|
|
if (LineColor != Color.Empty)
|
|
G.DrawRectangle(trimPen, InArea);
|
|
break;
|
|
}
|
|
if(InShapeEditMode)
|
|
{
|
|
int sz = DragSize;
|
|
Color edgeColor = Color.Black;
|
|
if (FillColor == Color.Black) edgeColor = Color.White;
|
|
coloredBrush = new SolidBrush(edgeColor);
|
|
//We want to put drag-marks on the corners of our rectangle
|
|
foreach(Rectangle one in Corners())
|
|
G.FillRectangle(coloredBrush, one);
|
|
G.DrawImage(Properties.Resources.X, Center());
|
|
}
|
|
G.Dispose();
|
|
}
|
|
|
|
List<Rectangle> Corners()
|
|
{
|
|
int sz = DragSize;
|
|
List<Rectangle> tCorners = new List<Rectangle>();
|
|
Rectangle TL = new Rectangle(InArea.X, InArea.Y, sz, sz);
|
|
Rectangle TR = new Rectangle(InArea.X + InArea.Width - sz, InArea.Y, sz, sz);
|
|
Rectangle BL = new Rectangle(InArea.X, InArea.Y + InArea.Height - sz, sz, sz);
|
|
Rectangle BR = new Rectangle(InArea.X + InArea.Width - sz, InArea.Y + InArea.Height - sz, sz, sz);
|
|
tCorners.Add(TL);
|
|
tCorners.Add(TR);
|
|
tCorners.Add(BL);
|
|
tCorners.Add(BR);
|
|
return tCorners;
|
|
}
|
|
|
|
//A rectangle in the center of the shape that we can click on
|
|
Rectangle Center()
|
|
{
|
|
int size = 100;
|
|
if (InArea.Width < 200 || InArea.Height < 200)
|
|
size = 50;
|
|
if (InArea.Width < size || InArea.Height < size)
|
|
size = Math.Min(InArea.Width / 2, InArea.Height / 2);
|
|
int cx = InArea.X + (InArea.Width / 2);
|
|
int cy = InArea.Y + (InArea.Height / 2);
|
|
return new Rectangle(cx - (size / 2), cy - (size / 2), size, size);
|
|
}
|
|
|
|
public bool CornersAreClickedOn(Point ClickPoint)
|
|
{
|
|
foreach(Rectangle rec in Corners())
|
|
{
|
|
if (rec.Contains(ClickPoint))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool CenterIsClickedOn(Point ClickPoint)
|
|
{
|
|
if (Center().Contains(ClickPoint))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// return the opposite point from the one clicked on. This is so we can start
|
|
/// dragging from here.
|
|
/// </summary>
|
|
/// <param name="ClickPoint"></param>
|
|
/// <returns></returns>
|
|
public Point OppositePoint(Point ClickPoint)
|
|
{
|
|
int fX = ClickPoint.X;
|
|
int fY = ClickPoint.Y;
|
|
int halfWidth = InArea.Width / 2;
|
|
int halfHeight = InArea.Height / 2;
|
|
if (ClickPoint.X > InArea.X + halfWidth) fX = InArea.X;
|
|
else fX = InArea.X + InArea.Width;
|
|
if (ClickPoint.Y > InArea.Y + halfHeight) fY = InArea.Y;
|
|
else fY = InArea.Y + InArea.Height;
|
|
return new Point(fX, fY);
|
|
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
string answer = Name + " " + MyShape.ToString() + " " + LineColor.Name + "/" + FillColor.Name;
|
|
answer = answer + " X:" + InArea.X + " Y:" + InArea.Y;
|
|
answer = answer + "W:" + InArea.Width + " H:" + InArea.Height;
|
|
return answer;
|
|
}
|
|
|
|
public void Load(XmlNode theNode)
|
|
{
|
|
foreach (XmlNode Individual in theNode.ChildNodes)
|
|
{
|
|
XmlNodeType myNodetype = Individual.NodeType;
|
|
if (myNodetype == XmlNodeType.Element)
|
|
{
|
|
switch (Individual.Name.ToLower())
|
|
{
|
|
case "name":
|
|
Name = Individual.InnerText;
|
|
break;
|
|
case "what":
|
|
MyShape = NB.TryParseEnum<NetShapeType>(Individual.InnerText, NetShapeType.none);
|
|
break;
|
|
case "where":
|
|
RectangleConverter converter = new RectangleConverter();
|
|
InArea = (Rectangle)converter.ConvertFromString(Individual.InnerText);
|
|
break;
|
|
case "fillcolor":
|
|
FillColor = Color.FromName(Individual.InnerText);
|
|
break;
|
|
case "linecolor":
|
|
LineColor = Color.FromName(Individual.InnerText);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Save(XmlWriter writer)
|
|
{
|
|
writer.WriteStartElement("shape");
|
|
writer.WriteElementString("name", Name);
|
|
writer.WriteElementString("what", MyShape.ToString());
|
|
RectangleConverter converter = new RectangleConverter();
|
|
writer.WriteElementString("where", converter.ConvertToString(InArea));
|
|
writer.WriteElementString("fillcolor", FillColor.Name);
|
|
writer.WriteElementString("linecolor", LineColor.Name);
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
}
|