Example #1
0
        public ConnectedWire(Gates.AbstractGate originGate, Gate.TerminalID origin, Gates.AbstractGate destGate, Gate.TerminalID dest)
            :base()
        {
            if (origin.isInput || !dest.isInput)
            {
                throw new ArgumentException("Can only connect output (origin) to input (dest)");
            }

            Value = false;
            this.originGate = originGate;
            this.destGate = destGate;
            this.origin = origin;
            this.dest = dest;
            //originGate.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(originGate_PropertyChanged);
            originGate.PropertyChanged += EventDispatcher.CreateBatchDispatchedHandler(originGate, originGate_PropertyChanged);

            Connect();
        }
Example #2
0
        public void circuitInkCanvas_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            // only come here if the uigate doesn't handle it
            ClearSelection();

            Point mp2 = e.GetPosition(circuitInkCanvas);
            sp = new Point(mp2.X, mp2.Y);

            ReadyToSelect = true;
            onGateStroke = false;
        
            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)
                    {
                        onGateStroke = true;

                        uigate_MouseDown(g, e);

                        if (dragging == DragState.MOVE)
                        {
                            if (g is UIGates.UserInput)
                            {
                                UIGates.UserInput temp = g as UIGates.UserInput;
                                temp.r_MouseDown(this, e);
                            }
                        }
                        break;
                    }
                }

            }

            if (sender is ConnectedWire)
            {
                onWireStroke = true;
                //Debug.WriteLine("HitTest Wire start at " + mp2.ToString());

                ConnectedWire myWire = sender as ConnectedWire;

                Gate.TerminalID tid = myWire.OriginTerminalID;

                // 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)))
                    
                    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);

                //if (dragging == DragState.MOVE)
                //{
                //    if (g is UIGates.UserInput)
                //    {
                //        UIGates.UserInput temp = g as UIGates.UserInput;
                //        temp.r_MouseDown(this, e);
                //    }
                //}
                //break;
            }

            e.Handled = true;
        }
