/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.java.graph;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.EditProvider;
import org.netbeans.api.visual.action.MoveProvider;
import org.netbeans.api.visual.action.PopupMenuProvider;
import org.netbeans.api.visual.action.SelectProvider;
import org.netbeans.api.visual.action.TwoStateHoverProvider;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.anchor.AnchorFactory;
import org.netbeans.api.visual.animator.AnimatorEvent;
import org.netbeans.api.visual.animator.AnimatorListener;
import org.netbeans.api.visual.export.SceneExporter;
import org.netbeans.api.visual.graph.GraphScene;
import org.netbeans.api.visual.graph.layout.GraphLayout;
import org.netbeans.api.visual.graph.layout.GraphLayoutFactory;
import org.netbeans.api.visual.graph.layout.GraphLayoutSupport;
import org.netbeans.api.visual.layout.SceneLayout;
import org.netbeans.api.visual.model.ObjectState;
import org.netbeans.api.visual.widget.ConnectionWidget;
import org.netbeans.api.visual.widget.LayerWidget;
import org.netbeans.api.visual.widget.Widget;
import org.openide.filesystems.FileChooserBuilder;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;

/**
 *
 * @author Milos Kleint 
 * @param <I> 
 */
public class DependencyGraphScene<I extends GraphNodeImplementation> extends GraphScene<GraphNode<I>, GraphEdge<I>> {
    
    
    public interface PaintingProvider<I extends GraphNodeImplementation> {        
        /**
         * Determines an icon for the given node.
         * 
         * @param node
         * @return the icon or <code>null</code> if none should be used
         */
        Icon getIcon(I node);
        
        /**
         * Determines if the given node should be visible.
         * 
         * @param node
         * @return <code>true</code> if the node should be visible, otherwise <code>false</code>
         */
        boolean isVisible(I node);
        
        /**
         * Determines if the given edge should be visible.
         * 
         * @param source
         * @param target
         * @return <code>true</code> if the edge should be visible, otherwise <code>false</code>
         */
        boolean isVisible(I source, I target);
        
        /**
         * Determines a color for the given node.
         * 
         * @param node
         * @return the color or <code>null</code> if default should be used
         */
        Color getColor(I node);
        
        /**
         * Determines a stroke for the given edge.
         * 
         * @param source
         * @param target
         * @return the stroke or <code>null</code> if default should be used
         */
        Stroke getStroke(I source, I target);
    }
        
    public interface HighlightDepthProvider {
        int getDepth();
    }
    
    public interface VersionProvider<I extends GraphNodeImplementation> {        
        // conflict type
        public static final int VERSION_NO_CONFLICT = 0;
        public static final int VERSION_POTENTIAL_CONFLICT = 1;
        public static final int VERSION_CONFLICT = 2;
    
        String getVersion(I impl);    
        int compareVersions(I impl1, I impl2);
        boolean isIncluded(I impl);
        boolean isOmmitedForConflict(I impl);
    }
    
    public interface ActionsProvider<I extends GraphNodeImplementation> {
        Action createFixVersionConflictAction(DependencyGraphScene scene, GraphNode<I> rootNode, GraphNode<I> node);
        Action createExcludeDepAction(DependencyGraphScene scene, GraphNode<I> rootNode, GraphNode<I> node);
        Action createShowGraphAction(GraphNode<I> node);
    }
    
    private final VersionProvider versionProvider;
    private final ActionsProvider nodeActionProvider;
    private final HighlightDepthProvider highlightProvider;
    private final PaintingProvider<I> paintingProvider;
    
    private LayerWidget mainLayer;
    private final LayerWidget connectionLayer;
    private GraphNode rootNode;
    private final AllActionsProvider allActionsP = new AllActionsProvider();
    
//    private GraphLayout layout;
    private final WidgetAction moveAction = ActionFactory.createMoveAction(null, allActionsP);
    private final WidgetAction popupMenuAction = ActionFactory.createPopupMenuAction(allActionsP);
    private final WidgetAction zoomAction = ActionFactory.createMouseCenteredZoomAction(1.1);
    private final WidgetAction panAction = ActionFactory.createPanAction();
    private final WidgetAction editAction = ActionFactory.createEditAction(allActionsP);
    private final WidgetAction hoverAction = ActionFactory.createHoverAction(new HoverController());

    private final Action sceneZoomToFitAction = new SceneZoomToFitAction();
    private final Action highlitedZoomToFitAction = new HighlightedZoomToFitAction();

