Overview
Users create circuit diagrams by selecting components from the component menus. Then using the mouse, a user can select and move components to represent the circuit of interest. When the user selects the Wire Mode button, wires can be drawn to interconnect components interactively using the mouse and "rubberband" lines.
Keyboard events will be implemented to rotate a component as it is moved using the "R" key. Also, during mouse move, a component can be deleted using the "D" key.
Keyboard Events
Add keypress event variables in MainForm.cs
// Keypress event variables
public bool rotate = false; // Rotate component flag
public bool delete =
false; // Delete
component flag
Add a MainForm Key Press event handler as follows:
private void MainForm_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 114 || e.KeyChar ==
82) // 114 =
r, 82 = R
rotate =
!rotate;
if (e.KeyChar == 100 || e.KeyChar ==
68) // 100 =
d, 68 = D
delete = !delete;
}
Mouse Events
Add the mouse event variables in MainForm.cs
// Mouse event variables
bool isMouseDown = false;
bool lineDrawing = false;
int offsetX, offsetY, startX, startY;
Comp tempComp = new Comp();
// The wire we are drawing
private Wire NewWire = null;
// Points for the new line.
private Point NewPt1, NewPt2;
Modify the Paint() event in MainForm.cs to draw the component output wires
private void schematicCanvas_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
foreach (Comp comp in ckt.comps)
{
comp.Draw(e.Graphics);
schematicCanvas.Invalidate();
foreach (Wire wire in comp.wires)
{
wire.Draw(e.Graphics);
schematicCanvas.Invalidate();
}
}
}
Add the HitTest() method to MainForm.cs.
private bool hitTest(Comp comp)
{
bool hit;
hit = false;
if ((startX >= comp.Loc.X
&& startX <= comp.Loc.X + comp.Width) &&
(startY
>= comp.Loc.Y && startY <= comp.Loc.Y + comp.Height))
{
Debug.WriteLine("Hit!");
hit = true;
}
else
{
Debug.WriteLine("No Hit!");
hit = false;
}
return hit;
}
Add the SnapToGrid() helper method to MainForm
// Snap XY point to the grid
private void SnapToGrid(ref int x, ref int y)
{
//if (!chkSnapToGrid.Checked) return;
x = grid_gap * (int)Math.Round((double)x / grid_gap);
y = grid_gap * (int)Math.Round((double)y / grid_gap);
}
Add the Wire Mode button handler in MainForm.cs
private void btnWireMode_Click(object sender, EventArgs e)
{
lineDrawing =
!lineDrawing;
}
Add a list of wires to Comp.cs
public List<Wire> wires = new List<Wire>();
Initialize width & height in Comp.cs to facilitate the HitTest
protected int _width = 60;
protected int _height
= 40;
Add MouseDown, MouseMove & MouseUp events to the schematicCanvas.
private void schematicCanvas_MouseDown(object sender, MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Left:
{
closeOtherPanels(null);
isMouseDown = true;
if (!lineDrawing)
{// Snap the start point to the Grid
int x = e.X;
int y = e.Y;
SnapToGrid(ref x, ref y);
startX = x;
startY = y;
// Iterate over the schematic component list & draw each
component
foreach (Comp comp in ckt.comps)
{
if (hitTest(comp))
{
tempComp = comp;
offsetX = startX - comp.Loc.X;
offsetY = startY - comp.Loc.Y;
}
}
}
if (lineDrawing)
{
// Snap the start point to the Grid
int x = e.X;
int y = e.Y;
SnapToGrid(ref x, ref y);
NewPt1 = new Point(x,
y);
NewPt2 = new Point(x,
y);
startX = x;
startY = y;
// Create a new wire and add it to the schematic wires list
NewWire = new Wire(); // Use the constructor with no parameters
NewWire.Pt1 = NewPt1;
NewWire.Pt2 = NewPt2;
NewWire.endcapsVisible = true;
//schematic.wires.Add(NewWire);
// Debugs to show the line points on the console
Debug.WriteLine("Line Start Points: (" + NewPt1.X + ", " + NewPt1.Y + " )");
// Iterate over the schematic component list & draw each
component
foreach (Comp comp in ckt.comps)
{
if (hitTest(comp))
{
Debug.WriteLine("Start Component hit!" + comp.ToString());
NewWire.Cin = comp;
//NewWire.Cout = Pout;
comp.wires.Add(NewWire);
}
}
}
break;
}
case MouseButtons.Right:
{
int x = e.X;
int y = e.Y;
SnapToGrid(ref x, ref y);
startX = x;
startY = y;
Comp
hitComp = new Comp();
foreach (Comp comp in ckt.comps)
{
if (hitTest(comp))
{
hitComp = comp;
}
}
// TODO: Add code for property grid here
break;
}
default:
break;
}
}
private void schematicCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown == true)
{
if (!lineDrawing)
{
if (tempComp != null)
{
if (rotate)
{
if (tempComp.Orientation == "Series")
tempComp.Orientation = "Shunt";
else if (tempComp.Orientation == "Shunt")
tempComp.Orientation = "Series";
rotate = false;
}
// TODO: Add delete code here
int x = e.X;
int y = e.Y;
SnapToGrid(ref x, ref y);
tempComp.Loc = new Point(x - offsetX, y - offsetY);
schematicCanvas.Invalidate();
}
}
if (lineDrawing)
{
if (NewWire == null) return;
// Snap the end point to the Grid
int x = e.X;
int y = e.Y;
SnapToGrid(ref x, ref y);
NewPt2 =
new Point(x, y);
NewWire.Pt2 = NewPt2;
// Redraw, this creates the "rubber band" effect while
drawing the wire
schematicCanvas.Invalidate(); // Refresh the
drawing canvas pictureBox
}
}
}
private void schematicCanvas_MouseUp(object sender, MouseEventArgs e)
{
isMouseDown = false;
tempComp = null;
if (lineDrawing)
{
int x = e.X;
int y = e.Y;
SnapToGrid(ref x, ref y);
startX = x;
startY = y;
// Iterate over the schematic component list and draw each
component
foreach (Comp comp in ckt.comps)
{
if (hitTest(comp))
{
Debug.WriteLine("End Component hit! " + comp.ToString());
NewWire.Cout = comp;
}
}
// Update the new wire end points
NewWire.Pt1
= NewPt1;
NewWire.Pt2
= NewPt2;
NewWire.endcapsVisible = false;
// Terminate any further updates to the new wire, this makes it
permanent in the schematic wires list
NewWire = null;
// Redraw.
schematicCanvas.Invalidate(); // Refresh the
drawing canvas pictureBox
// Debugs to show the line points on the console
Debug.WriteLine("Line End Points: (" + NewPt2.X + ", " + NewPt2.Y + " )");
}
//lineDrawing = false;
}
Wire Mode LED
// C# Libraries
using System;
using System.Collections.Generic;
using System.Drawing;
namespace MicrowaveTools.Components
{
public class LED : Comp
{
// LED specific variables
SolidBrush onfillColor = new SolidBrush(Color.Green);
SolidBrush
offfillColor = new
SolidBrush(Color.Maroon);
Color offColor =
Color.Black;
public Pen offPen = new Pen(Color.DimGray, 2);
public Pen onPen = new Pen(Color.Green, 2);
private const int
endcap_radius = 3;
public bool hotSpotsVisible = false;
public bool logicState = false;
// Component text variables
// Create font and brush.
public Font drawFont = new Font("Arial", 10);
public SolidBrush drawBrush = new SolidBrush(Color.White);
public StringFormat drawFormat = new StringFormat();
public LED()
{
}
public LED(Point location)
{
Loc = location;
Pin = Loc;
}
// Let the LED draw itself called from the canvas paint event
public override void
Draw(Graphics gr)
{
// Draw outer circle
Rectangle rect =
new Rectangle((int)Loc.X - 6, (int)Loc.Y - 6, 12, 12);
gr.FillEllipse(new SolidBrush(Color.DarkGray), rect);
// Draw inner circle = LED based on the LED state
if (logicState)
{
//gr.DrawLine(this.onPen,
new Point((int)Loc.X, (int)Loc.Y + 20), new Point((int)Loc.X + 10, (int)Loc.Y +
20));
rect = new Rectangle((int)Loc.X - 4, (int)Loc.Y - 4, 8, 8);
gr.FillEllipse(this.onfillColor,
rect);
}
else
{
//gr.DrawLine(this.offPen, new Point((int)Loc.X, (int)Loc.Y + 20),
new Point((int)Loc.X + 10, (int)Loc.Y + 20));
rect = new Rectangle((int)Loc.X - 4, (int)Loc.Y - 4, 8, 8);
gr.FillEllipse(this.offfillColor, rect);
}
// Add label
drawCompText(gr,
new Point(Loc.X - 75, Loc.Y - 8), "Wire Mode");
}
public virtual void
drawCompText(Graphics gr, Point p1, String drawString)
{
// Convert Point ints to floats
float x = p1.X;
float y = p1.Y;
// Draw string to screen.
gr.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat);
}
}
}
// Create the wire mode LED
LED led = new LED(new Point(300, 200));
// Display permanent wire mode LED
showWireModeLED(e.Graphics);
private void showWireModeLED(Graphics gr)
{
// Draw the wire mode LED in the lower left corner of the
schematic canvas
int x, y;
x = 80;
y =
schematicCanvas.ClientSize.Height - 20; // Forces
location to lower left corner if height changes
led.Loc = new Point(x, y);
led.Draw(gr);
}
private void btnWireMode_Click(object sender, EventArgs e)
{
lineDrawing =
!lineDrawing;
led.logicState =
lineDrawing;
schematicCanvas.Invalidate();
}
MainForm Source Code Organization
Comments and regions have been added to MainForm.cs to group source code for constructors, schematicCanvas event handlers, main menu button handlers, component menu button handlers, and helper methods. The reorganized source code with updates from this post can be seen on GitHub.
There remain things to implement:
- Rotate
- Delete
- Component Text
No comments:
Post a Comment