private void updateModels()
        {
            var i = 20;

            foreach (var node in nodes)
            {
                SignalNodeViewModel model;
                if (!models.TryGetValue(node, out model))
                {
                    model = new SignalNodeViewModel
                    {
                        Node = node,
                        //TODO find sensible place to dump nodes on canvas
                        //TODO generation of models should be delegated to another class
                        X     = i,
                        Y     = 20,
                        Sinks = node.Sinks.Select(s => new SignalSinkViewModel {
                            Sink = s
                        }).ToList(),
                        Sources = node.Sources.Select(s => new SignalSourceViewModel {
                            Source = s
                        }).ToList(),
                    };
                    models[node] = model;
                }
                i += 400;
            }
        }
        private void renderModel(SignalNodeViewModel model)
        {
            var modelTransform = Matrix3x2.Translation(model.X, model.Y);

            applyTransform(modelTransform);

            const int portSize = 32;
            const int margin   = 20;

            var nodeTitle = new TextLayout(context.FontFactory, model.Node.Name, nodeFont, 10000f, 0f);

            var nodeTitleWidth  = (int)nodeTitle.Metrics.Width + margin;
            var nodeTitleHeight = (int)nodeTitle.Metrics.Height + margin * 2;

            var portCount        = Math.Max(model.Node.Sources.Count(), model.Node.Sinks.Count());
            var portColumnWidth  = portSize + margin;
            var portColumnHeight = portSize + margin;

            var boxWidth  = Math.Max(portColumnWidth * 2, nodeTitleWidth);
            var boxHeight = nodeTitleHeight + portColumnHeight * portCount;

            model.Width  = boxWidth;
            model.Height = boxHeight;

            context.RenderTarget.DrawRectangle(
                new RectangleF
            {
                Left   = 0,
                Top    = 0,
                Height = boxHeight,
                Width  = boxWidth
            }, boxBrush, 1f / zoom);

            var fontX = (boxWidth - (int)nodeTitle.Metrics.Width) / 2;
            var fontY = (margin >> 1);

            context.RenderTarget.DrawTextLayout(new Vector2(fontX, fontY), nodeTitle, boxBrush);

            renderPorts(
                model.Sinks,
                modelTransform,
                margin,
                nodeTitleHeight,
                portSize,
                portColumnHeight);

            renderPorts(
                model.Sources,
                modelTransform,
                boxWidth - portSize - margin,
                nodeTitleHeight,
                portSize,
                portColumnHeight);
        }
 private void updateModels()
 {
     var i = 20;
     foreach (var node in nodes)
     {
         SignalNodeViewModel model;
         if (!models.TryGetValue(node, out model))
         {
             model = new SignalNodeViewModel
             {
                 Node = node,
                 //TODO find sensible place to dump nodes on canvas
                 //TODO generation of models should be delegated to another class
                 X = i,
                 Y = 20,
                 Sinks = node.Sinks.Select(s => new SignalSinkViewModel { Sink = s }).ToList(),
                 Sources = node.Sources.Select(s => new SignalSourceViewModel { Source = s }).ToList(),
             };
             models[node] = model;
         }
         i += 400;
     }
 }
        private void renderModel(SignalNodeViewModel model)
        {
            var modelTransform = Matrix3x2.Translation(model.X, model.Y);
            applyTransform(modelTransform);

            const int portSize = 32;
            const int margin = 20;

            var nodeTitle = new TextLayout(context.FontFactory, model.Node.Name, nodeFont, 10000f, 0f);

            var nodeTitleWidth = (int)nodeTitle.Metrics.Width + margin;
            var nodeTitleHeight = (int)nodeTitle.Metrics.Height + margin * 2;

            var portCount = Math.Max(model.Node.Sources.Count(), model.Node.Sinks.Count());
            var portColumnWidth = portSize + margin;
            var portColumnHeight = portSize + margin;

            var boxWidth = Math.Max(portColumnWidth * 2, nodeTitleWidth);
            var boxHeight = nodeTitleHeight + portColumnHeight * portCount;

            model.Width = boxWidth;
            model.Height = boxHeight;

            context.RenderTarget.DrawRectangle(
                new RectangleF
                {
                    Left = 0,
                    Top = 0,
                    Height = boxHeight,
                    Width = boxWidth
                }, boxBrush, 1f/zoom);

            var fontX = (boxWidth - (int)nodeTitle.Metrics.Width) / 2;
            var fontY = (margin >> 1);
            context.RenderTarget.DrawTextLayout(new Vector2(fontX, fontY), nodeTitle, boxBrush);

            renderPorts(
                model.Sinks,
                modelTransform,
                margin,
                nodeTitleHeight,
                portSize,
                portColumnHeight);

            renderPorts(
                model.Sources,
                modelTransform,
                boxWidth - portSize - margin,
                nodeTitleHeight,
                portSize,
                portColumnHeight);
        }