public void circuitInkCanvas_StylusUp(object sender, StylusEventArgs e) { if (IsPieMenuVisible) { PieMenuHitTestEventArgs hitargs = new PieMenuHitTestEventArgs(e.GetPosition(this), e, PieMenuHitTestEventArgs.EventType.Up); hitPieMenuHandler(this, hitargs); } //Make Pie Menu Invisible PieMenuEventArgs args = new PieMenuEventArgs(false); triggerPieMenuHandler(this, args); Point mp2 = e.GetPosition(circuitInkCanvas); foreach (UIElement gate in circuitInkCanvas.Children) { if (gate is Gate) { Gate g = gate as Gate; Rect grect = new Rect(g.Margin.Left - 10, g.Margin.Top - 10, g.Width + 10, g.Height + 10); bool condition = false; condition = grect.Contains(mp2); if (condition) { uigate_StylusUp(g ,e); break; } }else if(gate is ConnectedWire) { HitTestResult result = VisualTreeHelper.HitTest(gate, mp2); if(result != null) { Debug.WriteLine("Hit Test Wire circuitInkCanvas_StylusUp"); //Image stroke starts from one terminal and stop at this wire //1. through this wire, create new wire to connect existing wire's //if stroke starts from input terminal from one gate, then search for input terminal from existing wire. //otherwise stroke starts from the output termianl from one gate, then search for output terminal from existing wire. ConnectedWire myWire = gate as ConnectedWire; //new wire's destination is mp2; new wire's orignal is ??? if (onGateStroke) { //start the stroke from gate terminal Gate.TerminalID tid = myWire.OriginTerminalID; 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); } } break; } } } dragging = DragState.NONE; //dragSelect.Width = 0; //dragSelect.Height = 0; //dragSelect.Margin = new Thickness(0, 0, 0, 0); //dragSelect.Visibility = Visibility.Hidden; dragWire.Destination = new Point(0, 0); dragWire.Origin = new Point(0, 0); // unhightlight all foreach (Gates.AbstractGate ag in gates.Keys) { for (int i = 0; i < ag.Output.Length; i++) { gates[ag].FindTerminal(false, i).t.Highlight = false; } for (int i = 0; i < ag.NumberOfInputs; i++) { gates[ag].FindTerminal(true, i).t.Highlight = false; } } if (UndoProvider != null && moves != null && moves.Count > 0) UndoProvider.Add(moves); moves = null; ReadyToSelect = false; }
/// <summary> /// Moves all gates so that the upper edge of the bounds is along the top, /// and the left edge of the bounds is along the left. /// </summary> public void AlignUpperLeft() { Rect r = GetBounds(0, false); UndoRedo.Transaction align = new UndoRedo.Transaction("Align Gates to Upper-Left"); ; foreach (Gate g in gates.Values) { Point origin = new Point(g.Margin.Left, g.Margin.Top); Point dest = new Point(g.Margin.Left - r.Left, g.Margin.Top - r.Top); g.Margin = new Thickness(dest.X, dest.Y, 0, 0); ((GateLocation)g.Tag).x = dest.X; ((GateLocation)g.Tag).y = dest.Y; UndoRedo.MoveGate mg = new UndoRedo.MoveGate(g, this, origin, dest); align.Add(mg); } if (UndoProvider != null) UndoProvider.Add(align); UpdateLayout(); UpdateWireConnections(); }
void uigate_MouseDown(object sender, MouseButtonEventArgs e) { Point mp2 = e.GetPosition(circuitInkCanvas); if (IsReadOnly) return; Gate tg = (Gate)sender; // to avoid sticking on other gates, move this one to the top circuitInkCanvas.Children.Remove(tg); circuitInkCanvas.Children.Add(tg); if (!tg.Selected) { selected.Add(tg); ((GateLocation)tg.Tag).x = tg.Margin.Left; ((GateLocation)tg.Tag).y = tg.Margin.Top; tg.Selected = true; } Rect gRect = new Rect(tg.Margin.Left, tg.Margin.Top, tg.Width, tg.Height); foreach (Gate.TerminalID tid in tg) { Rect tRect = GetTerminalBounds(tg, gRect, tid); bool condition = tRect.Contains(mp2); // if (tid.t.IsMouseOver) //if (mp2.X >= tRect.Value.Left - 10 && mp2.X <= tRect.Value.Right + 10 // && mp2.Y >= tRect.Value.Top - 10 && mp2.Y <= tRect.Value.Bottom + 10) if(condition) { // ok, so are we connecting to or from // is this an input or output? if (tid.isInput) { // can only connect from an input // if there is no other connection here if (wires.ContainsKey(new Gates.Terminal(tid.ID, tid.abgate))) continue; dragging = DragState.CONNECT_TO; dragWire.Value = false; // highlight all terminals which provide output foreach (Gates.AbstractGate ag in gates.Keys) { for (int i = 0; i < ag.Output.Length; i++) { gates[ag].FindTerminal(false, i).t.Highlight = true; } } } else { dragging = DragState.CONNECT_FROM; // TODO: if the value of the output changes // while being dragged, this won't update dragWire.Value = tid.abgate.Output[tid.ID]; // highlight all terminals which accept input // note this is all inputs NOT already connected foreach (Gates.AbstractGate ag in gates.Keys) { for (int i = 0; i < ag.NumberOfInputs; i++) { if (c.GetSource(new Gates.Terminal(i, ag)) == null) gates[ag].FindTerminal(true, i).t.Highlight = true; } } } beginTID = tid; dragWire.Destination = tid.t.TranslatePoint(new Point(5, 5), circuitInkCanvas); dragWire.Origin = tid.t.TranslatePoint(new Point(5, 5), circuitInkCanvas); e.Handled = true; return; } } dragging = DragState.MOVE; moves = new UndoRedo.Transaction( (e.LeftButton == MouseButtonState.Pressed ? "Move" : "Rotate") + " " + (selected.Count == 1 ? "Gate" : selected.Count.ToString() + " Gates")); e.Handled = true; }
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> /// Copies the contents of the given IC into this canvas at a slight offset /// from its original location hinted positions. This creates an undo action. /// </summary> /// <param name="ic"></param> public void PasteIC(UIGates.IC ic) { // +32 so they don't appear right on top of the originals Point offset = new Point(32, 32); Dictionary<Gate, Gate> blah; ClearSelection(); UndoRedo.IUndoable paste = AddGates(new GateCanvas(ic, icl), offset, out blah); foreach (Gate g in blah.Values) { g.Selected = true; selected.Add(g); } if (UndoProvider != null) { // use a transaction as a wrapper to change the name // to paste instead of add UndoRedo.Transaction pt = new UndoRedo.Transaction("Paste " + paste.Name.Substring(4)); // 4 is "Add " pt.Add(paste); UndoProvider.Add(pt); } UpdateLayout(); UpdateWireConnections(); }
/// <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> /// Recursively flatten this circuit by replacing all ICs within it /// with their contents. Repeat until no ICs remain. /// </summary> public void Flatten() { Queue<UIGates.IC> toFlatten = new Queue<GatesWpf.UIGates.IC>(); UndoRedo.Transaction flatten = new UndoRedo.Transaction("Flatten All"); do { while (toFlatten.Count > 0) flatten.Add(Flatten(toFlatten.Dequeue())); foreach (Gate g in gates.Values) { if (g is UIGates.IC) { toFlatten.Enqueue(g as UIGates.IC); } } } while (toFlatten.Count > 0); ClearSelection(); UpdateLayout(); UpdateWireConnections(); if (UndoProvider != null) UndoProvider.Add(flatten); }
/// <summary> /// Delete all those gates in the selected list. This returns an /// undo transaction which can be added to an undo manager, /// or folded into a larger transaction. /// </summary> /// <returns></returns> public UndoRedo.IUndoable DeleteSelectedGates() { if (selected.Count == 0) return new UndoRedo.Transaction("Delete 0 gates"); UndoRedo.Transaction del = new UndoRedo.Transaction("Delete " + (selected.Count == 1 ? "gate" : (selected.Count.ToString() + " gates"))); foreach (Gate g in selected) { // have to remember all its connections // check all this gate's inputs for (int i = 0; i < g.AbGate.NumberOfInputs; i++) { Gates.Terminal t = c.GetSource(new Gates.Terminal(i, g.AbGate)); if (t != null) { del.Add(new UndoRedo.Reverse(new UndoRedo.ConnectWire(c, t, new Gates.Terminal(i, g.AbGate)))); } } // and all outputs, BUT // avoid getting in trouble with recursive connections for (int i = 0; i < g.AbGate.Output.Length; i++) { List<Gates.Terminal> outs = c.GetTargets(new Gates.Terminal(i, g.AbGate)); foreach (Gates.Terminal t in outs) { if (g.AbGate != t.gate) del.Add(new UndoRedo.Reverse(new UndoRedo.ConnectWire(c, new Gates.Terminal(i, g.AbGate), t))); } } del.Add(new UndoRedo.Reverse(new UndoRedo.AddGate(this, g))); RemoveGate(g); } oldgatepositions.Clear(); // just used for gate replacement ClearSelection(); return del; }
private void uigate_MouseDown(object sender, MouseButtonEventArgs e) { if (IsReadOnly) return; Gate tg = (Gate)sender; // to avoid sticking on other gates, move this one to the top GC.Children.Remove(tg); GC.Children.Add(tg); if (!tg.Selected) { // can use ctrl or alt to multi-select if (Keyboard.Modifiers == ModifierKeys.None) ClearSelection(); selected.Add(tg); ((GateLocation)tg.Tag).x = tg.Margin.Left; ((GateLocation)tg.Tag).y = tg.Margin.Top; tg.Selected = true; } foreach (Gate.TerminalID tid in tg) { if (tid.t.IsMouseOver) { // ok, so are we connecting to or from // is this an input or output? if (tid.isInput) { // can only connect from an input // if there is no other connection here if (wires.ContainsKey(new Gates.Terminal(tid.ID, tid.abgate))) continue; dragging = DragState.CONNECT_TO; dragWire.Value = false; // highlight all terminals which provide output foreach (Gates.AbstractGate ag in gates.Keys) { for (int i = 0; i < ag.Output.Length; i++) { gates[ag].FindTerminal(false, i).t.Highlight = true; } } } else { dragging = DragState.CONNECT_FROM; // TODO: if the value of the output changes // while being dragged, this won't update dragWire.Value = tid.abgate.Output[tid.ID]; // highlight all terminals which accept input // note this is all inputs NOT already connected foreach (Gates.AbstractGate ag in gates.Keys) { for (int i = 0; i < ag.NumberOfInputs; i++) { if (c.GetSource(new Gates.Terminal(i, ag)) == null) gates[ag].FindTerminal(true, i).t.Highlight = true; } } } beginTID = tid; dragWire.Destination = tid.t.TranslatePoint(new Point(5, 5), GC); dragWire.Origin = tid.t.TranslatePoint(new Point(5, 5), GC); e.Handled = true; return; } } dragging = DragState.MOVE; moves = new UndoRedo.Transaction( (e.LeftButton == MouseButtonState.Pressed ? "Move" : "Rotate") + " " + (selected.Count == 1 ? "Gate" : selected.Count.ToString() + " Gates")); e.Handled = true; }
private void GateCanvas_MouseUp(object sender, MouseButtonEventArgs e) { dragging = DragState.NONE; dragSelect.Width = 0; dragSelect.Height = 0; dragSelect.Margin = new Thickness(0, 0, 0, 0); dragSelect.Visibility = Visibility.Hidden; dragWire.Destination = new Point(0, 0); dragWire.Origin = new Point(0, 0); // unhightlight all foreach (Gates.AbstractGate ag in gates.Keys) { for (int i = 0; i < ag.Output.Length; i++) { gates[ag].FindTerminal(false, i).t.Highlight = false; } for (int i = 0; i < ag.NumberOfInputs; i++) { gates[ag].FindTerminal(true, i).t.Highlight = false; } } if (UndoProvider != null && moves != null && moves.Count > 0) UndoProvider.Add(moves); moves = null; ReadyToSelect = false; }
private void Window1_EditFull_KeyDown(object sender, KeyEventArgs e) { // delete all selected gates if (e.Key == Key.Delete) { gateCanvas.UndoProvider.Add(gateCanvas.DeleteSelectedGates()); } if (e.Key == Key.Escape) { DragDrop.DragDropHelper.Cancel(); } if (Keyboard.Modifiers == ModifierKeys.Control) { // the control shortcuts // because our toolbar are image not text if (e.Key == Key.N && MyEditLevel == EditLevel.FULL) { btnNew_Click(sender, e); } if (e.Key == Key.O && MyEditLevel == EditLevel.FULL) { btnOpen_Click(sender, e); } if (e.Key == Key.S && MyEditLevel == EditLevel.FULL) { if (btnSave.IsEnabled) btnSave_Click(sender, e); else btnSave_As_Click(sender, e); } if (e.Key == Key.X && btnCut.IsEnabled) { btnCut_Click(sender, e); } if (e.Key == Key.C && btnCopy.IsEnabled) { btnCopy_Click(sender, e); } if (e.Key == Key.V && btnPaste.IsEnabled) { btnPaste_Click(sender, e); } if (e.Key == Key.Z && btnUndo.IsEnabled) { btnUndo_Click(sender, e); } if (e.Key == Key.Y && btnRedo.IsEnabled) { btnRedo_Click(sender, e); } if (e.Key == Key.A) { gateCanvas.SelectAll(); } // gate rotation if (e.Key == Key.Right) { KeyRotateGates(90); } if (e.Key == Key.Left) { KeyRotateGates(-90); } } else { // not using ctrl if ((e.Key == Key.Right || e.Key == Key.Left || e.Key == Key.Down || e.Key == Key.Up) && gateCanvas.selected.Count > 0 && moves == null) { moves = new UndoRedo.Transaction("Move " + (gateCanvas.selected.Count == 1 ? "Gate" : gateCanvas.selected.Count.ToString() + " Gates")); } // moving gates if (e.Key == Key.Right) { KeyMoveGates(1, 0); } if (e.Key == Key.Left) { KeyMoveGates(-1, 0); } if (e.Key == Key.Up) { KeyMoveGates(0, -1); } if (e.Key == Key.Down) { KeyMoveGates(0, 1); } } }
protected Window1(EditLevel e) { InitializeComponent(); _myEditLevel = e; EventDispatcher.BatchDispatcher = Dispatcher; gateCanvas.Circuit.Start(); // Everybody gets zoom sbZoom = new ShadowBox(); sbZoom.Margin = new Thickness(20); Grid1.Children.Remove(spZoom); sbZoom.Children.Add(spZoom); spZoom.Background = Brushes.Transparent; sbZoom.VerticalAlignment = VerticalAlignment.Top; sbZoom.HorizontalAlignment = HorizontalAlignment.Right; Grid1.Children.Add(sbZoom); Grid.SetColumn(sbZoom, 1); Grid.SetRow(sbZoom, 1); // everybody gets view keys this.PreviewKeyDown += new KeyEventHandler(Window1_View_KeyDown); Grid1.Children.Remove(spGates); if (e == EditLevel.FULL || e == EditLevel.EDIT) { // delete for edit or full this.PreviewKeyDown += new KeyEventHandler(Window1_EditFull_KeyDown); this.PreviewKeyUp += (s2, e2) => { // add moves if needed if (moves != null) ((UndoRedo.UndoManager)Resources["undoManager"]).Add(moves); moves = null; }; // drag/drop for edit or full DragDrop.DragDropHelper.ItemDropped += new EventHandler<DragDrop.DragDropEventArgs>(DragDropHelper_ItemDropped); // gates for edit or full sbGates = new ShadowBox(); sbGates.Margin = new Thickness(20, 20, 20, 20); sbGates.Children.Add(spGates); spGates.Background = Brushes.Transparent; sbGates.VerticalAlignment = VerticalAlignment.Center; sbGates.HorizontalAlignment = HorizontalAlignment.Left; Grid1.Children.Add(sbGates); Grid.SetColumn(sbGates, 1); Grid.SetRow(sbGates, 1); // edit or full get undo and edit tbUndo.Visibility = Visibility.Visible; tbEdit.Visibility = Visibility.Visible; // monitor the clipboard to provide cut/copy/paste visibility gateCanvas.selected.ListChanged += (s2, e2) => { btnCopy.IsEnabled = gateCanvas.selected.Count > 0; btnCut.IsEnabled = gateCanvas.selected.Count > 0; btnCopyAsImage.IsEnabled = gateCanvas.selected.Count > 0; }; this.Activated += (s2, e2) => { btnPaste.IsEnabled = Clipboard.ContainsData("IC"); }; } Grid1.Children.Remove(spSpeed); if (e == EditLevel.FULL) { // speed only for the main window sbSpeed = new ShadowBox(); sbSpeed.Margin = new Thickness(20, 20, 175, 20); sbSpeed.Children.Add(spSpeed); spSpeed.Background = Brushes.Transparent; sbSpeed.VerticalAlignment = VerticalAlignment.Top; sbSpeed.HorizontalAlignment = HorizontalAlignment.Right; Grid1.Children.Add(sbSpeed); Grid.SetColumn(sbSpeed, 1); Grid.SetRow(sbSpeed, 1); // otherwise the defaults mess it up when you open a new window slSpeed.ValueChanged += (sender2, e2) => { Gates.PropagationThread.SLEEP_TIME = (int)slSpeed.Value; }; // full also gets file and ic tbFile.Visibility = Visibility.Visible; tbIC.Visibility = Visibility.Visible; } if (e == EditLevel.EDIT) { // can't edit the user gates in this view spGates.IsReadOnly = true; } /* this.Loaded += (sender2, e2) => { ((UndoRedo.UndoManager)Resources["undoManager"]).SetSavePoint(); UpdateTitle(); lblAppTitle.Text = APP_TITLE; lblAppVersion.Text = APP_VERSION; lblAppCopyright.Text = APP_COPYRIGHT; }; * * */ this.PreviewMouseWheel += (sender, e2) => { if (e2.Delta > 0) slZoom.Value += 0.1; else slZoom.Value -= 0.1; e2.Handled = true; }; //BOKANG /* ((UndoRedo.UndoManager)Resources["undoManager"]).PropertyChanged += (sender2, e2) => { UpdateTitle(); // look for modified or not }; * * */ //BOKANG //InfoLine.GetInstance().PropertyChanged += InfoLine_PropertyChanged; //BOKANG if (sbSpeed != null) sbSpeed.Visibility = Visibility.Collapsed; if (myToolbarTray != null) myToolbarTray.Visibility = Visibility.Collapsed; spAppInfo.Visibility = Visibility.Collapsed; lblInfoLine.Visibility = Visibility.Collapsed; spGates.Visibility = Visibility.Collapsed; }