using System;
using System.Drawing;
using System.Windows.Forms;
namespace Netron.Diagramming.Core {
class ConnectionTool : AbstractTool, IMouseListener {
#region Fields
///
/// the location of the mouse when the motion starts
///
private Point initialPoint;
private bool doDraw;
#endregion
#region Constructor
///
/// Initializes a new instance of the class.
///
/// The name of the tool.
public ConnectionTool(string name)
: base(name) {
}
#endregion
#region Methods
///
/// Called when the tool is activated.
///
protected override void OnActivateTool() {
Controller.View.CurrentCursor = CursorPalette.Grip;
this.SuspendOtherTools();
doDraw = false;
}
///
/// Handles the mouse down event
///
/// The instance containing the event data.
/// Returns 'true' if the event was handled, otherwise 'false'.
public bool MouseDown(MouseEventArgs e) {
if (e == null)
throw new ArgumentNullException("The argument object is 'null'");
if (e.Button == MouseButtons.Left && Enabled && !IsSuspended) {
initialPoint = e.Location;
doDraw = true;
return true;
}
return false;
}
///
/// Handles the mouse move event
///
/// The instance containing the event data.
public void MouseMove(MouseEventArgs e) {
if (e == null)
throw new ArgumentNullException("The argument object is 'null'");
Point point = e.Location;
if (IsActive) {
if (foundConnector != null)
foundConnector.Hovered = false;
foundConnector = this.Controller.Model.Selection.FindConnectorAt(e.Location);
if (foundConnector != null)
foundConnector.Hovered = true;
}
if (IsActive && doDraw) {
Controller.View.PaintGhostLine(initialPoint, point);
Controller.View.Invalidate(System.Drawing.Rectangle.Inflate(Controller.View.Ghost.Rectangle, 20, 20));
}
}
private IConnector foundConnector;
///
///
///
/// The instance containing the event data.
public void MouseUp(MouseEventArgs e) {
if (IsActive) {
// First, make sure the initial point is far enough away from
// the final point to make a connection.
int maxX = Math.Abs(Math.Max(initialPoint.X, e.Location.X));
int maxY = Math.Abs(Math.Max(initialPoint.Y, e.Location.Y));
if (!(maxX > ConnectionBase.MinLength) ||
!(maxY > ConnectionBase.MinLength)) {
return;
}
//whatever comes hereafter, a compund command is the most economic approach
CompoundCommand package = new CompoundCommand(this.Controller);
//let's see if the connection endpoints hit other connectors
//note that the following can be done because the actual connection has not been created yet
//otherwise the search would find the endpoints of the newly created connection, which
//would create a loop and a stack overflow!
IConnector startConnector = this.Controller.Model.Selection.FindConnectorAt(initialPoint);
IConnector endConnector = this.Controller.Model.Selection.FindConnectorAt(e.Location);
#region Create the new connection
Connection cn = new Connection(this.initialPoint, e.Location, this.Controller.Model);
AddConnectionCommand newcon = new AddConnectionCommand(this.Controller, cn);
#endregion
#region Initial attachment?
if (startConnector != null) {
BindConnectorsCommand bindStart = new BindConnectorsCommand(this.Controller, startConnector, cn.From);
package.Commands.Add(bindStart);
}
#endregion
#region Final attachment?
if (endConnector != null) {
BindConnectorsCommand bindEnd = new BindConnectorsCommand(this.Controller, endConnector, cn.To);
package.Commands.Add(bindEnd);
}
#endregion
package.Text = "New connection";
package.Commands.Add(newcon);
this.Controller.UndoManager.AddUndoCommand(package);
//do it all
package.Redo();
//reset highlight of the found connector
if (foundConnector != null)
foundConnector.Hovered = false;
//drop the painted ghost
Controller.View.ResetGhost();
this.doDraw = false;
}
}
#endregion
}
}