using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace trackDesigner { public partial class editForm : Form { /*-----*----- DATA MEMBERS -----*-----*/ const int MAX_SIZE=30; private int index = -1; private bool add_mode = true; private bool add_turnout = false; private char aORb; private bool mDown = false; private Image imgTrack; private Graphics imgGraphics; // declare data structures private trackStructure[] myTrack; private int num_segments; private int temp_nsegs; private int pCount = 0; /*-----*----- PROPERTIES -----*-----*/ // properties so data structures can be passed back & forth public bool a_mode { set { add_mode = value; } } public trackStructure[] track { get { return myTrack; } set { myTrack = value; } } public int segs { get { return num_segments; } set { num_segments = value; temp_nsegs = value; } } public editForm() { InitializeComponent(); } /*-----*----- METHODS -----*-----*/ /******************************************************************* Method Name: on_point Purpose: Determines whether Point p is on (or sufficiently close * enough) a trackPt. If trackPt is already a turnout, tells user * they cannot add any more segments in that location Input: Point p Output: trackPt that Point p is on or close to *******************************************************************/ private trackPt on_point(Point p) { trackPt pt = new trackPt(); pt.loc = p; int xdiff, ydiff; // find out if there's a corresponding segment endpoint or midpoint for (int i = 0; i < num_segments; i++) { xdiff = Math.Abs(myTrack[i].ptMid.loc.X - p.X); ydiff = Math.Abs(myTrack[i].ptMid.loc.Y - p.Y); if (xdiff <= 5 && ydiff <= 5) { index = i; return new trackPt(new Point(-1, -1), true); } xdiff = Math.Abs(myTrack[i].ptA.loc.X - p.X); ydiff = Math.Abs(myTrack[i].ptA.loc.Y - p.Y); if (xdiff <= 5 && ydiff <= 5) { if (myTrack[i].ptA.num_connected <= 2) { pt = myTrack[i].ptA; } else { MessageBox.Show("You can't add any more segments there!"); pt.loc.X = -1; return pt; } } xdiff = Math.Abs(myTrack[i].ptB.loc.X - p.X); ydiff = Math.Abs(myTrack[i].ptB.loc.Y - p.Y); if (xdiff <= 5 && ydiff <= 5) { if (myTrack[i].ptB.num_connected <= 2) { pt = myTrack[i].ptB; } else { MessageBox.Show("You can't add any more segments there"); pt.loc.X = -1; return pt; } } } return pt; // if not near any existing points, use exact location they clicked } /******************************************************************* Method Name: redo_track Purpose: Redraws the whole track Input: None Output: None *******************************************************************/ private void redo_Track() { imgTrack = new Bitmap(this.Width, this.Height); imgGraphics = Graphics.FromImage(imgTrack); // draw black guidelines imgGraphics.DrawLine(Pens.Black, 0, 25, this.Width, 25); imgGraphics.DrawLine(Pens.Black, 0, 380, this.Width, 380); // draw segments... endpoints and midpoint and then connect it with the curve for (int i = 0; i < num_segments; i++) { if (myTrack[i].ptA.num_connected > 2) { drawPT(Brushes.Lime, myTrack[i].ptA.loc); } else { drawPT(Brushes.Blue, myTrack[i].ptA.loc); } drawPT(Brushes.Red, myTrack[i].ptMid.loc); if (myTrack[i].ptB.num_connected > 2) { drawPT(Brushes.Lime, myTrack[i].ptB.loc); } else { drawPT(Brushes.Blue, myTrack[i].ptB.loc); } drawCurve(Pens.Black, myTrack[i]); } return; } /******************************************************************* Method Name: drawCurve Purpose: Draws a segment of track from 3 points (TrackPt locations) Input: None Output: None *******************************************************************/ private void drawCurve(Pen p, trackStructure t) { // array of 3 points to fit the DrawCurve function Point[] temp = new Point[3]; temp[0] = t.ptA.loc; temp[1] = t.ptMid.loc; temp[2] = t.ptB.loc; imgGraphics.DrawCurve(p, temp); } /******************************************************************* Method Name: drawPT Purpose: Draws a point at location p with brush b. Color of point is * specified by the brush Input: Brush b, Point p Output: None *******************************************************************/ private void drawPT(Brush b, Point p) { imgGraphics.FillEllipse(b, p.X - 5, p.Y - 5, 10, 10); } /******************************************************************* Method Name: populateLB Purpose: dynamically populates a checked list box with all segments * of the track so that they can be selected and deleted if the user * desires Input: None Output: None *******************************************************************/ private void populateLB() { for (int i = 0; i < num_segments; i++) { cLBDeleteSegments.Items.Add("Segment " + (i + 1).ToString()); } } /******************************************************************* Method Name: draw_highlighted Purpose: Redraws the "highlighted" segments of track when a checkbox * is UNCHECKED in delete mode Input: integer for currently checked item (needed because checked * status does not change until AFTER event) Output: None *******************************************************************/ void draw_highlighted(int x) { for (int i = 0; i < num_segments; i++) { if (cLBDeleteSegments.GetItemChecked(i) && i != x) // it's checked AND it wasn't { // just unchecked Pen p = new Pen(Brushes.Orange, 3); drawCurve(p, myTrack[i]); } } } /*-----*----- EVENT HANDLERS -----*-----*/ private void btnCancel_Click(object sender, EventArgs e) { // this isn't properly done. OBJECTS are changed because data points // right to them. Need to make copies and change the copy to make this // work properly num_segments = temp_nsegs; // don't increase the number of segments this.DialogResult = DialogResult.Cancel; this.Close(); return; } private void btnFinished_Click(object sender, EventArgs e) { // check to make sure it's all okay this.DialogResult = DialogResult.OK; // save the data-- don't need to do this since the objects are // directly referenced and get changed immediately this.Close(); return; } private void btnApply_Click(object sender, EventArgs e) { // check to make sure it's okay // save the data // THIS IS WHERE YOU WOULD UPDATE THE COPY YOU MADE temp_nsegs = num_segments; // update the number of segments return; } private void editForm_MouseDown(object sender, MouseEventArgs e) { trackPt temp = new trackPt(); mDown = true; if (add_mode && !add_turnout && e.Y <= 375 && e.Y >=30) { if (pCount == 1) // second endpoint { temp = on_point(new Point(e.X, e.Y)); if (temp.loc.X != -1) // make sure we aren't dragging a midpoint { // do the work to add everything myTrack[num_segments].ptA.num_connected++; if (myTrack[num_segments].ptA.num_connected == 3) { add_turnout = true; aORb = 'A'; MessageBox.Show("Please click the midpoint of the segment \n to be traveled" + " if the turnout is curved."); } temp.num_connected++; if (temp.num_connected == 3) { add_turnout = true; aORb = 'B'; MessageBox.Show("Please click the midpoint of the segment \n to be traveled" + " if the turnout is curved."); } int chX = myTrack[num_segments].ptA.loc.X - temp.loc.X; // calculate midpoint int chY = myTrack[num_segments].ptA.loc.Y - temp.loc.Y; myTrack[num_segments].ptMid = new trackPt(new Point(e.X + (chX / 2), e.Y + (chY / 2)), true); imgGraphics.FillEllipse(Brushes.Red, (e.X + (chX / 2)) - 5, (e.Y + (chY / 2)) - 5, 10, 10); myTrack[num_segments].ptB = temp; imgGraphics.FillEllipse(Brushes.Blue, temp.loc.X - 5, temp.loc.Y - 5, 10, 10); num_segments++; // actually add the segment pCount = 0; redo_Track(); } if (temp.loc.Y == -1) { // set back to 0 if they were dragging a midpoint pCount = 0; } } else // first endpoint OR dragging midpoint { myTrack[num_segments] = new trackStructure(); // check if a point was clicked if yes, use that point temp = on_point(new Point(e.X, e.Y)); if (temp.loc.X != -1 && temp.loc.Y != -1) // make sure we aren't dragging a midpoint { pCount++; myTrack[num_segments].ptA = temp; imgGraphics.FillEllipse(Brushes.Blue, temp.loc.X - 5, temp.loc.Y - 5, 10, 10); } } Invalidate(); Update(); } else if (add_turnout) { // check if it's on the point temp = on_point(new Point(e.X, e.Y)); if (temp.loc.Y == -1 && index != -1 && pCount == 0) { // if y == -1 (means on midpoint) and index != -1 (index = segment number) // and pCount == 0 (curved segment) then val1=index; if( aORb == 'A' ) myTrack[num_segments - 1].ptA.val1 = index; else if ( aORb == 'B' ) myTrack[num_segments - 1].ptB.val1 = index; // print new message and wait for another click MessageBox.Show("Please click the midpoint of the segment \n to be traveled" + " if the turnout is straight."); pCount++; index = -1; } else if (temp.loc.Y == -1 && index != -1 && pCount == 1) { // if y == -1 (means on midpoint) and index != -1 (index = segment number) // and pCount == 1 (straight segment) then val2=index; if (aORb == 'A') myTrack[num_segments - 1].ptA.val2 = index; else if (aORb == 'B') myTrack[num_segments - 1].ptB.val2 = index; // both have been clicked so set add_turnout to false and pCount back MessageBox.Show("Thank you"); pCount = 0; add_turnout = false; index = -1; } else MessageBox.Show("That is not a midpoint"); } } private void editForm_MouseMove(object sender, MouseEventArgs e) { if (mDown && index != -1 && !add_turnout) { // redraw the screen if dragging a midpoint myTrack[index].ptMid.loc = new Point(e.X, e.Y); redo_Track(); Invalidate(); Update(); } } private void editForm_MouseUp(object sender, MouseEventArgs e) { mDown = false; if (index != -1 && e.Y >= 30 && e.Y <= 375) // a point was dragged, need to change it now { imgGraphics.FillEllipse(Brushes.Red, e.X - 5, e.Y - 5, 10, 10); myTrack[index].ptMid.loc = new Point(e.X, e.Y); index = -1; // change back to -1 for next time! redo_Track(); } else if (index != -1 && e.Y < 30) // give valid Y value { imgGraphics.FillEllipse(Brushes.Red, e.X - 5, 30, 10, 10); myTrack[index].ptMid.loc = new Point(e.X, 30); index = -1; // change back to -1 for next time! redo_Track(); } else if (index != -1 && e.Y > 375) // give valid Y value { imgGraphics.FillEllipse(Brushes.Red, e.X - 5, 375, 10, 10); myTrack[index].ptMid.loc = new Point(e.X, 375); index = -1; // change back to -1 for next time! redo_Track(); } Invalidate(); // redraw it Update(); } private void myPaintHandler(object sender, PaintEventArgs e) { Graphics g = this.CreateGraphics(); g.DrawImage(imgTrack, 0, 0); } private void editForm_Load(object sender, EventArgs e) { // initialize all objects imgTrack = new Bitmap(this.Width, this.Height); imgGraphics = Graphics.FromImage(imgTrack); if (add_mode) { btnAddMode.Text = "Delete Segments"; cLBDeleteSegments.Visible = false; btnDeleteSelected.Visible = false; } else { // never currently happens btnAddMode.Text = "Add Segments"; populateLB(); cLBDeleteSegments.Visible = true; btnDeleteSelected.Visible = true; } redo_Track(); Invalidate(); Update(); } private void btnAddMode_Click(object sender, EventArgs e) { add_mode = !add_mode; // toggle it if (add_mode) // get rid of listbox items and prepare to add { cLBDeleteSegments.Items.Clear(); redo_Track(); btnAddMode.Text = "Delete Segments"; cLBDeleteSegments.Visible = false; btnDeleteSelected.Visible = false; } else { // populate the listbox and prepare to delete pCount = 0; btnAddMode.Text = "Add Segments"; populateLB(); cLBDeleteSegments.Visible = true; btnDeleteSelected.Visible = true; } } private void cLBDeleteSegments_ItemCheck(object sender, ItemCheckEventArgs e) { if ( !cLBDeleteSegments.GetItemChecked(e.Index)) // not currently checked but will be checked when event finishes { // if it's checked, "highlight" it Pen p = new Pen(Brushes.Orange, 3); drawCurve(p, myTrack[e.Index]); } else { // make it look normal redo_Track(); draw_highlighted(e.Index); // need to send this since the selected index // value doesn't change until AFTER this event } Invalidate(); Update(); } private void btnDeleteSelected_Click(object sender, EventArgs e) { if (!add_mode) // only do it if we're in delete mode { if (cLBDeleteSegments.CheckedItems.Count == num_segments) { // don't bother looping if they're all deleted, just get rid of them num_segments = 0; } else { // loop through and get the ones we want gone // shift others up to fill holes trackStructure[] temp = new trackStructure[num_segments]; int j = 0; for(int i=0; i