    private FruchtermanReingoldLayout layout;
    private int maxDepth = 0;
    private FitToViewLayout fitViewL;

    private static final Set<GraphNode> EMPTY_SELECTION = new HashSet<>();
    private JScrollPane pane;
    private final AtomicBoolean animated = new AtomicBoolean(false);
    
    private HighlightVisitor highlightV;
    
    public DependencyGraphScene(JScrollPane pane) {
        this(null, null, null, null);
    }
    
    public DependencyGraphScene(ActionsProvider<I> nodeActionProvider, HighlightDepthProvider highlightProvider, VersionProvider<I> versionProvider, PaintingProvider<I> paintingProvider) {                
        this.nodeActionProvider = nodeActionProvider;
        this.highlightProvider = highlightProvider;
        this.versionProvider = versionProvider;
        this.paintingProvider = paintingProvider;
        
        mainLayer = new LayerWidget(this);
        addChild(mainLayer);
        connectionLayer = new LayerWidget(this);
        addChild(connectionLayer);
        
        //this glasspane thing is only here to get rid of connection lines across widgets
        Widget glasspane = new LayerWidget(this) {

            @Override
            protected void paintChildren() {
                if (isCheckClipping()) {
                    Rectangle clipBounds = DependencyGraphScene.this.getGraphics().getClipBounds();
                    for (Widget child : mainLayer.getChildren()) {
                        Point location = child.getLocation();
                        Rectangle bounds = child.getBounds();
                        bounds.translate(location.x, location.y);
                        if (clipBounds == null || bounds.intersects(clipBounds)) {
                            child.paint();
                        }
                    }
                } else {
                    for (Widget child : mainLayer.getChildren()) {
                        child.paint();
                    }
                }
            }

        };
        addChild(glasspane);
        //getActions().addAction(this.createObjectHoverAction());
        getActions().addAction(hoverAction);
        getActions().addAction(ActionFactory.createSelectAction(allActionsP));
        getActions().addAction(zoomAction);
        getActions().addAction(panAction);
        getActions().addAction(editAction);
        getActions().addAction(popupMenuAction);
    }

    boolean isVisible(GraphEdge<I> e) {
        return paintingProvider == null || paintingProvider.isVisible(e.getSource(), e.getTarget());
    }   
    
    boolean isVisible(GraphNode<I> n) {
        return paintingProvider == null || paintingProvider.isVisible(n.getImpl());
    }
    
    Stroke getStroke(GraphEdge<I> e) {
        return paintingProvider != null ? paintingProvider.getStroke(e.getSource(), e.getTarget()) : null;
    }
    
    Color getColor(GraphNode<I> n) {
        return paintingProvider != null ? paintingProvider.getColor(n.getImpl()) : null;
    }
    
    Icon getIcon(GraphNode<I> n) {
        return paintingProvider != null ? paintingProvider.getIcon(n.getImpl()) : null;
    }
    
    public void addGraphNodeImpl(I d) {
        super.addNode(new GraphNode<>(d));
    }
    
    public GraphEdge addEdge(I source, I target) {
        Collection<GraphNode<I>> nodes = getNodes();
        GraphNode<I> s = getGraphNode(nodes, source);
        assert s != null;
        GraphNode<I> t = getGraphNode(nodes, target);
        assert t != null;
        GraphEdge<I> edge = new GraphEdge<>(source, target);
        addEdge(edge);
        setEdgeSource(edge, s);
        setEdgeTarget(edge, t);
        return edge;
    }
    
    private GraphNode<I> getGraphNode(Collection<GraphNode<I>> nodes, I i) {
        for(GraphNode<I> n : nodes) {
            if(n.getImpl().equals(i)) {
                return n;
            }
        }
        assert false : "no node found for " + i.getName();
        return null;
    }

    public void setSearchString(String val) {
        SearchVisitor visitor = new SearchVisitor(this);
        visitor.setSearchString(val);
        visitor.accept(getRootGraphNode().getImpl());
        validate();
        repaint();
        revalidate();
        repaint();
    }
    
    public void notifyModelChanged(GraphNode<I> graphNode) {
        NodeWidget nodeWidget = (NodeWidget) findWidget(graphNode);
        if (nodeWidget != null) {
            nodeWidget.modelChanged();
        }
    }
    
