private Gates.Terminal CreateTerminal(Dictionary <int, Gates.AbstractGate> gid, XElement terminal) { Gates.Terminal t = new Gates.Terminal( int.Parse(terminal.Attribute("Port").Value), gid[int.Parse(terminal.Attribute("ID").Value)]); return(t); }
public ConnectWire(Gates.Circuit c, Gates.Terminal origin, Gates.Terminal dest) { this.c = c; this.origin = origin; this.dest = dest; c.ReplaceGates += (sender2, e2) => { if (e2.ContainsKey(origin.gate) && e2[origin.gate] != null) { origin.gate = e2[origin.gate]; } if (e2.ContainsKey(dest.gate) && e2[dest.gate] != null) { dest.gate = e2[dest.gate]; } }; }
private UndoRedo.IUndoable Flatten(UIGates.IC ic) { GateCanvas icgc = new GateCanvas((UIGates.IC)ic, icl); UndoRedo.Transaction undo_inline = new UndoRedo.Transaction("Inline Circuit"); // step 1. make room for the circuit // NOTE: exclude user i/o gates // because these will be removed anyways! Rect bounds = GetBounds(icgc.gates.Values.Where(g => !(g is UIGates.UserIO)), 0); foreach (Gate g in gates.Values) { if (g.Margin.Left > ic.Margin.Left || g.Margin.Top > ic.Margin.Top) { Point origin = new Point(g.Margin.Left, g.Margin.Top); double left = g.Margin.Left; double top = g.Margin.Top; if (g.Margin.Left > ic.Margin.Left && bounds.Width - ic.Width > 0) left += bounds.Width - ic.Width; if (g.Margin.Top > ic.Margin.Top && bounds.Height - ic.Height > 0) top += bounds.Height - ic.Height; g.Margin = new Thickness(left, top, 0, 0); ((GateLocation)g.Tag).x = left; ((GateLocation)g.Tag).y = top; undo_inline.Add(new UndoRedo.MoveGate(g, this, origin, new Point(g.Margin.Left, g.Margin.Top))); } } // steps 2 and 3. // bring in circuit and connect internal wiring Dictionary<Gate, Gate> newgates; // = new Dictionary<Gate, Gate>(); undo_inline.Add(AddGates(icgc, new Point(-bounds.Left + ic.Margin.Left, -bounds.Top + ic.Margin.Top), out newgates)); // step 4. connect external wiring Gates.IC gic = ic.AbGate as Gates.IC; // step 4a. connect inputs for (int i = 0; i < gic.NumberOfInputs; i++) { // for each input, find out which circuits within the ic // it is connected to List<Gates.Terminal> targets = gic.Circuit.GetTargets(new Gates.Terminal(0, gic.Inputs[i])); // and this particular ic input, what supplies it from outside the ic? Gates.Terminal source = c.GetSource(new Gates.Terminal(i, gic)); // then disconnect those inputs // and connect it them from the outer foreach (Gates.Terminal t in targets) { Gates.Terminal tt = new Gates.Terminal(t.portNumber, newgates[icgc.FindGate(t.gate)].AbGate); undo_inline.Add(new UndoRedo.Reverse(new UndoRedo.ConnectWire(c, c.GetSource(tt), tt))); c.Disconnect(tt); if (source != null) { c[tt] = source; undo_inline.Add(new UndoRedo.ConnectWire(c, source, tt)); } } } // step 4b. connect outputs for (int i = 0; i < gic.Output.Length; i++) { // for each output, find out which circuit within the ic // it comes from Gates.Terminal source = gic.Circuit.GetSource(new Gates.Terminal(0, gic.Outputs[i])); // translate into our circuit if (source != null) { source = new Gates.Terminal(source.portNumber, newgates[icgc.FindGate(source.gate)].AbGate); } // and this particular output supplies which sources in our circuit? List<Gates.Terminal> targets = c.GetTargets(new Gates.Terminal(i, gic)); // then disconnect those inputs // and connect it them from the outer foreach (Gates.Terminal t in targets) { undo_inline.Add(new UndoRedo.Reverse(new UndoRedo.ConnectWire(c, c.GetSource(t), t))); c.Disconnect(t); if (source != null) { c[t] = source; undo_inline.Add(new UndoRedo.ConnectWire(c, source, t)); } } } // step 5. delete user i/o and ic ClearSelection(); for (int i = 0; i < gic.NumberOfInputs; i++) { selected.Add(newgates[icgc.FindGate(gic.Inputs[i])]); } for (int i = 0; i < gic.Outputs.Length; i++) { selected.Add(newgates[icgc.FindGate(gic.Outputs[i])]); } selected.Add(ic); undo_inline.Add(DeleteSelectedGates()); // step 6. set selection to newly inlined gates ClearSelection(); foreach (Gate g in newgates.Values) { if (!(g is UIGates.UserIO)) { selected.Add(g); g.Selected = true; } } return undo_inline; }
/// <summary> /// Add all gates from a given canvas into our canvas at the selected offset. /// A clone of each gate will be made, both at the visual and internal level. /// A map will be produced indicated the relationship between the gates in the original /// canvas and the gates added to this canvas. /// </summary> /// <param name="icgc"></param> /// <param name="offset"></param> /// <param name="gatemap"></param> /// <returns></returns> protected UndoRedo.Transaction AddGates(GateCanvas icgc, Point offset, out Dictionary<Gate, Gate> gatemap) { UndoRedo.Transaction addgates = new UndoRedo.Transaction("Add Gates"); gatemap = new Dictionary<Gate, Gate>(); // step 1. bring the circuit in foreach (Gate g in icgc.gates.Values) { gatemap[g] = g.CreateUserInstance(); AddGate(gatemap[g], new GateLocation(offset.X + g.Margin.Left, g.Margin.Top + offset.Y, ((RotateTransform)g.RenderTransform).Angle)); addgates.Add(new UndoRedo.AddGate(this, gatemap[g])); } // step 2. connect internal wiring foreach (ConnectedWire cw in icgc.wires.Values) { Gates.Terminal target = new Gates.Terminal(cw.DestTerminalID.ID, gatemap[icgc.FindGate(cw.DestinationGate)].AbGate); Gates.Terminal source = new Gates.Terminal(cw.OriginTerminalID.ID, gatemap[icgc.FindGate(cw.OriginGate)].AbGate); c[target] = source; addgates.Add(new UndoRedo.ConnectWire(c, source, target)); } return addgates; }
/// <summary> /// Add a pre-existing visual gate at a particular location. The gate will also /// be added to the circuit if it is not already a member. /// </summary> /// <param name="uigate"></param> /// <param name="pos"></param> public void AddGate(Gate uigate, GateLocation pos) { Gates.AbstractGate gate = uigate.AbGate; gates[gate] = uigate; uigate.Margin = new Thickness(pos.x, pos.y, 0, 0); GC.Children.Add(uigate); if (!c.Contains(gate)) c.Add(gate); uigate.RenderTransform = new RotateTransform(pos.angle, uigate.Width / 2.0, uigate.Height / 2.0); uigate.Tag = new GateLocation() { x = pos.x, y = pos.y, angle = pos.angle }; // NOTE that we need a separate angle and transform // for the snap-to to work properly // so I am using the tag to store the angle uigate.MouseDown += new MouseButtonEventHandler(uigate_MouseDown); uigate.MouseUp += new MouseButtonEventHandler(uigate_MouseUp); if (uigate is UIGates.IC) { uigate.MouseDoubleClick += new MouseButtonEventHandler(uigate_MouseDoubleClick); uigate.ContextMenu = new ContextMenu(); MenuItem inline = new MenuItem(); inline.Header = "Inline Circuit"; inline.Tag = uigate; uigate.ContextMenu.Items.Add(inline); inline.Click += new RoutedEventHandler(inline_Click); uigate.ContextMenu.IsEnabled = !IsReadOnly; } // can add inputs if (uigate.AbGate is Gates.IVariableInputs) { uigate.ContextMenu = new ContextMenu(); MenuItem addInput = new MenuItem(); addInput.Header = "Add Input"; addInput.Tag = uigate; uigate.ContextMenu.Items.Add(addInput); addInput.Click += (sender2, e2) => { Gates.AbstractGate newgate = ((Gates.IVariableInputs)uigate.AbGate).Clone(uigate.AbGate.NumberOfInputs + 1); c.ReplaceGate(uigate.AbGate, newgate); if (UndoProvider != null) UndoProvider.Add(new UndoRedo.ChangeNumInputs(c, uigate.AbGate, newgate)); }; if (uigate.AbGate.NumberOfInputs > 2) { MenuItem removeInput = new MenuItem(); removeInput.Header = "Remove Input"; removeInput.Tag = uigate; uigate.ContextMenu.Items.Add(removeInput); removeInput.Click += (sender2, e2) => { UndoRedo.Transaction removeInp = new GatesWpf.UndoRedo.Transaction("Remove Input"); // remember wires connected to removed input Gates.Terminal dest = new Gates.Terminal(uigate.AbGate.NumberOfInputs - 1, uigate.AbGate); Gates.Terminal origin = c.GetSource(dest); if (origin != null) removeInp.Add(new UndoRedo.Reverse(new UndoRedo.ConnectWire(c, origin, dest))); Gates.AbstractGate newgate = ((Gates.IVariableInputs)uigate.AbGate).Clone(uigate.AbGate.NumberOfInputs - 1); c.ReplaceGate(uigate.AbGate, newgate); removeInp.Add(new UndoRedo.ChangeNumInputs(c, uigate.AbGate, newgate)); if (UndoProvider != null) UndoProvider.Add(removeInp); }; } uigate.ContextMenu.IsEnabled = !IsReadOnly; } if (uigate is UIGates.UserIO) ((UIGates.UserIO)uigate).UndoProvider = UndoProvider; if (uigate is UIGates.Comment) ((UIGates.Comment)uigate).UndoProvider = UndoProvider; SetInfoLine(uigate); }
/// <summary> /// Construct a gate canvas to represent a given IC. The location hints /// within the IC are used to create and position visual gates equivalent to the /// circuit in the IC. /// </summary> /// <param name="ic"></param> /// <param name="icl"></param> public GateCanvas(UIGates.IC ic, ICList icl) : this(((Gates.IC)ic.AbGate).Circuit, icl) { ICName = ic.AbGate.Name; foreach (KeyValuePair<Gates.AbstractGate, GateLocation> gp in ic.locationHints) { if (gp.Key is Gates.IC) { // must get terminal id template UIGates.IC templateic = icl.GetIC(gp.Key.Name); AddGate(UIGates.IC.CreateFromTemplate( (Gates.IC)gp.Key, templateic), gp.Value); } else AddGate(gp.Key, gp.Value); } // this.Loaded += ((sender, e) => { foreach (KeyValuePair<Gates.AbstractGate, GateLocation> gp in ic.locationHints) { for (int i = 0; i < gp.Key.NumberOfInputs; i++) { Gates.Terminal inp = new Gates.Terminal(i, gp.Key); if (c.GetSource(inp) != null) { c_CircuitConnection(c, inp, c.GetSource(inp)); } } } }//); this.Loaded += (sender, e) => { UpdateWireConnections(); }; }
private void uigate_MouseUp(object sender, MouseButtonEventArgs e) { if (dragging == DragState.CONNECT_FROM || dragging == DragState.CONNECT_TO) { foreach (Gate.TerminalID tid in (Gate)sender) { if (tid.t.IsMouseOver) { Gates.Terminal origin = null, dest = null; if (tid.isInput && dragging == DragState.CONNECT_FROM && !wires.ContainsKey(new Gates.Terminal(tid.ID, tid.abgate))) { origin = new Gates.Terminal(beginTID.ID, beginTID.abgate); dest = new Gates.Terminal(tid.ID, tid.abgate); } if (!tid.isInput && dragging == DragState.CONNECT_TO) { origin = new Gates.Terminal(tid.ID, tid.abgate); dest = new Gates.Terminal(beginTID.ID, beginTID.abgate); } if (origin != null) { c[dest] = origin; UndoRedo.ConnectWire cw = new UndoRedo.ConnectWire(c, origin, dest); if (UndoProvider != null) UndoProvider.Add(cw); } } } } }
private Gates.Terminal CreateTerminal(Dictionary<int, Gates.AbstractGate> gid, XElement terminal) { Gates.Terminal t = new Gates.Terminal( int.Parse(terminal.Attribute("Port").Value), gid[int.Parse(terminal.Attribute("ID").Value)]); return t; }
/// <summary> /// Create an XML representation of a given IC. Nested ICs will be referenced, /// but not created by this method. /// </summary> /// <param name="cc"></param> /// <returns></returns> public XElement CreateCircuitXML(UIGates.IC cc) { XElement circuit = new XElement("Circuit"); circuit.SetAttributeValue("Name", cc.AbGate.Name); XElement gates = new XElement("Gates"); Dictionary <Gates.AbstractGate, int> gid = new Dictionary <Gates.AbstractGate, int>(); int cid = 1; Gates.Circuit circ = ((Gates.IC)cc.AbGate).Circuit; foreach (Gates.AbstractGate g in circ) { XElement gt = new XElement("Gate"); gt.SetAttributeValue("Type", g.GetType().Name); gt.SetAttributeValue("Name", g.Name); gt.SetAttributeValue("ID", cid); gt.Add(new XElement("Point")); gt.Element("Point").SetAttributeValue("X", cc.locationHints[g].X); gt.Element("Point").SetAttributeValue("Y", cc.locationHints[g].Y); gt.Element("Point").SetAttributeValue("Angle", cc.locationHints[g].Angle); if (g is Gates.IVariableInputs) { gt.SetAttributeValue("NumInputs", g.NumberOfInputs); } if (g is Gates.IOGates.AbstractNumeric) { gt.SetAttributeValue("Bits", ((Gates.IOGates.AbstractNumeric)g).Bits); gt.SetAttributeValue("SelRep", (int)(((Gates.IOGates.AbstractNumeric)g).SelectedRepresentation)); gt.SetAttributeValue("Value", ((Gates.IOGates.AbstractNumeric)g).Value); } if (g is Gates.IOGates.Clock) { gt.SetAttributeValue("Milliseconds", ((Gates.IOGates.Clock)g).Milliseconds); } if (g is Gates.IOGates.Comment) { gt.Add(new XElement("Comment", ((Gates.IOGates.Comment)g).Value)); } gates.Add(gt); gid.Add(g, cid); cid++; } XElement wires = new XElement("Wires"); foreach (Gates.AbstractGate g in circ) { for (int i = 0; i < g.NumberOfInputs; i++) { Gates.Terminal t = circ.GetSource(new Gates.Terminal(i, g)); if (t != null) { XElement wire = new XElement("Wire", new XElement("From"), new XElement("To")); wire.Element("From").SetAttributeValue("ID", gid[t.gate]); wire.Element("From").SetAttributeValue("Port", t.portNumber); wire.Element("To").SetAttributeValue("ID", gid[g]); wire.Element("To").SetAttributeValue("Port", i); wires.Add(wire); } } } circuit.Add(gates); circuit.Add(wires); return(circuit); }