// 
//     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.
//

= DevFaqNodesDecorating
:jbake-type: wiki
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqNodesDecorating
:description: Apache NetBeans wiki DevFaqNodesDecorating
:toc: left
:toc-title:
:syntax: true

=== Decorating an entire tree of Nodes

Say you have a reference to the root of a tree of `Node` instances, and you want to add icons or actions to those nodes.  First, what you *do not* do is call `setDisplayName` or any other setter on that Node (unless you created it - the point here is that it is rude and can have bad side effects to call setters on random Nodes somebody else created - setters in APIs are bugs - the fact that Node has them is a historical artifact, not proper design).

If you own the component that will display the Nodes, this sort of thing is very easily done by subclassing `FilterNode` and overriding the appropriate methods (e.g. `getActions()`, `getIcon()`, etc.), wrapping the original node inside your `FilterNode`. Now let's say that the Node you want to decorate builds out its children in a lazy fashion, that is, only when the user expands the tree in some tree view. How would you decorate that node and all of its children, without traversing the entire tree and effectively undoing the benefits of the lazy population of the tree?

Fortunately, while this sounds rather challenging, it turns out to be surprisingly easy and simple to achieve. The trick is to subclass the `FilterNode.Children` class and override the `copyNode()` method. Below is a short example:

[source,java]
----

class NodeProxy extends FilterNode {

    public NodeProxy(Node original) {
        super(original, new ProxyChildren(original));
    }

    // add your specialized behavior here...
}

class ProxyChildren extends FilterNode.Children {

    public ProxyChildren(Node owner) {
        super(owner);
    }

    protected Node copyNode(Node original) {
        return new NodeProxy(original);
    }
}

----

As you can see, `NodeProxy` is intended to wrap around another `Node` and provide some additional appearance or behavioral changes (e.g. different icons or actions). The fun part is the `ProxyChildren` class. While very short and simple, it provides that critical ability for our `NodeProxy` to act as a decorator for not only the root node, but all of its children, and their children, and so on, without having to traverse the entire tree at once.

While `FilterNode` should NOT be used to insert additional nodes at the beginning or end of the list (see its JavaDoc), it can be easily used to filter out some of the children nodes. For instance, this refinement of `ProxyChildren` overrides the `createNodes()` method and conditionally selects the children nodes by submitting them to a custom `accept()` method:

[source,java]
----

   class ProxyChildren extends FilterNode.Children {

        public ProxyChildren (Node owner)  {
            super(owner);
          }
        
        @Override
        protected Node copyNode (Node original){
            return new NodeProxy(original);
          }
        
        @Override
        protected Node[] createNodes (Object object) {
            List<Node> result = new ArrayList<Node>();
            
            for (Node node : super.createNodes(object)) {
                if (accept(node)) {
                    result.add(node);
                  }
              }
            
            return result.toArray(new Node[0]);
          }

        private boolean accept (Node node) {
            // ...
          }
      }

----

Below a complete example of a `FileFilteredNode` that can be used to show a file hierarchy where only a subset of files is shown, selected by means of the standard `java.io.FileFilter` class:

[source,java]
----

class FileFilteredNode extends FilterNode {
   
    static class FileFilteredChildren extends FilterNode.Children {
        private final FileFilter fileFilter;
   
        public FileFilteredChildren (Node owner, FileFilter fileFilter) {
            super(owner);
            this.fileFilter = fileFilter;
          }

        @Override
        protected Node copyNode (Node original) {
            return new FileFilteredNode(original, fileFilter);
          }

        @Override
        protected Node[] createNodes (Object object) {
            List<Node> result = new ArrayList<Node>();

            for (Node node : super.createNodes(object)) {
                DataObject dataObject = (DataObject)node.getLookup().lookup(DataObject.class);

                if (dataObject != null) {
                    FileObject fileObject = dataObject.getPrimaryFile();
                    File file = FileUtil.toFile(fileObject);

                    if (fileFilter.accept(file)) {
                        result.add(node);
                      }
                  }
              }

            return result.toArray(new Node[result.size()]);
          }
      }

    public FileFilteredNode (Node original, FileFilter fileFilter) {
        super(original, new FileFilteredChildren(original, fileFilter));
      }
  }

----

Note that if you're showing the filtered nodes in a tree view according to the code above, you might find expansion handles on leaf nodes.  link:http://openide.netbeans.org/servlets/ReadMsg?listName=dev&msgNo=11595[This thread from the dev@openide list] discusses some solutions to this problem.

=== Apache Migration Information

The content in this page was kindly donated by Oracle Corp. to the
Apache Software Foundation.

This page was exported from link:http://wiki.netbeans.org/DevFaqNodesDecorating[http://wiki.netbeans.org/DevFaqNodesDecorating] , 
that was last modified by NetBeans user J.boesl 
on 2010-08-19T14:20:51Z.


*NOTE:* This document was automatically converted to the AsciiDoc format on 2018-02-07, and needs to be reviewed.