    public void notifyModelChanged(GraphEdge<I> graphEdge) {
        EdgeWidget edgeWidget = (EdgeWidget) findWidget(graphEdge);
        if (edgeWidget != null) {
            edgeWidget.modelChanged();
        }
    }
    
    boolean supportsVersions () {
        return versionProvider != null;
    }    
    
    public boolean isIncluded(I node) {
        if(!supportsVersions()) {
            return true;
        }
        assert versionProvider != null;
        return versionProvider.isIncluded(node);
    }
    
    boolean isConflict(I node) {
        if(!supportsVersions()) {
            return false;
        }
        assert versionProvider != null;
        return versionProvider.isOmmitedForConflict(node);        
    }
            
    String getVersion(I impl) {
        assert versionProvider != null;
        return versionProvider.getVersion(impl);
    } 

    int compareVersions(I n1, I n2) {
        assert versionProvider != null;
        return versionProvider.compareVersions(n1, n2);        
    }
    
    public void setMyZoomFactor(double zoom) {
        setZoomFactor(zoom);
        ArrayList<Widget> arr = new ArrayList<Widget>();
        arr.addAll(mainLayer.getChildren());
        arr.addAll(connectionLayer.getChildren());
        for (Widget wid : arr) {
            if (wid instanceof NodeWidget) {
                ((NodeWidget)wid).updateReadableZoom();
            }
            if (wid instanceof EdgeWidget) {
                ((EdgeWidget)wid).updateReadableZoom();
            }
        }
    }

    public void initialLayout() {
        //start using default layout
        layout =  new FruchtermanReingoldLayout(this, pane);
        layout.invokeLayout();
        addSceneListener(new SceneListener() {

            @Override
            public void sceneRepaint() {
               
            }

            @Override
            public void sceneValidating() {
                
            }

            @Override
            public void sceneValidated() {
                //the first layout has not be non animated, then we can fit to zoom easily
                if (animated.compareAndSet(false, true)) {
                    new SceneZoomToFitAction().actionPerformed(null);
                }
                    
            }
        });
    }
    
    public void setSurroundingScrollPane(JScrollPane pane) {
        this.pane = pane; 
    }
    
    public GraphNode<I> getRootGraphNode() {
        return rootNode;
    }

    public int getMaxNodeDepth() {
        return maxDepth;
    }

    boolean isAnimated () {
        return animated.get();
    }

    @CheckForNull public GraphNode getGraphNodeRepresentant(GraphNodeImplementation impl) {
        for (GraphNode grnode : getNodes()) {
            if (grnode.getImpl().equals(impl)) {
                return grnode;                
            }
            if(supportsVersions() && (grnode.represents(impl))) { 
                return grnode;            
            }
        }
        return null;
    }
    
    @Override protected Widget attachNodeWidget(GraphNode node) {
        if (rootNode == null) {
            rootNode = node;
        }
        if (node.getPrimaryLevel() > maxDepth) {
            maxDepth = node.getPrimaryLevel();
        }
        
        Action fixAction = nodeActionProvider != null ? nodeActionProvider.createFixVersionConflictAction(this, rootNode, node) : null;        
        NodeWidget root = new NodeWidget(this, node, fixAction, hoverAction);
        mainLayer.addChild(root);
        root.setOpaque(true);
        
        root.getActions().addAction(this.createObjectHoverAction());
        root.getActions().addAction(this.createSelectAction());
        root.getActions().addAction(moveAction);
        root.getActions().addAction(editAction);
        root.getActions().addAction(popupMenuAction);
                    
        return root;
    }
    
    @Override protected Widget attachEdgeWidget(GraphEdge edge) {
        EdgeWidget connectionWidget = new EdgeWidget(this, edge);
        connectionLayer.addChild(connectionWidget);
        return connectionWidget;
    }
    
    @Override protected void attachEdgeSourceAnchor(GraphEdge edge,
            GraphNode oldsource,
            GraphNode source) {
        ((ConnectionWidget) findWidget(edge)).setSourceAnchor(AnchorFactory.createRectangularAnchor(findWidget(source)));
        
    }
    
    @Override protected void attachEdgeTargetAnchor(GraphEdge edge,
            GraphNode oldtarget,
            GraphNode target) {
        NodeWidget wid = (NodeWidget)findWidget(target);
        ((ConnectionWidget) findWidget(edge)).setTargetAnchor(AnchorFactory.createRectangularAnchor(wid));
    }    
    
