Files
UseCase_Designer/UseCases/Form1.cs
2018-02-21 09:40:31 +01:00

380 lines
13 KiB
C#

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace UseCases
{
public partial class FrmMain : Form
{
[DllImport("kernel32")]
static extern bool AllocConsole();
enum AddAction
{
Nothing,
Actor,
UseCase
}
public FrmMain()
{
//get the command line arguments
var args = Environment.GetCommandLineArgs();
InitializeComponent();
//check if there are multiple arguments
if (args.Count() > 1)
{
//check if first arguments is a file
if (File.Exists(args[1]))
{
//try to open the file
OpenFile(args[1]);
}
else
{
Diagram = new Diagram();
//initialise default values
}
}
else
{
//initialise default values
Diagram = new Diagram();
}
}
#region variables
//actors and usecases
public Diagram Diagram { get; private set; }
//drawing variables
private readonly Font _myFont = new Font("Sans Sherif", 20f, FontStyle.Regular);
private readonly Pen _drawingPen = new Pen(Color.Black, 3f);
//adding elements
private AddAction _toAdd = AddAction.Nothing;
private IDrawable _dragged = null;
//edit tracker
private bool _hasEdited = false;
#endregion
#region menustrip
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
private void btAddActor_Click(object sender, EventArgs e)
{
_toAdd = AddAction.Actor;
}
private void btAddUseCase_Click(object sender, EventArgs e)
{
_toAdd = AddAction.UseCase;
}
//save in json format
private void btSave_Click(object sender, EventArgs e)
{
//show save file dialog and quit if canceled
var saveDiag = new SaveFileDialog {Filter = @"*.ucd|*.ucd"};
if (saveDiag.ShowDialog() != DialogResult.OK) return;
_hasEdited = false;
Diagram.Size = Size;
Diagram.Maximized = WindowState == FormWindowState.Maximized;
//save to file
var serialized = JsonConvert.SerializeObject(Diagram, Utils.SerializerSettings);
File.WriteAllText(saveDiag.FileName, serialized);
}
//save png format
private void btSaveImage_Click(object sender, EventArgs e)
{
//show save file dialog and quit if canceled
var saveDiag = new SaveFileDialog {Filter = @"*.png|*.png"};
if (saveDiag.ShowDialog() != DialogResult.OK) return;
//create bitmap and draw usecases and actors to it
var bmp = new Bitmap(Size.Width, Size.Height);
var g = Graphics.FromImage(bmp);
DrawElements(g);
//save image to file
bmp.Save(saveDiag.FileName);
}
//open json format
private void btOpen_Click(object sender, EventArgs e)
{
//check if anything has been edited
if (_hasEdited)
{
if (
MessageBox.Show(@"Are you sure you want to load a new file?", @"Load new file",
MessageBoxButtons.YesNo) == DialogResult.No)
return;
}
//show open file dialog and quit if canceled
var openDiag = new OpenFileDialog {Filter = @"*.ucd|*ucd"};
if (openDiag.ShowDialog() != DialogResult.OK) return;
//open the file
OpenFile(openDiag.FileName);
Refresh();
}
private void clearToolStripMenuItem_Click(object sender, EventArgs e)
{
//check if user realy wants to clear the diagram else return
if (MessageBox.Show(@"Are you sure you want to clear the diagram?", @"Clear", MessageBoxButtons.YesNo) !=
DialogResult.Yes) return;
//clear lists and refresh screen
Diagram = new Diagram(new Size(430, 372));
// _actors.Clear();
// _useCases.Clear();
WindowState = FormWindowState.Normal;
Size = Diagram.Size;
Refresh();
}
private void controlsToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show(@"Pres Ctrl+A or click Add>Actor to add an Actor
Press Ctrl+U or click File>Use Case to add a Use Case
Click somwhere on screen to add Use Case or Actor at that position
Leave name empty to remove
Click and drag to move usecase or actor
Press Ctrl+S or click File>Save to save the diagram
Press Ctrl+Shift+S or click File>Save as image to save diagram as image
Click File>Clear to clear the diagram
Press Alt+F4 or click the cross or click File>Exit to close the form
Click Help>Controls to view this message
Click Help>About to view information about the application", @"Controls");
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show(@"Use Case Designer by Rick Rongen
Version 1.0
Developed by order of Fontys Hogerescholen ICT Eindhoven", @"About");
}
#endregion
#region functions
/// <summary>
/// Opens an file into form and shows error if it could not be loaded
/// </summary>
/// <param name="filename">full path of ile to load</param>
private void OpenFile(string filename)
{
//try to open file
try
{
Diagram = JsonConvert.DeserializeObject<Diagram>(File.ReadAllText(filename), Utils.SerializerSettings);
WindowState = Diagram.Maximized ? FormWindowState.Maximized : FormWindowState.Normal;
Size = Diagram.Size;
Refresh();
}
catch (JsonException jex)
{
//show the console with the error if the user wan't to see it
if (
MessageBox.Show(
$@"Error while loading {filename}\n
Invallid format or broken data\nGeeks may check console for the exception, pres yes to show console",
@"Error occured, show console?", MessageBoxButtons.YesNo) == DialogResult.Yes) AllocConsole();
Console.WriteLine(jex.ToString());
}
catch (IOException ioex)
{
//show the console with the error if the user wan't to see it
if (
MessageBox.Show(
$@"Error while loading {filename}\nCouldn't open the file or there was an encoding issue.",
@"Error occured, show console?", MessageBoxButtons.YesNo) == DialogResult.Yes) AllocConsole();
Console.WriteLine(ioex.ToString());
}
finally
{
_hasEdited = false;
}
}
/// <summary>
/// Draws all ellements in actors and useCases to the graphics object
/// </summary>
/// <param name="g">graphics object</param>
private void DrawElements(Graphics g)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
foreach (var drawable in Diagram.Drawable)
{
drawable.Draw(g, _myFont, _drawingPen);
}
}
#endregion
#region mouse
//handle creation of components
private void frmMain_Click(object sender, EventArgs e)
{
var pos = PointToClient(MousePosition);
switch (_toAdd)
{
case AddAction.Actor:
//create new actor
var adiag = new EditActor();
if (adiag.ShowDialog() == DialogResult.OK && adiag.ActorName != "")
{
Diagram.Actors.Add(new Actor(adiag.ActorName, pos));
}
Refresh();
break;
case AddAction.UseCase:
//create new useCase
var udiag = new editUseCase(Diagram.Actors) {UseCase = new UseCase(), CasePos = pos};
if (udiag.ShowDialog() == DialogResult.OK && udiag.UseCase.Name != "")
{
Diagram.UseCases.Add(udiag.UseCase);
udiag.UseCase.Actors.ForEach(Console.WriteLine);
}
Refresh();
break;
default:
case AddAction.Nothing:
break;
}
_toAdd = AddAction.Nothing;
if (Diagram.UseCases.Any() || Diagram.Actors.Any()) _hasEdited = true;
}
//handle editing of components
private void frmMain_DoubleClick(object sender, EventArgs e)
{
var mousepos = PointToClient(MousePosition);
var closest = GetClosestDrawable(mousepos);
switch (closest)
{
case null:
return;
case Actor actor:
var edAcDiag = new EditActor(actor.Name);
if (edAcDiag.ShowDialog() == DialogResult.OK)
{
if (edAcDiag.ActorName == "")
{
//remove actor if name is equal to ""
Diagram.Actors.Remove(actor);
foreach (var usecase in Diagram.UseCases)
{
//remove this actor from all refering usecases
usecase.Actors.Remove(actor);
}
}
else
{
//update name
actor.Name = edAcDiag.ActorName;
}
}
break;
case UseCase useCase:
var edUcDiag = new editUseCase(Diagram.Actors)
{
UseCase = useCase,
CasePos = useCase.Position
};
if (edUcDiag.ShowDialog() == DialogResult.OK)
{
if (edUcDiag.UseCase.Name == "")
{
//remove usecase if name is equal to ""
Diagram.UseCases.Remove(useCase);
}
}
break;
}
Refresh();
}
//move usecase or actor
private void frmMain_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _toAdd == AddAction.Nothing)
{
_dragged = null;
}
}
private void frmMain_MouseDown(object sender, MouseEventArgs e)
{
//quit if not left mousebutton or adding item
if (e.Button != MouseButtons.Left || _toAdd != AddAction.Nothing) return;
//get mouse position in client
var mousepos = PointToClient(MousePosition);
var closest = GetClosestDrawable(mousepos);
if (closest == null)
return;
_dragged = closest;
}
private void frmMain_MouseMove(object sender, MouseEventArgs e)
{
if (_dragged == null) return;
_dragged.Position = PointToClient(MousePosition);
Refresh();
}
private IDrawable GetClosestDrawable(Point position, double maxDistance = 30d)
{
if (!Diagram.UseCases.Any() && !Diagram.Actors.Any())
return null; // No items to check
var comm = Diagram.Drawable.Select(org => new
{
original = org,
distance = Math.Sqrt(Math.Pow(org.Position.X - position.X, 2) +
Math.Pow(org.Position.Y - position.Y, 2))
}).Aggregate((a1, a2) => a1.distance < a2.distance ? a1 : a2);
return comm.distance > maxDistance ? null : comm.original;
}
#endregion
private void frmMain_Paint(object sender, PaintEventArgs e)
{
//draw actors, use cases and lines
DrawElements(e.Graphics);
}
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (!_hasEdited) return;
if (MessageBox.Show(@"Are you sure you want to exit?", @"exit", MessageBoxButtons.YesNo) !=
DialogResult.Yes)
e.Cancel = true;
}
}
}