Wednesday Jun 12, 2013

Adding a Palette to a MultiViewElement

The question of the day comes from Michele Vigilante from Italy who wants to combine a Palette with a MultiViewElement.

The two key references to solving this are the following:

Here's step by step how to put the pieces together, starting from the application described here:

https://blogs.oracle.com/geertjan/entry/how_to_create_a_satellite

  1. Create a Node Hierarchy. Typically you already have a hierarchy of nodes, but for the sake of argument, here's the one I'll be using, as simple as it gets:
    Node nodeHierarchy = new AbstractNode(Children.create(new ChildFactory<String>() {
        @Override
        protected boolean createKeys(List toPopulate) {
            for (int i = 0; i < 10; i++) {
                toPopulate.add("Category " + i);
            }
            return true;
        }
        @Override
        protected Node createNodeForKey(String key) {
            AbstractNode an = new AbstractNode(Children.create(new ChildFactory<String>() {
                @Override
                protected boolean createKeys(List<String> toPopulate) {
                    for (int i = 0; i < 10; i++) {
                        toPopulate.add("Item " + i);
                    }
                    return true;
                }
                @Override
                protected Node createNodeForKey(final String key) {
                    AbstractNode an = new AbstractNode(Children.LEAF, Lookups.singleton(key));
                    an.setDisplayName(key);
                    return an;
                }
            }, true));
            an.setDisplayName(key);
            return an;
        }
    }, true));
  2. Create a Palette from the Node Hierarchy. For the below, your module will need to depend on "Common Palette", which it won't be able to do unless it has been set as part of the application. Also, make sure to add the Palette to the Lookup of the MultiViewElement, so that the Palette will open/close with the MultiViewElement, together with the Lookup that has already been defined for it, by adding the following to the end of the MultiViewElement constructor:
    InstanceContent ic = new InstanceContent();
    Lookup dynamicLookup = new AbstractLookup(ic);
    lookup = new ProxyLookup(dynamicLookup, getLookup());
    ic.add(PaletteFactory.createPalette(nodeHierarchy, new PaletteActions() {
        @Override
        public Action[] getImportActions() {
            return null;
        }
        @Override
        public Action[] getCustomPaletteActions() {
            return null;
        }
        @Override
        public Action[] getCustomCategoryActions(Lookup category) {
            return null;
        }
        @Override
        public Action[] getCustomItemActions(Lookup item) {
            return null;
        }
        @Override
        public Action getPreferredAction(Lookup item) {
            return null;
        }
    }));
  3. Accept the Drop. Now, when the Visual tab opens, the user sees a Palette with items in it. Let's do something useful with the Palette, again in the MultiViewElement, somewhere in the constructor where the Scene is retrieved from the Lookup:
    scene.getActions().addAction(ActionFactory.createAcceptAction(new AcceptProvider() {
        @Override
        public ConnectorState isAcceptable(Widget widget, Point point, Transferable transferable) {
            return ConnectorState.ACCEPT;
        }
        @Override
        public void accept(Widget widget, Point point, Transferable transferable) {
            Node transferredNode = NodeTransfer.node(transferable, NodeTransfer.DND_COPY_OR_MOVE);
            String label = transferredNode.getLookup().lookup(String.class);
            if (label != null) {
                LabelWidget lw = new LabelWidget(scene, label);
                lw.setPreferredLocation(point);
                lkp.lookup(LayerWidget.class).addChild(lw);
                try {
                    String existingContent = obj.getPrimaryFile().asText();
                    String newContent = existingContent + "\n" + label;
                    OutputStream os = obj.getPrimaryFile().getOutputStream();
                    OutputStreamWriter writer = new OutputStreamWriter(os);
                    writer.write(newContent);
                    writer.flush();
                    writer.close();
                } catch (FileAlreadyLockedException ex) {
                    Exceptions.printStackTrace(ex);
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }
    }));

    Now, when an item is dropped, if the Node has a String in its Lookup, a LabelWidget is added to the LayerWidget and the String is also added to the underlying file.

That's all you need to do to get started with a simple scenario that can be extended however you like.

All the source code discussed above is integrated into the sample:

https://java.net/projects/nb-api-samples/sources/api-samples/show/versions/7.3/misc/ABCFileTypeNavigator

Are you trying out the code discussed in this blog entry and something doesn't work for you? Go to the location above and look at the source code and/or check it out from its repo.

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
« June 2013 »
SunMonTueWedThuFriSat
      
29
30
      
Today