Archiv für Oktober 2009

Creating An Explorer View with the Visual Library (3)

Montag, 05. Oktober 2009

As Geertjan has recently blogged, I’ve started creating an Explorer View with the Visual Library (1/2) as an example for the NetBeans Platform Certified Training that we held in Göttingen recently.

The example is still very basic and it misses a lot of functionality, e.g. it doesn’t listen on the ExplorerManager and it’s events, but I hope to be able to further extend this example to make it a real Explorer View over the next weeks. I like the fact that Geerjan picked up the example and enhanced it with some functionality. So if you think this is going too slow, feel free to extend the sample and blog about it. I’d like to finally host it as an example at Kenai when it’s finished.

As a next step,  we can expose the Node Actions via our Widgets:

To do so we should first convert our Scene to an ObjectScene. ObjectScenes are intended to make it easier to get hold of an Object that is represented by a Widget. Next I’ve added an action to each Widget that provides a PopupMenu with the Actions of the respective Node. With the ObjectScene we also don’t need to store Node references in the SelectionProvider, so we can reuse one instance for all Widgets:

import java.awt.Point;
import java.beans.BeanInfo;
import java.beans.PropertyVetoException;

import javax.swing.Action;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.PopupMenuProvider;
import org.netbeans.api.visual.action.SelectProvider;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.model.ObjectScene;
import org.netbeans.api.visual.widget.Widget;
import org.netbeans.api.visual.widget.general.IconNodeWidget;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;

public class VisualLibraryView extends JScrollPane {

    ExplorerManager em;
    ObjectScene scene;
    WidgetAction popupAction;
    WidgetAction selectAction;

    public VisualLibraryView() {
        popupAction = ActionFactory.createPopupMenuAction(new PopupMenuProviderImpl());
        selectAction = ActionFactory.createSelectAction(new SelectProviderImpl());
    }

    @Override
    public void addNotify() {
        super.addNotify();
        ExplorerManager m = ExplorerManager.find(this);
        if (m == em) {
            // do nothing
        } else {
            em = m;
            scene = new ObjectScene();

            Node root = em.getRootContext();
            addWidgetsForNodes(root.getChildren().getNodes(), scene);

            setViewportView(scene.createView());

        }
    }

    private void addWidgetsForNodes(Node[] nodes, final ObjectScene scene) {
        for (int i = 0; i < nodes.length; i++) {
            Node node = nodes[i];
            IconNodeWidget w = new IconNodeWidget(scene, IconNodeWidget.TextOrientation.BOTTOM_CENTER);
            w.setLabel(node.getDisplayName());
            w.setImage(node.getIcon(BeanInfo.ICON_COLOR_32x32));
            w.getActions().addAction(ActionFactory.createMoveAction());
            w.setPreferredLocation(new Point(10, i * 100));
            w.setOpaque(true);
            scene.addObject(node, w);
            scene.addChild(w);
            w.getActions().addAction(selectAction);
            w.getActions().addAction(popupAction);
        }
    }

    private class PopupMenuProviderImpl implements PopupMenuProvider {

        @Override
        public JPopupMenu getPopupMenu(Widget widget, Point localLocation) {
            JPopupMenu m = new JPopupMenu();
            Object o = scene.findObject(widget);
            if (o instanceof Node) {
                Action[] actions = ((Node) o).getActions(true);
                for (int i = 0; i < actions.length; i++) {
                    m.add(actions[i]);
                }
            }
            return m;
        }
    }

    private class SelectProviderImpl implements SelectProvider {

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

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

        public void select(Widget widget, Point localLocation, boolean invertSelection) {
            try {
                ObjectScene scene = ((ObjectScene) widget.getScene());
                Object object = scene.findObject(widget);

                scene.setFocusedObject(object);
                if (object != null) {
                    if (!invertSelection && scene.getSelectedObjects().contains(object)) {
                        return;
                    }

                    scene.userSelectionSuggested(Collections.singleton(object), invertSelection);
                } else {
                    scene.userSelectionSuggested(Collections.emptySet(), invertSelection);
                }

                if (object instanceof Node) {
                    Set selected = scene.getSelectedObjects();
                    ArrayList  selectedNodes = new ArrayList();
                    for (Object object1 : selected) {
                       if (object1 instanceof Node){
                           selectedNodes.add((Node)object1);
                       }
                    }
                    em.setSelectedNodes(selectedNodes.toArray(new Node [0]));
                }
            } catch (PropertyVetoException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }
}

The next step will be to listen for changes in the ExplorerManager…