    public void updateVisibility() {
        getEdges().stream().forEach(edge -> ((EdgeWidget)findWidget(edge)).updateAppearance(true));
        getNodes().stream().forEach(node -> ((NodeWidget)findWidget(node)).updatePaintContent());
    }
    
    public void calculatePrimaryPathsAndLevels() {
        Collection<GraphNode<I>> ns = getNodes();        
        for (GraphNode<I> n : ns) {
            List<GraphEdge> primaryPathEdges = new ArrayList<>();
            LinkedList<GraphNode> importantNodes = new LinkedList<>(); // XXX node depth?
            addPathToRoot(n, primaryPathEdges, importantNodes);
            for (GraphEdge pe : primaryPathEdges) {
                pe.setPrimaryPath(true);
                }
            int level = primaryPathEdges.size();
            n.setPrimaryLevel(level);
            if (level > maxDepth) {
                maxDepth = level;
            }
        }
    }
    
    void highlightRelated (GraphNode<I> node) {
        List<GraphNode> importantNodes = new ArrayList<GraphNode>();
        List<GraphEdge> otherPathsEdges = new ArrayList<GraphEdge>();
        List<GraphEdge> primaryPathEdges = new ArrayList<GraphEdge>();
        List<GraphNode> childrenNodes = new ArrayList<GraphNode>();
        List<GraphEdge> childrenEdges = new ArrayList<GraphEdge>();

        importantNodes.add(node);

        @SuppressWarnings("unchecked")
        List<I> children = node.getImpl().getChildren();
        if (children != null) {
            for (I n : children) {
                GraphNode child = getGraphNodeRepresentant(n);
                if (child != null) {
                    childrenNodes.add(child);
                }
            }
        }

        childrenEdges.addAll(findNodeEdges(node, true, false));

        // primary path
        addPathToRoot(node, primaryPathEdges, importantNodes);

        if(supportsVersions()) {
            // other important paths
            ArrayList<I> representants = new ArrayList<>(node.getDuplicatesOrConflicts());
            for (GraphNodeImplementation curRep : representants) {
                addPathToRoot(curRep, curRep.getParent(), otherPathsEdges, importantNodes);
            }
        }
        EdgeWidget ew;
        for (GraphEdge curE : getEdges()) {
            ew = (EdgeWidget) findWidget(curE);
            if (primaryPathEdges.contains(curE)) {
                ew.setState(EdgeWidget.HIGHLIGHTED_PRIMARY);
            } else if (otherPathsEdges.contains(curE)) {
                ew.setState(EdgeWidget.HIGHLIGHTED);
            } else if (childrenEdges.contains(curE)) {
                ew.setState(EdgeWidget.GRAYED);
            } else {
                ew.setState(EdgeWidget.DISABLED);
            }
        }

        NodeWidget aw;
        for (GraphNode curN : getNodes()) {
            aw = (NodeWidget) findWidget(curN);
            if (importantNodes.contains(curN)) {
                aw.setPaintState(EdgeWidget.REGULAR);
                aw.setReadable(true);
            } else if (childrenNodes.contains(curN)) {
                aw.setPaintState(EdgeWidget.REGULAR);
                aw.setReadable(true);
            } else {
                aw.setPaintState(EdgeWidget.DISABLED);
                aw.setReadable(false);
            }
        }

    }

    private void addPathToRoot(GraphNode node, List<GraphEdge> edges, List<GraphNode> nodes) {
        GraphNodeImplementation parentImpl = node.getParent();
        addPathToRoot(node.getImpl(), parentImpl, edges, nodes);
    }


    private void addPathToRoot(GraphNodeImplementation impl, GraphNodeImplementation parentImpl, List<GraphEdge> edges, List<GraphNode> nodes) {
        final Set<GraphNodeImplementation> seen = new HashSet<>();
        GraphNode grNode;
        while (parentImpl != null) {
            seen.add(parentImpl);
            grNode = getGraphNodeRepresentant(parentImpl);
            if (grNode == null) {
                return;
            }
            GraphNode targetNode = getGraphNodeRepresentant(impl);
            if (targetNode == null) {
                return;
            }
            edges.addAll(findEdgesBetween(grNode, targetNode));
            nodes.add(grNode);
            impl = parentImpl;
            parentImpl = grNode.getParent();
            if (seen.contains(parentImpl)) {
                parentImpl = null;
            }
        }
    }

