hackedteam/rcs-console

View on GitHub
src/it/ht/rcs/console/system/view/frontend/graph/FrontendGraph.as

Summary

Maintainability
Test Coverage
package it.ht.rcs.console.system.view.frontend.graph
{
    import flash.geom.Point;
    import flash.utils.Dictionary;
    
    import it.ht.rcs.console.system.view.frontend.graph.renderers.CollectorRenderer;
    import it.ht.rcs.console.system.view.frontend.graph.renderers.DBRenderer;
    import it.ht.rcs.console.system.view.frontend.graph.renderers.IPRenderer;
    import it.ht.rcs.console.utils.ScrollableGraph;
    
    import spark.primitives.Rect;

    [Event(name="nodeSelected", type="it.ht.rcs.console.system.view.frontend.graph.NodeEvent")]
    public class FrontendGraph extends ScrollableGraph
    {

        public var db:DBRenderer;

        public function FrontendGraph()
        {
            super();

      addEventListener(NodeEvent.SELECTED, onNodeEvent);
        }
    
    override protected function onSimulatedClick():void { removeSelection(); }
    
    public var selectedElement:CollectorRenderer;
    public function removeSelection():void
    {
      if (selectedElement != null) {
        selectedElement.selected = false;
        selectedElement = null;
        dispatchEvent(new NodeEvent(NodeEvent.SELECTED, null));
      }
    }
    
        private function onNodeEvent(e:NodeEvent):void
        {
            trace('NetworkGraph: NodeEvent');
      //dispatchEvent(e.clone());
        }

    
    // ----- RENDERING -----
    
    private var bg:Rect;
    private var ips:Vector.<IPRenderer>;
    private var map:Dictionary;
    
    [Bindable]
    public var dirty:Boolean=false;
    
        public function rebuildGraph():void
        {
            removeAllElements();
      
            ips = new Vector.<IPRenderer>();
      map = new Dictionary();

            if (db == null) return;

            addElement(db);
            for each (var cr:CollectorRenderer in db.collectors)
            {
                addElement(cr);
        map[cr.collector] = cr;
        
                var lastNode:CollectorRenderer = cr;
                while (lastNode.nextHop != null)
                {
          lastNode = lastNode.nextHop;
                    addElement(lastNode);
          map[lastNode.collector] = lastNode;
                }
        
                var ip:IPRenderer = new IPRenderer(lastNode.collector);
                ips.push(ip);
                addElement(ip);
            }
      
      // The background. We need a dummy component as background for two reasons:
      // 1) it defines maximum sizes
      // 2) will react to mouse events when the user clicks "nowhere" (eg, dragging)
      var p:Point = computeSize();
      bg = new Rect();
      bg.visible = false; // No need to see it, save rendering time...
      bg.width = p.x;
      bg.height = p.y;
      bg.depth = -1000; // Very bottom layer
      addElement(bg);

            invalidateSize();
            invalidateDisplayList();
        }
    
    private static const HORIZONTAL_DISTANCE:int = 60;
    private static const VERTICAL_DISTANCE:int   = 15;
    private static const HORIZONTAL_PAD:int      = 40;
    private static const VERTICAL_PAD:int        = 8;
    
    private function computeSize():Point
        {
            var _width:Number = 0, _height:Number = 0;
      
      if (db != null) {
      
        _width = db.collectors.length > 0 ?
          (db.collectors[0].width * db.collectors.length) + (HORIZONTAL_DISTANCE * (db.collectors.length - 1)) + HORIZONTAL_PAD * 2 :
          db.width + HORIZONTAL_PAD * 2;
  
        _height = VERTICAL_PAD * 2 + db.height;
        
              var branch:Number = 0;
              for each (var collector:CollectorRenderer in db.collectors)
              {
                  branch = VERTICAL_PAD * 2 + db.height + VERTICAL_DISTANCE + collector.height;
                  collector = collector.nextHop;
                  while (collector != null)
                  {
                      branch += VERTICAL_DISTANCE + collector.height;
            collector = collector.nextHop;
                  }
                  branch += VERTICAL_DISTANCE + ips[0].height;
          _height = Math.max(branch, _height);
              }
      
      }

      return new Point(_width, _height);
        }
    
    override protected function measure():void
    {
      super.measure();
      var p:Point = computeSize();
      measuredWidth = measuredMinWidth = p.x;
      measuredHeight = measuredMinHeight = p.y;
    }

        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            super.updateDisplayList(unscaledWidth, unscaledHeight);

            var _width:Number = Math.max(unscaledWidth, measuredWidth);
            var _height:Number = Math.max(unscaledHeight, measuredHeight);

      var i:int = 0; // Generic loop index
      var cX:int = 0, cY:int = 0; // Generic currentX, currentY
      var offsetFromCenter:int = 0; // Generic offset
      
            graphics.lineStyle(1, 0x999999, 1, true);


      if (db != null) {

                db.move(_width / 2 - db.width / 2, _height - VERTICAL_PAD - db.height);
        
        // Draw collectors
                if (db.collectors != null && db.collectors.length > 0) {
          
          // Where to draw the first collector?
                    var renderer:CollectorRenderer = db.collectors[0];
                  offsetFromCenter = db.collectors.length % 2 == 0 ?
            _width / 2 - (db.collectors.length / 2 * (HORIZONTAL_DISTANCE + renderer.width)) + HORIZONTAL_DISTANCE / 2 : // Even
                _width / 2 - (Math.floor(db.collectors.length / 2) * (HORIZONTAL_DISTANCE + renderer.width)) - renderer.width / 2; // Odd
                
                  for (i = 0; i < db.collectors.length; i++) {
  
                      renderer = db.collectors[i];
  
                      cX = offsetFromCenter + i * (HORIZONTAL_DISTANCE + renderer.width);
                      cY = _height - VERTICAL_PAD - db.height - VERTICAL_DISTANCE - renderer.height;
            renderer.move(cX, cY);

                      graphics.moveTo(_width / 2,              cY + renderer.height + VERTICAL_DISTANCE);
            graphics.lineTo(_width / 2,              cY + renderer.height + VERTICAL_DISTANCE / 2);
            graphics.lineTo(cX + renderer.width / 2, cY + renderer.height + VERTICAL_DISTANCE / 2);
            graphics.lineTo(cX + renderer.width / 2, cY + renderer.height);

            // Draw anonymizers
                      var lastNode:CollectorRenderer = renderer;
                      while (lastNode.nextHop != null) {

              lastNode = lastNode.nextHop;
              
                          cY = cY - VERTICAL_DISTANCE - lastNode.height;
              lastNode.move(cX, cY);
              
                          graphics.moveTo(cX + lastNode.width / 2, cY + lastNode.height + VERTICAL_DISTANCE);
                          graphics.lineTo(cX + lastNode.width / 2, cY + lastNode.height);

                      } // End anonymizers

                        var ip:IPRenderer = ips[i];
            
            cX = cX + lastNode.width / 2 - ip.width / 2;
            cY = cY - VERTICAL_DISTANCE - ip.height
                        ip.move(cX, cY);
      
                        graphics.moveTo(cX + ip.width / 2, cY + ip.height + VERTICAL_DISTANCE);
                        graphics.lineTo(cX + ip.width / 2, cY + ip.height);
  
                  }
          
        } // End collectors
        
            }

        }

    }

}