Example #3
0
        /*
        void circuitInkCanvas_StylusMove(object sender, StylusEventArgs e)
        {
            if (IsReadOnly)
                return;

            TimeSpan ts = _stopWatch.Elapsed;
            if (ts.TotalSeconds - _lastElapsedSecs> 2)
            {
                _stopWatch.Stop();
                _stopWatch = Stopwatch.StartNew();
                MessageBox.Show("Popup");
            }

            Point mp2 = e.GetPosition(circuitInkCanvas);

            circuitInkCanvas.BringIntoView(new Rect(new Point(mp2.X - 10, mp2.Y - 10),
                new Point(mp2.X + 10, mp2.Y + 10)));

            switch (dragging)
            {
                case DragState.CONNECT_FROM:
                    dragWire.Destination = mp2;
                    break;
                case DragState.CONNECT_TO:
                    dragWire.Origin = mp2;
                    break;
                case DragState.MOVE:
                    #region DragState is Move
                    foreach (Gate g in selected)
                    {
                        //g.RenderTransform = new TranslateTransform(mp2.X, mp2.Y);
                        //Direct Move
                        
                            double dx = mp2.X - mp.X;
                            double dy = mp2.Y - mp.Y;
                            ((GateLocation)g.Tag).x = ((GateLocation)g.Tag).x + dx;
                            ((GateLocation)g.Tag).y = ((GateLocation)g.Tag).y + dy;
                            double cx = ((GateLocation)g.Tag).x % GRID_SIZE;
                            double cy = ((GateLocation)g.Tag).y % GRID_SIZE;

                            Point op = new Point(g.Margin.Left, g.Margin.Top);

                            if ((Math.Abs(cx) < DELTA_SNAP || Math.Abs(GRID_SIZE - cx) < DELTA_SNAP) &&
                                (Math.Abs(cy) < DELTA_SNAP || Math.Abs(GRID_SIZE - cy) < DELTA_SNAP))
                            {
                                g.Margin = new Thickness(Math.Round(g.Margin.Left / GRID_SIZE) * GRID_SIZE,
                                    Math.Round(g.Margin.Top / GRID_SIZE) * GRID_SIZE, 0, 0);

                            }
                            else
                            {
                                g.Margin = new Thickness(((GateLocation)g.Tag).x, ((GateLocation)g.Tag).y, 0, 0);
                            }

                            Point np = new Point(g.Margin.Left, g.Margin.Top);
                            if (op != np)
                                moves.Add(new UndoRedo.MoveGate(g, this, op, np));

                            SizeCanvas();
                            g.BringIntoView(); // still needed because gate larger than 20px block

                    }

                    UpdateWireConnections();
                    break;
                    #endregion
                case DragState.NONE:
                    #region Drag State is None
                    // not dragging
                    // creating a selection rectangle
                    if (ReadyToSelect)
                    {
                        double x1 = Math.Min(mp2.X, sp.X);
                        double width = Math.Abs(mp2.X - sp.X);

                        double y1 = Math.Min(mp2.Y, sp.Y);
                        double height = Math.Abs(mp2.Y - sp.Y);

                        dragSelect.Margin = new Thickness(x1, y1, 0, 0);
                        dragSelect.Width = width;
                        dragSelect.Height = height;
                        dragSelect.Visibility = Visibility.Visible;

                        // select any gates inside the rectangle
                        Rect select = new Rect(x1, y1, width, height);
                        foreach (Gate g in gates.Values)
                        {
                            Rect grect = new Rect(g.Margin.Left, g.Margin.Top, g.Width, g.Height);
                            if (select.IntersectsWith(grect) && !g.Selected)
                            {
                                g.Selected = true;
                                selected.Add(g);
                            }

                            // this is not the same as just "not" or else the above
                            if (!select.IntersectsWith(grect) && g.Selected)
                            {
                                g.Selected = false;
                                selected.Remove(g);
                            }
                        }
                    }
                    break;
                    #endregion
            }
            mp = mp2;
        }
         * 
         * */
        
        /*
        void circuitInkCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (IsReadOnly)
                return;

            TimeSpan ts = _stopWatch.Elapsed;
            if (ts.TotalSeconds - _lastElapsedSecs > 2)
            {
                MessageBox.Show("Popup");
            }

            Point mp2 = e.GetPosition(circuitInkCanvas);

            circuitInkCanvas.BringIntoView(new Rect(new Point(mp2.X - 10, mp2.Y - 10),
                new Point(mp2.X + 10, mp2.Y + 10)));

            switch (dragging)
            {
                case DragState.CONNECT_FROM:
                    dragWire.Destination = mp2;
                    break;
                case DragState.CONNECT_TO:
                    dragWire.Origin = mp2;
                    break;
                case DragState.MOVE:
                    #region DragState is Move
                    foreach (Gate g in selected)
                    {
                        //g.RenderTransform = new TranslateTransform(mp2.X, mp2.Y);
                        //Direct Move
                        if (e.LeftButton == MouseButtonState.Pressed)
                        {
                            double dx = mp2.X - mp.X;
                            double dy = mp2.Y - mp.Y;
                            ((GateLocation)g.Tag).x = ((GateLocation)g.Tag).x + dx;
                            ((GateLocation)g.Tag).y = ((GateLocation)g.Tag).y + dy;
                            double cx = ((GateLocation)g.Tag).x % GRID_SIZE;
                            double cy = ((GateLocation)g.Tag).y % GRID_SIZE;

                            Point op = new Point(g.Margin.Left, g.Margin.Top);

                            if ((Math.Abs(cx) < DELTA_SNAP || Math.Abs(GRID_SIZE - cx) < DELTA_SNAP) &&
                                (Math.Abs(cy) < DELTA_SNAP || Math.Abs(GRID_SIZE - cy) < DELTA_SNAP))
                            {
                                g.Margin = new Thickness(Math.Round(g.Margin.Left / GRID_SIZE) * GRID_SIZE,
                                    Math.Round(g.Margin.Top / GRID_SIZE) * GRID_SIZE, 0, 0);

                            }
                            else
                            {
                                g.Margin = new Thickness(((GateLocation)g.Tag).x, ((GateLocation)g.Tag).y, 0, 0);
                            }

                            Point np = new Point(g.Margin.Left, g.Margin.Top);
                            if (op != np)
                                moves.Add(new UndoRedo.MoveGate(g, this, op, np));

                            SizeCanvas();
                            g.BringIntoView(); // still needed because gate larger than 20px block

                        }
                                               
                    }

                    UpdateWireConnections();
                    break;
                    #endregion
                case DragState.NONE:
                    #region Drag State is None
                        // not dragging
                        // creating a selection rectangle
                        if (ReadyToSelect)
                        {
                            double x1 = Math.Min(mp2.X, sp.X);
                            double width = Math.Abs(mp2.X - sp.X);

                            double y1 = Math.Min(mp2.Y, sp.Y);
                            double height = Math.Abs(mp2.Y - sp.Y);

                            dragSelect.Margin = new Thickness(x1, y1, 0, 0);
                            dragSelect.Width = width;
                            dragSelect.Height = height;
                            dragSelect.Visibility = Visibility.Visible;

                            // select any gates inside the rectangle
                            Rect select = new Rect(x1, y1, width, height);
                            foreach (Gate g in gates.Values)
                            {
                                Rect grect = new Rect(g.Margin.Left, g.Margin.Top, g.Width, g.Height);
                                if (select.IntersectsWith(grect) && !g.Selected)
                                {
                                    g.Selected = true;
                                    selected.Add(g);
                                }

                                // this is not the same as just "not" or else the above
                                if (!select.IntersectsWith(grect) && g.Selected)
                                {
                                    g.Selected = false;
                                    selected.Remove(g);
                                }
                            }
                        }
                        break;
                        #endregion 
            }
            mp = mp2;
        }
         * */

        /*
       void circuitInkCanvas_PreviewStylusDown(object sender, StylusDownEventArgs e)
       {
           if (EditingMode.currentEditingMode != EditingMode.EditingModeType.SketchLogicGate)
           {
               MessageBox.Show("Please Check Sketch Logic Diagram Radio Button", "TIP");
               return;
           }

           _lastElapsedSecs = _stopWatch.Elapsed.TotalSeconds;

           // only come here if the uigate doesn't handle it
           ClearSelection();

           Point mp2 = e.GetPosition(circuitInkCanvas);

           sp = new Point(mp2.X, mp2.Y);

           ReadyToSelect = true;

           onGateStroke = false;

           foreach (UIElement gate in circuitInkCanvas.Children)
           {
               if (gate is Gate)
               {
                   Gate g = gate as Gate;
                   Rect grect = new Rect(g.Margin.Left, g.Margin.Top, g.Width, g.Height);
                   if (mp2.X >= grect.Left && mp2.X <= grect.Right
                       && mp2.Y >= grect.Top && mp2.Y <= grect.Bottom)
                   {
                       onGateStroke = true;
                       uigate_MouseDown(g, e);

                       if (dragging == DragState.MOVE)
                       {
                           if (g is UIGates.UserInput)
                           {
                               UIGates.UserInput temp = g as UIGates.UserInput;
                               temp.r_MouseDown(this, e);
                           }
                       }
                       break;
                   }
               }
           }

           e.Handled = true;
       }
       */


        #endregion

        public void circuitInkCanvas_PreviewStylusMove(object sender, StylusEventArgs e)
        {
            if (IsReadOnly)
                return;

            Point mp2 = e.GetPosition(circuitInkCanvas);

            if (sender is ConnectedWire)
            {
                #region connectedWire Object

                onWireMoveStroke = true;

                ConnectedWire myWire = sender as ConnectedWire;

                Gate.TerminalID tid = myWire.OriginTerminalID;

                // 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)))

                    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);

                //if (dragging == DragState.MOVE)
                //{
                //    if (g is UIGates.UserInput)
                //    {
                //        UIGates.UserInput temp = g as UIGates.UserInput;
                //        temp.r_MouseDown(this, e);
                //    }
                //}
                //break;

                return;

                #endregion
            }

            circuitInkCanvas.BringIntoView(new Rect(new Point(mp2.X - 10, mp2.Y - 10),
                new Point(mp2.X + 10, mp2.Y + 10)));

            switch (dragging)
            {
                case DragState.CONNECT_FROM:

                    foreach (UIElement gate in circuitInkCanvas.Children)
                    {
                        if (gate is Gate)
                        {
                            Gate g = gate as Gate;
                            foreach (Gate.TerminalID tid in g)
                            {
                                tid.t.Background = Brushes.Transparent;
                            }
                         }
                    }
                   
                    // gate termination indication
                    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)
                            {
                                Rect gRect = new Rect(g.Margin.Left, g.Margin.Top, g.Width, g.Height);

                                foreach (Gate.TerminalID tid in g)
                                {
                                    Rect tRect = GetTerminalBounds(g, grect, tid);
                                    condition = tRect.Contains(mp2);
                                    if (condition)
                                    {
                                        tid.t.Background = Brushes.Yellow;
                                    }else
                                    {
                                        tid.t.Background = Brushes.Transparent;
                                    }
                                }
                            }
                        }
                    }
                    dragWire.Destination = mp2;
                    break;
                case DragState.CONNECT_TO:
                     foreach (UIElement gate in circuitInkCanvas.Children)
                    {
                        if (gate is Gate)
                        {
                            Gate g = gate as Gate;
                            foreach (Gate.TerminalID tid in g)
                            {
                                tid.t.Background = Brushes.Transparent;
                            }
                         }
                    }
                   
                    // gate termination indication
                    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)
                            {
                                Rect gRect = new Rect(g.Margin.Left, g.Margin.Top, g.Width, g.Height);

                                foreach (Gate.TerminalID tid in g)
                                {
                                    Rect tRect = GetTerminalBounds(g, grect, tid);
                                    condition = tRect.Contains(mp2);
                                    if (condition)
                                    {
                                        tid.t.Background = Brushes.Yellow;
                                    }else
                                    {
                                        tid.t.Background = Brushes.Transparent;
                                    }
                                }
                            }
                        }
                    }
                    dragWire.Origin = mp2;
                    break;
                case DragState.MOVE:
                    #region DragState is Move

                    foreach (Gate g in selected)
                    {
                        //g.RenderTransform = new TranslateTransform(mp2.X, mp2.Y);
                        //Direct Move

                        double dx = mp2.X - mp.X;
                        double dy = mp2.Y - mp.Y;
                        ((GateLocation)g.Tag).x = ((GateLocation)g.Tag).x + dx;
                        ((GateLocation)g.Tag).y = ((GateLocation)g.Tag).y + dy;
                        double cx = ((GateLocation)g.Tag).x % GRID_SIZE;
                        double cy = ((GateLocation)g.Tag).y % GRID_SIZE;

                        Point op = new Point(g.Margin.Left, g.Margin.Top);

                        if ((Math.Abs(cx) < DELTA_SNAP || Math.Abs(GRID_SIZE - cx) < DELTA_SNAP) &&
                            (Math.Abs(cy) < DELTA_SNAP || Math.Abs(GRID_SIZE - cy) < DELTA_SNAP))
                        {
                            g.Margin = new Thickness(Math.Round(g.Margin.Left / GRID_SIZE) * GRID_SIZE,
                                Math.Round(g.Margin.Top / GRID_SIZE) * GRID_SIZE, 0, 0);

                        }
                        else
                        {
                            g.Margin = new Thickness(((GateLocation)g.Tag).x, ((GateLocation)g.Tag).y, 0, 0);
                        }

                        Point np = new Point(g.Margin.Left, g.Margin.Top);
                        if (op != np)
                            moves.Add(new UndoRedo.MoveGate(g, this, op, np));

                        SizeCanvas();
                        g.BringIntoView(); // still needed because gate larger than 20px block

                    }

                    UpdateWireConnections();
                    break;
                    #endregion
                case DragState.NONE:
                    #region Drag State is None
                    // not dragging
                    // creating a selection rectangle
                    if (ReadyToSelect)
                    {
                        double x1 = Math.Min(mp2.X, sp.X);
                        double width = Math.Abs(mp2.X - sp.X);

                        double y1 = Math.Min(mp2.Y, sp.Y);
                        double height = Math.Abs(mp2.Y - sp.Y);

                        //dragSelect.Margin = new Thickness(x1, y1, 0, 0);
                        //dragSelect.Width = width;
                        //dragSelect.Height = height;
                        //dragSelect.Visibility = Visibility.Visible;

                        // select any gates inside the rectangle
                        Rect select = new Rect(x1, y1, width, height);
                        foreach (Gate g in gates.Values)
                        {
                            Rect grect = new Rect(g.Margin.Left, g.Margin.Top, g.Width, g.Height);
                            if (select.IntersectsWith(grect) && !g.Selected)
                            {
                                g.Selected = true;
                                selected.Add(g);
                            }

                            // this is not the same as just "not" or else the above
                            if (!select.IntersectsWith(grect) && g.Selected)
                            {
                                g.Selected = false;
                                selected.Remove(g);
                            }
                        }
                    }
                    break;
                    #endregion
            }

            mp = mp2;
        }
Example #4
0
        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;
        }
Example #5
0
        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;

        }