    private class AllActionsProvider implements PopupMenuProvider, 
            MoveProvider, EditProvider, SelectProvider {

        private Point moveStart;

/*        public void select(Widget wid, Point arg1, boolean arg2) {
            System.out.println("select called...");
            Widget w = wid;
            while (w != null) {
                GraphNode node = (GraphNode)findObject(w);
                if (node != null) {
                    setSelectedObjects(Collections.singleton(node));
                    System.out.println("selected object: " + node.getArtifact().getArtifact().getArtifactId());
                    highlightRelated(node);
                    ((NodeWidget)w).setSelected(true);
                    return;
                }
                w = w.getParentWidget();
            }
        }*/
        
        @Messages({
            "ACT_Export_As_Image=Export As Image",
            "ACT_LayoutSubMenu=Layout",
            "ACT_Export_As_Image_Title=Export Dependency Graph As PNG"
        })
        @Override public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
            JPopupMenu popupMenu = new JPopupMenu();
            if (widget == DependencyGraphScene.this) {
                popupMenu.add(sceneZoomToFitAction);
                final JMenu layoutMenu = new JMenu(Bundle.ACT_LayoutSubMenu());
                popupMenu.add(layoutMenu);
                layoutMenu.add(new FruchtermanReingoldLayoutAction());
                layoutMenu.add(new JSeparator());
                layoutMenu.add(new HierarchicalGraphLayoutAction());
                layoutMenu.add(new TreeGraphLayoutVerticalAction());
                layoutMenu.add(new TreeGraphLayoutHorizontalAction());
                popupMenu.add(new AbstractAction(Bundle.ACT_Export_As_Image()) {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        File file = new FileChooserBuilder("DependencyGraphScene-ExportDir").setTitle(Bundle.ACT_Export_As_Image_Title())
                                .setAcceptAllFileFilterUsed(false).addFileFilter(new FileNameExtensionFilter("PNG file", "png")).showSaveDialog();
                        if (file != null) {
                            try {
                                DependencyGraphScene theScene = DependencyGraphScene.this;
                                SceneExporter.createImage(theScene, file, SceneExporter.ImageType.PNG, SceneExporter.ZoomType.CURRENT_ZOOM_LEVEL, false, false, -1, -1, -1);
                            } catch (IOException ex) {
                                Exceptions.printStackTrace(ex);
                            }
                        }
                    }
                });
            } else {
                if(nodeActionProvider != null) {
                    GraphNode node = (GraphNode)findObject(widget);
                    
                    boolean addSeparator = false;
                    Action a = nodeActionProvider.createFixVersionConflictAction(DependencyGraphScene.this, rootNode, node);
                    if(a != null) {
                        popupMenu.add(a);
                        addSeparator = true;                        
                    }
                    a = nodeActionProvider.createExcludeDepAction(DependencyGraphScene.this, rootNode, node);
                    if(a != null) {
                        popupMenu.add(a);
                        addSeparator = true;                        
                    }                    
                    if (addSeparator) {
                        popupMenu.add(new JSeparator());
                    }
                    popupMenu.add(highlitedZoomToFitAction);
                    if (!node.isRoot()) {
                        a = nodeActionProvider.createShowGraphAction(node);
                        if(a != null) {
                            popupMenu.add(a);
                        }
                    }
                }
            }
            return popupMenu;
        }

        @Override public void movementStarted(Widget widget) {
            widget.bringToFront();
            moveStart = widget.getLocation();
        }
        @Override public void movementFinished(Widget widget) {
            // little hack to call highlightRelated on mouse click while leaving
            // normal move behaviour on real dragging
            Point moveEnd = widget.getLocation();
            if (moveStart.distance(moveEnd) < 5) {
                Object obj = DependencyGraphScene.this.findObject(widget);
                if (obj instanceof GraphNode) {
                    DependencyGraphScene.this.highlightRelated((GraphNode)obj);
                }
            }
        }
        @Override public Point getOriginalLocation(Widget widget) {
            return widget.getPreferredLocation ();
        }
        @Override public void setNewLocation(Widget widget, Point location) {
            widget.setPreferredLocation (location);
        }

        @Override public void edit(Widget widget) {
            if (DependencyGraphScene.this == widget) {
                sceneZoomToFitAction.actionPerformed(null);
            } else {
                highlitedZoomToFitAction.actionPerformed(null);
            }
        }

        @Override public boolean isAimingAllowed(Widget widget, Point localLocation, boolean invertSelection) {
            return false;
        }

        @Override public boolean isSelectionAllowed(Widget widget, Point localLocation, boolean invertSelection) {
            return true;
        }

        @Override public void select(Widget widget, Point localLocation, boolean invertSelection) {
            setSelectedObjects(EMPTY_SELECTION);
            highlightDepthIntern();
        }

    }        

    /** 
     * Highlights/diminishes graph nodes and edges based on path from root depth 
     * based on the in constructor provided HighlightDepthProvider
     */
    public void highlightDepth(int depth) {
        assert depth > -1 || highlightProvider != null : "using depth highlighting without providing HighlightProvider in c'tor no allowed";
        if(depth == -1) {
            depth = 0;
        }
        if (highlightV == null) {
            highlightV = new HighlightVisitor(this);
        }
        highlightV.setMaxDepth(depth);
        highlightV.accept(getRootGraphNode().getImpl());
        validate();
        repaint();
    }
    
    public void resetHighlight() {
        highlightV = null;
    }
    
    private void highlightDepthIntern () {        
        int depth;
        if(highlightProvider == null) {
            depth = -1; // not available
        } else {
            depth = highlightProvider.getDepth();
        }
        highlightDepth(depth);
    }
    
    @Override
    protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
        super.notifyStateChanged(previousState, state);

        if (!previousState.isSelected() && state.isSelected()) {
            highlightDepthIntern();
        }
    }

    private FitToViewLayout getFitToViewLayout () {
        if (fitViewL == null) {
            fitViewL = new FitToViewLayout(this, pane);
        }
        return fitViewL;
    }
        
    private static class FitToViewLayout extends SceneLayout {

        private final DependencyGraphScene depScene;
        private List<? extends Widget> widgets;
        private final JScrollPane parentScrollPane;

        FitToViewLayout(DependencyGraphScene scene, JScrollPane parentScrollPane) {
            super(scene);
            this.depScene = scene;
            this.parentScrollPane = parentScrollPane;
        }

        
        protected void fitToView(@NullAllowed List<? extends Widget> widgets) {
            this.widgets = widgets;
            this.invokeLayout(); 
        }

        @Override
        protected void performLayout() {
            Rectangle rectangle = null;
            List<? extends Widget> toFit = widgets != null ? widgets : depScene.getChildren();
            if (toFit == null) {
                return;
            }

            for (Widget widget : toFit) {
                Rectangle bounds = widget.getBounds();
                if (bounds == null) {
                    continue;
                }
                if (rectangle == null) {
                    rectangle = widget.convertLocalToScene(bounds);
                } else {
                    rectangle = rectangle.union(widget.convertLocalToScene(bounds));
                }
            }
            // margin around
            if (widgets == null) {
                rectangle.grow(5, 5);
            } else {
                rectangle.grow(25, 25);
            }
            Dimension dim = rectangle.getSize();
            Dimension viewDim = parentScrollPane.getViewportBorderBounds().getSize ();
            double zf = Math.min ((double) viewDim.width / dim.width, (double) viewDim.height / dim.height);
            if (depScene.isAnimated()) {
                if (widgets == null) {
                    depScene.getSceneAnimator().animateZoomFactor(zf);
                } else {
                    CenteredZoomAnimator cza = new CenteredZoomAnimator(depScene.getSceneAnimator());
                    cza.setZoomFactor(zf,
                            new Point((int)rectangle.getCenterX(), (int)rectangle.getCenterY()));
                }
            } else {
                depScene.setMyZoomFactor (zf);
            }
        }

    }

    private class SceneZoomToFitAction extends AbstractAction {

        @Messages("ACT_ZoomToFit=Zoom To Fit")
        SceneZoomToFitAction() {
            putValue(NAME, Bundle.ACT_ZoomToFit());
        }

        @Override public void actionPerformed(ActionEvent e) {
            DependencyGraphScene.this.getFitToViewLayout().fitToView(null);
        }
    };

    private class HighlightedZoomToFitAction extends AbstractAction {

        HighlightedZoomToFitAction() {
            putValue(NAME, Bundle.ACT_ZoomToFit());
        }

        @Override public void actionPerformed(ActionEvent e) {
            Collection<GraphNode<I>> grNodes = DependencyGraphScene.this.getNodes();
            List<NodeWidget> aws = new ArrayList<NodeWidget>();
            NodeWidget aw = null;
            int paintState;
            for (GraphNode grNode : grNodes) {
                aw = (NodeWidget) findWidget(grNode);
                paintState = aw.getPaintState();
                if (paintState != EdgeWidget.DISABLED && paintState != EdgeWidget.GRAYED) {
                    aws.add(aw);
                }
            }
            DependencyGraphScene.this.getFitToViewLayout().fitToView(aws);
        }
    };

    private static class HoverController implements TwoStateHoverProvider {

        @Override public void unsetHovering(Widget widget) {
            NodeWidget aw = findArtifactW(widget);
            if (widget != null) {
                aw.bulbUnhovered();
            }
        }

        @Override public void setHovering(Widget widget) {
            NodeWidget aw = findArtifactW(widget);
            if (aw != null) {
                aw.bulbHovered();
            }
        }

        private NodeWidget findArtifactW (Widget w) {
            while (w != null && !(w instanceof NodeWidget)) {
                w = w.getParentWidget();
            }
            return (NodeWidget)w;
        }

    }
    
    private class HierarchicalGraphLayoutAction extends AbstractAction {

       @Messages("ACT_Layout_HierarchicalGraphLayout=Hierarchical")
       HierarchicalGraphLayoutAction() {
           putValue(NAME, Bundle.ACT_Layout_HierarchicalGraphLayout());
       }

       @Override public void actionPerformed(ActionEvent e) {
           final GraphLayout layout = GraphLayoutFactory.createHierarchicalGraphLayout(DependencyGraphScene.this, DependencyGraphScene.this.isAnimated(), false);
           layout.layoutGraph(DependencyGraphScene.this);
            fitToZoomAfterLayout();
        }
   };
   private class TreeGraphLayoutVerticalAction extends AbstractAction {

       @Messages("ACT_Layout_TreeGraphLayoutVertical=Vertical Tree")
       TreeGraphLayoutVerticalAction() {
           putValue(NAME, Bundle.ACT_Layout_TreeGraphLayoutVertical());
       }

       @Override public void actionPerformed(ActionEvent e) {
           final GraphLayout layout = GraphLayoutFactory.createTreeGraphLayout(10, 10, 50, 50, true);
           GraphLayoutSupport.setTreeGraphLayoutRootNode(layout, DependencyGraphScene.this.rootNode);
           
           layout.layoutGraph(DependencyGraphScene.this);
           fitToZoomAfterLayout();
       }
   };

   private class TreeGraphLayoutHorizontalAction extends AbstractAction {

       @Messages("ACT_Layout_TreeGraphLayoutHorizontal=Horizontal Tree")
       TreeGraphLayoutHorizontalAction() {
           putValue(NAME, Bundle.ACT_Layout_TreeGraphLayoutHorizontal());
       }

       @Override public void actionPerformed(ActionEvent e) {
           final GraphLayout layout = GraphLayoutFactory.createTreeGraphLayout(10, 10, 50, 50, false);
           GraphLayoutSupport.setTreeGraphLayoutRootNode(layout, DependencyGraphScene.this.rootNode);
           
           layout.layoutGraph(DependencyGraphScene.this);
           fitToZoomAfterLayout();
           
       }
   };
   private class FruchtermanReingoldLayoutAction extends AbstractAction {

       @Messages("ACT_Layout_FruchtermanReingoldLayout=Default Layout")
       FruchtermanReingoldLayoutAction() {
           putValue(NAME, Bundle.ACT_Layout_FruchtermanReingoldLayout());
       }

       @Override public void actionPerformed(ActionEvent e) {
           //default layout in 7.3 
           layout.invokeLayout();
           fitToZoomAfterLayout();
       }
   };

    void fitToZoomAfterLayout() {
            DependencyGraphScene.this.getSceneAnimator().getPreferredLocationAnimator().addAnimatorListener(new AnimatorListener() {
                
                @Override
                public void animatorStarted(AnimatorEvent event) {
                    
                }
                
                @Override
                public void animatorReset(AnimatorEvent event) {
                    
                }
                
                @Override
                public void animatorFinished(AnimatorEvent event) {
                    DependencyGraphScene.this.getSceneAnimator().getPreferredLocationAnimator().removeAnimatorListener(this);
                    new SceneZoomToFitAction().actionPerformed(null);
                }
                
                @Override
                public void animatorPreTick(AnimatorEvent event) {
                    
                }
                
                @Override
                public void animatorPostTick(AnimatorEvent event) {
                    
                }
            });
    }
}
