package flare.vis.operator.filter { import flare.animate.Transitioner; import flare.vis.data.DataSprite; import flare.vis.data.EdgeSprite; import flare.vis.data.NodeSprite; import flare.vis.operator.Operator; import flash.utils.Dictionary; /** * Filter operator that sets visible all items within a specified graph * distance from a set of focus nodes. */ public class GraphDistanceFilter extends Operator { /** An object vector of focal NodeSprites. */ public var focusNodes:Vector.; /** Graph distance within which which items wll be visible. */ public var distance:int; /** Flag indicating which graph links to traverse. */ public var links:int; /** * Creates a new GraphDistanceFilter. * @param focusNodes an object vector of focal NodeSprites. Graph distance is * measured as the minimum number of edge-hops to one of these nodes. * @param distance graph distance within which items will be visible * @param links flag indicating which graph links to traverse. The * default value is NodeSprite.GRAPH_LINKS. */ public function GraphDistanceFilter(focusNodes:Vector. = null, distance:int=1, links:int=3) { this.focusNodes = focusNodes; this.distance = distance; this.links = links; } /** @inheritDoc */ public override function operate(t:Transitioner=null):void { t = (t==null ? Transitioner.DEFAULT : t); // initialize breadth-first traversal var q:Vector. = new Vector.(); var depths:Dictionary = new Dictionary(); for each (var fn:NodeSprite in focusNodes) { depths[fn] = 0; fn.visitEdges(function(e:EdgeSprite):void { depths[e] = 1; q.push(e); }, links); } // perform breadth-first traversal var xe:EdgeSprite, xn:NodeSprite, d:int; while (q.length > 0) { xe = q.shift(); d = depths[xe]; // -- fix to bug 1924891 by goosebumps4all if (depths[xe.source] == undefined) { xn = xe.source; } else if (depths[xe.target] == undefined) { xn = xe.target; } else { continue; } // -- end fix depths[xn] = d; if (d == distance) { xn.visitEdges(function(e:EdgeSprite):void { if (depths[e.target]==d && depths[e.source]==d) { depths[e] = d+1; } }, links); } else { xn.visitEdges(function(e:EdgeSprite):void { if (depths[e] == undefined) { depths[e] = d+1; q.push(e); } }, links); } } // now set visibility based on traversal results visualization.data.visit(function(ds:DataSprite):void { var visible:Boolean = (depths[ds] != undefined); var alpha:Number = visible ? 1 : 0; var obj:Object = t.$(ds); obj.alpha = alpha; if (ds is NodeSprite) { var ns:NodeSprite = ds as NodeSprite; ns.expanded = (visible && depths[ds] < distance); } if (t.immediate) { ds.visible = visible; } else { obj.visible = visible; } }); } } // end of class GraphDistanceFilter }