Wednesday Jan 23, 2013

org.openide.nodes.NodeListener

Here's a node hierarchy, with 4 selected, followed by a right-click, which results in a "Delete" menu item being shown:

Click the menu item and you see this dialog:

Click Yes and then all 4 are gone:

How to implement this?

  1. Enable the Delete Action on the ExplorerManager. The "true" below causes the "Confirm Deletion" dialog to appear.
    ActionMap map = getActionMap();
    map.put("delete", ExplorerUtils.actionDelete(controler, true));
    
    associateLookup(ExplorerUtils.createLookup(controler, map));
  2. Make the Node deletable. Make sure that the underlying object is in the Node Lookup. Then return "true" in "canDestroy", include the "DeleteAction" in "getActions", and, most important of all, call "fireNodeDestroyed" in "destroy":
    public class MansionNode extends BeanNode {
    
        public MansionNode(Mansion bean) throws IntrospectionException {
            super(bean, Children.LEAF, Lookups.singleton(bean));
            setDisplayName("Mansion: " + bean.getCity());
            setIconBaseWithExtension("com/mit/movie/viewer/resources/movie-orange-icon.gif");
        }
    
        @Override
        public boolean canDestroy() {
            return true;
        }
    
        @Override
        public Action[] getActions(boolean context) {
            return new Action[]{(SystemAction.get(DeleteAction.class))};
        }
    
        @Override
        public void destroy() throws IOException {
            fireNodeDestroyed();
        }
        
    }
  3. Implement NodeListener in the ChildFactory. The interesting thing is that when you implement "NodeListener", the "nodeDestroyed" is automatically called by "fireNodeDisplayed" in the Node's "destroy". So, the link between the Node and the ChildFactory does not need to be provided by ChangeSupport, which is how Toni did it in a cool example he made on this topic. Instead, the NodeListener, added to the Node, listens for the "fireNodeDestroyed" in the "destroy".
    public class MansionChildFactory extends ChildFactory<Mansion> implements NodeListener {
    
        private final Actor actor;
        private List<Mansion> mansions;
    
        public MansionChildFactory(Actor actor) {
            this.actor = actor;
            mansions = new ArrayList<Mansion>();
            mansions.addAll(actor.getMansions());
    
        }
    
        @Override
        protected boolean createKeys(List<Mansion> list) {
            list.addAll(mansions);
            return true;
        }
    
        @Override
        protected Node createNodeForKey(Mansion key) {
            MansionNode mansionNode = null;
            try {
                mansionNode = new MansionNode(key);
                mansionNode.addNodeListener(this);
            } catch (IntrospectionException ex) {
                Exceptions.printStackTrace(ex);
            }
            return mansionNode;
        }
    
        @Override
        public void nodeDestroyed(NodeEvent ev) {
            Mansion removedMansion = ev.getNode().getLookup().lookup(Mansion.class);
            mansions.remove(removedMansion);
            refresh(true);
        }
    
        @Override
        public void childrenAdded(NodeMemberEvent nme) {
        }
    
        @Override
        public void childrenRemoved(NodeMemberEvent nme) {
        }
    
        @Override
        public void childrenReordered(NodeReorderEvent nre) {
        }
    
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
        }
        
    }

There's only one problem with the above. Let's assume that instead of "MansionChildFactory", we have "PersonChildFactory", with a "createNodesForKey" that creates either an ActorNode or a DirectorNode. Under these circumstances, the above sequence doesn't work. In short, I don't know how to set up the above for a ChildFactory that uses "createNodesForKey" instead of "createNodeForKey".

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« January 2013 »
SunMonTueWedThuFriSat
  
25
26
27
30
  
       
Today