Aaron Foster - 2011-03-09

I recently took the time to track down that annoying little problem of edges remaining in a visualization after removing them from the data.  You might not notice this if you pass a Transitioner as an argument to the update(), but the following shows the problem perfectly:

package
{
    import flare.vis.Visualization;
    import flare.vis.data.Data;
    import flare.vis.data.NodeSprite;
    import flare.vis.operator.layout.NodeLinkTreeLayout;

    import flash.display.Sprite;
    import flash.events.MouseEvent;

    public class RemoveEdgeEx extends Sprite
    {
        private var v:Visualization;
        public function RemoveEdgeEx()
        {
            var d:Data = new Data(true);
            for (var i:int = 0; i < 16; i++) d.addNode();           
            d.root = d.nodes[0];
            d.addEdgeFor(d.nodes[0], d.nodes[1]);
            d.addEdgeFor(d.nodes[0], d.nodes[2]);
            d.addEdgeFor(d.nodes[1], d.nodes[3]);
            d.addEdgeFor(d.nodes[1], d.nodes[4]);
            d.addEdgeFor(d.nodes[2], d.nodes[5]);
            d.addEdgeFor(d.nodes[2], d.nodes[6]);
            d.addEdgeFor(d.nodes[2], d.nodes[7]);
            d.addEdgeFor(d.nodes[4], d.nodes[8]);
            d.addEdgeFor(d.nodes[4], d.nodes[9]);
            d.addEdgeFor(d.nodes[4], d.nodes[10]);
            d.addEdgeFor(d.nodes[4], d.nodes[11]);
            d.addEdgeFor(d.nodes[5], d.nodes[12]);
            d.addEdgeFor(d.nodes[5], d.nodes[13]);
            d.addEdgeFor(d.nodes[5], d.nodes[14]);
            d.addEdgeFor(d.nodes[5], d.nodes[15]);
            d.visit(
                function(n:NodeSprite):void
                {
                    n.addEventListener(MouseEvent.CLICK, nodeClickHandler);
                }, Data.NODES);

            v = new Visualization(d);
            v.operators.add(new NodeLinkTreeLayout("topToBottom"));
            v.update();
            addChild(v);
        }

        private function nodeClickHandler(e:MouseEvent):void
        {
            var n:NodeSprite = NodeSprite(e.target);
            v.data.removeEdgeFor(n.parentNode, n);
            v.update();
        }
    }
}

The problem lies in the Visualization class, specifically at lines 435 and 474.  At line 474, the edge is pushed into the

_dataItemsRemoved

array, but that edge is never removed from the display list on line 435 with the call to

_marks.removeChild(d);

.  This is because the

update()

function does not dispatch a

TransitionEvent.END

event.

A simple way to get around this problem (bug?) is to pass a Transitioner as an argument to the

update()

function like so:

               

private function nodeClickHandler(e:MouseEvent):void
        {
            var n:NodeSprite = NodeSprite(e.target);
            v.data.removeEdgeFor(n.parentNode, n);
            v.update(0).play();
        }

Presto!  Your edge has disappeared, almost like magic!