Friday, June 8, 2012

How Absurd and Scary (more Java coding).

I wrote a class that scares me. It makes nodes into widgets and calls itself recursively.

import java.awt.Image;
import java.awt.Point;
import java.beans.BeanInfo;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.Action;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.PopupMenuProvider;
import org.netbeans.api.visual.layout.LayoutFactory;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;
import org.netbeans.api.visual.widget.general.IconNodeWidget;
import org.openide.nodes.*;
import org.openide.util.Lookup;
import org.openide.util.lookup.Lookups;

public class NodeWidget extends IconNodeWidget implements PopupMenuProvider, Lookup.Provider, NodeListener {
    Node node;
    boolean vertical;
    public NodeWidget(Scene scene, Node node) {
        this(scene,node,true);
    }
   
    private NodeWidget(Scene scene, Node node, boolean vertical) {
        super(scene);
        this.vertical = vertical;
        this.node = node;
        Image icon = node.getIcon(BeanInfo.ICON_COLOR_32x32);
        if (icon != null) {
            getImageWidget().setImage(icon);  
        }
        getLabelWidget().setLabel(node.getDisplayName());
        if (vertical) {
            this.setLayout(LayoutFactory.createVerticalFlowLayout());
        }
        else {
            this.setLayout(LayoutFactory.createHorizontalFlowLayout());
        }
        if (node.getActions(false) != null) {
            getActions().addAction(ActionFactory.createPopupMenuAction(this));
        }
        refreshChildren();
        node.addNodeListener(this);
    }

    @Override
    public Lookup getLookup() {
        return Lookups.proxy(node);
    }

    @Override
    public JPopupMenu getPopupMenu(Widget widget, Point point) {
        JPopupMenu pop = new JPopupMenu();
        for (Action action : node.getActions(false)) {
            pop.add(action);
        }
        return pop;
    }
   
    private Collection childnodewidgets = new ArrayList<>();
    private void refreshChildren() {
        if (!SwingUtilities.isEventDispatchThread()) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    refreshChildren();
                }
            });
            return;
        }
        for (Widget widget : childnodewidgets) {
            widget.revalidate();
            widget.removeFromParent();
            revalidate();
        }
        childnodewidgets.clear();
        Widget widget;
        if (!node.isLeaf()) {
            Children c = node.getChildren();
            for (Node n : c.getNodes()) {
                widget = new NodeWidget(getScene(), n, !vertical);
                childnodewidgets.add(widget);
                addChild(widget);
                widget.revalidate();
                revalidate();
            }
        }
        getScene().validate();
    }

    @Override
    public void childrenAdded(NodeMemberEvent nme) {
        refreshChildren();
    }

    @Override
    public void childrenRemoved(NodeMemberEvent nme) {
        refreshChildren();
    }

    @Override
    public void childrenReordered(NodeReorderEvent nre) {
        refreshChildren();
    }

    @Override
    public void nodeDestroyed(NodeEvent ne) {
       removeChildren();
       removeFromParent();
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
    }
   
}


 That's spooky. And looks terrible-ish. I'll remove that recursive children part and actually use it. But, it uses Virtual Library and cross connects Netbeans display Nodes. I dragged a directory out of favorites (and had an AcceptAction in the scene to grab nodes) and the sucker did an entire directory display all over the place.

No comments: