Exemplo n.º 1
0
        /// <summary>
        /// Find output pin, if any, at given point</summary>
        /// <param name="element">Element</param>
        /// <param name="g">Graphics object</param>
        /// <param name="p">Point to test</param>
        /// <returns>Output pin hit by p; null otherwise</returns>
        private TPin PickOutput(TElement element, Graphics g, Point p)
        {
            ElementTypeInfo info = GetElementTypeInfo(element, g);

            Point ep    = element.Bounds.Location;
            int   x     = ep.X + info.Size.Width - m_pinSize;
            int   y     = ep.Y + m_rowSpacing + 2 * PinMargin + m_pinOffset;
            int   width = m_pinSize;

            Rectangle bounds        = new Rectangle(x, y, width, m_pinSize);
            int       pickTolerance = m_theme.PickTolerance;

            bounds.Inflate(pickTolerance, pickTolerance);
            ICircuitElementType type = element.Type;

            foreach (TPin output in type.Outputs)
            {
                if (bounds.Contains(p.X, p.Y))
                {
                    return(output);
                }
                bounds.Y += m_rowSpacing;
            }
            return(null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Find input pin, if any, at given point</summary>
        /// <param name="element">Element</param>
        /// <param name="g">Graphics object</param>
        /// <param name="p">Point to test</param>
        /// <returns>Input pin hit by p; null otherwise</returns>
        private TPin PickInput(TElement element, Graphics g, Point p)
        {
            Point ep    = element.Bounds.Location;
            int   x     = ep.X;
            int   y     = ep.Y + m_rowSpacing + 2 * PinMargin + m_pinOffset;
            int   width = m_pinSize;
            //if (IsDraggingWire)
            //{
            //    ElementTypeInfo info = GetElementTypeInfo(element, g);
            //    width = info.Width / 2 - m_pickTolerance;
            //}

            Rectangle bounds        = new Rectangle(x, y, width, m_pinSize);
            int       pickTolerance = m_theme.PickTolerance;

            bounds.Inflate(pickTolerance, pickTolerance);
            ICircuitElementType type = element.Type;

            foreach (TPin input in type.Inputs)
            {
                if (bounds.Contains(p.X, p.Y))
                {
                    return(input);
                }
                bounds.Y += m_rowSpacing;
            }
            return(null);
        }
Exemplo n.º 3
0
        private void DrawGhost(TElement element, Graphics g)
        {
            ElementTypeInfo info   = GetElementTypeInfo(element, g);
            Point           p      = element.Bounds.Location;
            Rectangle       bounds = new Rectangle(p, info.Size);

            // clip to window to speed up drawing when zoomed in
            if (g.ClipBounds.IntersectsWith(bounds))
            {
                if (info.Path == null)
                {
                    ICircuitElementType type = element.Type;
                    BuildGraphics(type, info, g);
                }

                s_pathTransform.Translate(p.X, p.Y);
                info.Path.Transform(s_pathTransform);

                g.FillPath(m_theme.GhostBrush, info.Path);
                g.DrawPath(m_theme.GhostPen, info.Path);

                s_pathTransform.Translate(-2 * p.X, -2 * p.Y);
                info.Path.Transform(s_pathTransform);
                s_pathTransform.Reset();
            }
        }
Exemplo n.º 4
0
 private void DomNodeOnChildRemoving(object sender, ChildEventArgs e)
 {
     if (Validating)
     {
         // removing a module from a sub-circuit?
         Element    element    = e.Child.As <Element>();
         SubCircuit subCircuit = e.Parent.As <SubCircuit>();
         if (element != null &&
             subCircuit != null)
         {
             ICircuitElementType type = element.Type;
             // todo: this test isn't quite right, because not all circuit elements
             //  necessarily have both inputs and outputs. For example, if the Speaker
             //  element from the Circuit Editor sample app is the only element in a Master,
             //  and then it is deleted, that will trigger this exception.
             if (type.Inputs.Count + type.Outputs.Count == 1)
             {
                 // Ensures that sub-circuit inputs/outputs aren't added or removed, as this would
                 //    invalidate wiring on instances of them.
                 throw new InvalidTransactionException(
                           "Can't remove connectors from sub-circuits".Localize());
             }
         }
     }
 }
Exemplo n.º 5
0
        /// <summary>
        /// Gets all the output pins for this element, including hidden pins (if this is a Group).</summary>
        /// <param name="type">The type</param>
        /// <returns>An enumeration of all the output pins for this type of circuit element</returns>
        public static IEnumerable <ICircuitPin> GetAllOutputPins(this ICircuitElementType type)
        {
            var group = type as Group;

            if (group == null)
            {
                return(type.Outputs);
            }
            return(group.AllOutputPins);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Gets the output pin, taking into account whether 'type' is a Group or not.</summary>
        /// <param name="type">The type</param>
        /// <param name="index">The zero-based index</param>
        /// <returns>The output pin whose zero-based index is 'index'.</returns>
        public static ICircuitPin GetOutputPin(this ICircuitElementType type, NameString pinName)
        {
            var group = type as Group;

            if (group == null)
            {
                return(type.Outputs.GetPinByName(pinName));
            }
            return(group.OutputPin(pinName));
        }
Exemplo n.º 7
0
        /// <summary>
        /// Gets the output pin, taking into account whether 'type' is a Group or not.</summary>
        /// <param name="type">The type</param>
        /// <param name="index">The zero-based index</param>
        /// <returns>The output pin whose zero-based index is 'index'.</returns>
        public static ICircuitPin GetOutputPin(this ICircuitElementType type, int index)
        {
            var group = type as Group;

            if (group == null)
            {
                return(type.Outputs[index]);
            }
            return(group.OutputPin(index));
        }
Exemplo n.º 8
0
        /// <summary>
        /// Gets the input pin index by pin name
        /// </summary>
        /// <param name="type">The type</param>
        /// <param name="pinName">Pin Name</param>
        /// <returns>The input pin indexwhose zero-based index is 'index'.</returns>
        public static int GetInputPinIndex(this ICircuitElementType type, NameString pinName)
        {
            var group = type as Group;

            if (group == null)
            {
                return(type.Inputs.IndexOf(pinName));
            }
            return(group.Inputs.IndexOf(pinName));
        }
        /// <summary>
        /// Gets the input pin, taking into account whether 'type' is a Group or not.</summary>
        /// <param name="type">The type</param>
        /// <param name="index">The zero-based index</param>
        /// <returns>The input pin whose zero-based index is 'index'.</returns>
        public static ICircuitPin GetInputPin(this ICircuitElementType type, int index)
        {
            var group = type as Group;

            if (group == null)
            {
                return(type.Inputs.FirstOrDefault(p => p.Index == index));
            }
            return(group.InputPin(index));
        }
Exemplo n.º 10
0
        private void BuildGraphics(ICircuitElementType elementType, ElementTypeInfo info, Graphics g)
        {
            int width  = info.Size.Width;
            int height = info.Size.Height;

            // create rounded corner rect
            GraphicsPath gp = new GraphicsPath();
            const float  r  = 6;
            const float  d  = 2 * r;

            gp.AddLine(r, 0, width - d, 0);
            gp.AddArc(width - d, 0, d, d, 270, 90);
            gp.AddLine(width, r, width, height - d);
            gp.AddArc(width - d, height - d, d, d, 0, 90);
            gp.AddLine(width - d, height, r, height);
            gp.AddArc(0, height - d, d, d, 90, 90);
            gp.AddLine(0, height - d, 0, r);
            gp.AddArc(0, 0, d, d, 180, 90);

            info.Path = gp;
        }
Exemplo n.º 11
0
        private void DrawOutline(TElement element, Pen pen, Graphics g)
        {
            ElementTypeInfo info = GetElementTypeInfo(element, g);

            if (info.Path == null)
            {
                ICircuitElementType type = element.Type;
                BuildGraphics(type, info, g);
            }

            Point p = element.Bounds.Location;

            s_pathTransform.Translate(p.X, p.Y);
            info.Path.Transform(s_pathTransform);

            g.DrawPath(pen, info.Path);

            s_pathTransform.Translate(2 * -p.X, 2 * -p.Y);
            info.Path.Transform(s_pathTransform);
            s_pathTransform.Reset();
        }
Exemplo n.º 12
0
        private ElementTypeInfo GetElementTypeInfo(TElement element, Graphics g)
        {
            // look it up in the cache
            ICircuitElementType type = element.Type;
            ElementTypeInfo     cachedInfo;

            if (m_elementTypeCache.TryGetValue(type, out cachedInfo))
            {
                return(cachedInfo);
            }

            // not in cache, recompute
            ElementSizeInfo sizeInfo = GetElementSizeInfo(type, g);
            ElementTypeInfo info     = new ElementTypeInfo
            {
                Size        = sizeInfo.Size,
                Interior    = sizeInfo.Interior,
                OutputLeftX = sizeInfo.OutputLeftX.ToArray()
            };

            m_elementTypeCache.Add(type, info);

            return(info);
        }
Exemplo n.º 13
0
 /// <summary>
 /// Invalidates cached info for element type name</summary>
 /// <param name="elementType">Element type to invalidate</param>
 public void Invalidate(ICircuitElementType elementType)
 {
     m_elementTypeCache.Remove(elementType);
     OnRedraw();
 }
Exemplo n.º 14
0
        /// <summary>
        /// Computes interior and exterior size as well as the X positions of output pins</summary>
        /// <param name="type">Circuit element type</param>
        /// <param name="g">Graphics that can be used for measuring strings</param>
        /// <returns>Element size info, must not be null</returns>
        /// <remarks>Clients using customized rendering should override this method
        /// to adjust sizes accordingly. These sizes will be used by drag-fram picking.</remarks>
        protected virtual ElementSizeInfo GetElementSizeInfo(ICircuitElementType type, Graphics g)
        {
            SizeF typeNameSize = g.MeasureString(type.Name, m_theme.Font);
            int   width        = (int)typeNameSize.Width + 2 * PinMargin;

            IList <ICircuitPin> inputPins  = type.Inputs;
            IList <ICircuitPin> outputPins = type.Outputs;
            int inputCount  = inputPins.Count;
            int outputCount = outputPins.Count;
            int minRows     = Math.Min(inputCount, outputCount);
            int maxRows     = Math.Max(inputCount, outputCount);

            int[] outputLeftX = new int[outputCount];

            int height = m_rowSpacing + 2 * PinMargin;

            height += Math.Max(
                maxRows * m_rowSpacing,
                minRows * m_rowSpacing + type.InteriorSize.Height - PinMargin);

            bool imageRight = true;

            for (int i = 0; i < maxRows; i++)
            {
                double rowWidth = 2 * PinMargin;
                if (inputCount > i)
                {
                    SizeF labelSize = g.MeasureString(inputPins[i].Name, m_theme.Font);
                    rowWidth += labelSize.Width + m_pinSize + PinMargin;
                }
                else
                {
                    rowWidth  += type.InteriorSize.Width;
                    imageRight = false;
                }
                if (outputCount > i)
                {
                    SizeF labelSize = g.MeasureString(outputPins[i].Name, m_theme.Font);
                    outputLeftX[i] = (int)labelSize.Width;
                    rowWidth      += labelSize.Width + m_pinSize + PinMargin;
                }
                else
                {
                    rowWidth += type.InteriorSize.Width;
                }
                width = Math.Max(width, (int)rowWidth);
            }

            if (inputCount == outputCount)
            {
                width = Math.Max(width, type.InteriorSize.Width + 2);
            }

            width  = Math.Max(width, MinElementWidth);
            height = Math.Max(height, MinElementHeight);

            Size      size     = new Size(width, height);
            Rectangle interior = new Rectangle(
                imageRight ? width - type.InteriorSize.Width : 1,
                height - type.InteriorSize.Height,
                type.InteriorSize.Width,
                type.InteriorSize.Height);

            for (int i = 0; i < outputLeftX.Length; i++)
            {
                outputLeftX[i] = width - PinMargin - m_pinSize - outputLeftX[i];
            }

            return(new ElementSizeInfo(size, interior, outputLeftX));
        }
Exemplo n.º 15
0
        private void Draw(TElement element, Graphics g)
        {
            ElementTypeInfo info   = GetElementTypeInfo(element, g);
            Point           p      = element.Bounds.Location;
            Rectangle       bounds = new Rectangle(p, info.Size);

            // clip to window
            if (g.ClipBounds.IntersectsWith(bounds))
            {
                ICircuitElementType type = element.Type;

                if (info.Path == null)
                {
                    BuildGraphics(type, info, g);
                }

                s_pathTransform.Translate(p.X, p.Y);
                info.Path.Transform(s_pathTransform);

                // try to use custom brush if registered
                Brush fillBrush = m_theme.GetCustomBrush(type.Name);
                if (fillBrush != null)
                {
                    g.FillPath(fillBrush, info.Path);
                }
                else
                {
                    // use a default brush
                    using (LinearGradientBrush lgb = new LinearGradientBrush(
                               bounds,
                               Color.White,
                               Color.LightSteelBlue,
                               LinearGradientMode.Vertical))
                    {
                        g.FillPath(lgb, info.Path);
                    }
                }
                g.DrawPath(m_theme.OutlinePen, info.Path);

                int titleHeight = m_rowSpacing + PinMargin;
                g.DrawLine(m_theme.OutlinePen, p.X, p.Y + titleHeight, p.X + info.Size.Width, p.Y + titleHeight);
                g.DrawString(type.Name, m_theme.Font, m_theme.TextBrush, p.X + PinMargin + 1, p.Y + PinMargin + 1);

                int pinY = p.Y + titleHeight + PinMargin;
                foreach (TPin inputPin in type.Inputs)
                {
                    Pen pen = GetPen(inputPin);
                    if (pen != null)
                    {
                        g.DrawRectangle(pen, p.X + 1, pinY + m_pinOffset, m_pinSize, m_pinSize);
                    }
                    g.DrawString(inputPin.Name, m_theme.Font, m_theme.TextBrush, p.X + m_pinSize + PinMargin, pinY);
                    pinY += m_rowSpacing;
                }

                pinY = p.Y + titleHeight + PinMargin;
                int i = 0;
                foreach (TPin outputPin in type.Outputs)
                {
                    Pen pen = GetPen(outputPin);
                    if (pen != null)
                    {
                        g.DrawRectangle(pen, p.X + info.Size.Width - m_pinSize, pinY + m_pinOffset, m_pinSize, m_pinSize);
                    }
                    g.DrawString(outputPin.Name, m_theme.Font, m_theme.TextBrush, p.X + info.OutputLeftX[i], pinY);
                    pinY += m_rowSpacing;
                    i++;
                }

                Image image = type.Image;
                if (image != null)
                {
                    g.DrawImage(image, p.X + info.Interior.X, p.Y + info.Interior.Y, info.Interior.Width, info.Interior.Height);
                }

                s_pathTransform.Translate(-2 * p.X, -2 * p.Y);
                info.Path.Transform(s_pathTransform);
                s_pathTransform.Reset();

                string name = element.Name;
                if (!string.IsNullOrEmpty(name))
                {
                    RectangleF alignRect = new RectangleF(
                        bounds.Left - MaxNameOverhang, bounds.Bottom + PinMargin, bounds.Width + 2 * MaxNameOverhang, m_rowSpacing);
                    g.DrawString(name, m_theme.Font, m_theme.TextBrush, alignRect, m_theme.CenterStringFormat);
                }
            }
        }