alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.java.ui.nodes.elements;

import org.openide.src.ElementProperties;
import org.openide.nodes.Node;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.util.datatransfer.NewType;
import org.openide.util.actions.SystemAction;
import org.openide.util.NbBundle;
import org.openide.actions.NewAction;
import org.openide.actions.ToolsAction;
import org.openide.actions.PropertiesAction;
import org.netbeans.jmi.javamodel.JavaClass;
import org.netbeans.jmi.javamodel.JavaEnum;
import org.netbeans.jmi.javamodel.ClassDefinition;
import org.netbeans.jmi.javamodel.AnnotationType;
import org.netbeans.modules.java.ui.nodes.SourceNodeFactory;

import java.util.Collection;
import java.util.ArrayList;
import java.util.List;

/**
 * Support for category nodes (fields, methods, ...). Use Categories.createClassChildren(...).
 * @author Petr Hamernik, Jan Pokorsky
 * 
 * XXX fix helpids
 */
public final class Categories {
    /**
     * Tag for fields category node.
     */
    private static final Object CATEGORY_FIELDS = new Object();
    /**
     * Tag for "Method" category node.
     */
    private static final Object CATEGORY_METHODS = new Object();
    /**
     * Tag for "Constructors" category node.
     */
    private static final Object CATEGORY_CONSTRUCTORS = new Object();
    /**
     * Tag for "Constants" category node
     */ 
    private static final Object CATEGORY_CONSTANTS = new Object();
    /**
     * Tag for "Members" category node.
     */
    private static final Object CATEGORY_ANN_TYPE_METHODS = new Object();
    
    private static final List CLASS_CATEGORIES;
    private static final List INTERFACE_CATEGORIES;
    private static final List ENUM_CATEGORIES;
    private static final List ANNTYPES_CATEGORIES;
    public static final int FILTER_CATEGORIES = 0x1000;
    /** Array of the actions of the category nodes. */
    private static final SystemAction[] CATEGORY_ACTIONS = new SystemAction[] {
		/*
                SystemAction.get(CopyAction.class),
		*/
        // XXX paste is not supported
//                SystemAction.get(PasteAction.class),
//                null,
                SystemAction.get(NewAction.class),
                null,
                SystemAction.get(ToolsAction.class),
                SystemAction.get(PropertiesAction.class)
            };
    /** Filters under each category node */
    static final int[][] FILTERS = new int[][] {
                                       { ClassElementFilter.FIELD },
                                       { ClassElementFilter.CONSTRUCTOR },
                                       { ClassElementFilter.METHOD },
                                       { EnumFilter.CONSTANTS },
                                       { AnnotationTypeFilter.MEMBER },
                                   };
    /** The names of the category nodes */
    static final String[] NAMES = new String[] {
                                      getString("Fields"), //NOI18N
                                      getString("Constructors"), //NOI18N
                                      getString("Methods"), //NOI18N
                                      getString("Constants"), // NOI18N
                                      getString("AnnTypeMethods") // NOI18N
                                  };
    /** The short descriptions of the category nodes */
    static final String[] SHORTDESCRS = new String[] {
                                            getString("Fields_HINT"), //NOI18N
                                            getString("Constructors_HINT"), //NOI18N
                                            getString("Methods_HINT"), //NOI18N
                                            getString("Constants_HINT"), // NOI18N
                                            getString("AnnTypeMethods_HINT") // NOI18N
                                        };
    /** Array of the icons used for category nodes */
    static final String[] CATEGORY_ICONS = new String[] {
        IconStrings.FIELDS_CATEGORY,
        IconStrings.CONSTRUCTORS_CATEGORY,
        IconStrings.METHODS_CATEGORY,
        IconStrings.CONSTANTS_CATEGORY,
        IconStrings.ANN_TYPE_METHODS_CATEGORY,
    };
    
    /** Create children for a class node, with specified factory.
    * The default implementation used {@link org.netbeans.modules.java.ui.nodes.elements.ClassChildren}.
    * @param element a class element
    * @param factory the factory which will be used to create children
    * @return children for the class element
    */
    public static final Children createClassChildren(ClassDefinition element, SourceNodeFactory factory, boolean writable) {
        if (ElementNode.getSourceOptions().getCategoriesUsage()) {
            ClassChildren children = new Categories.CategorizingChildren(factory, element, writable);
            ClassElementFilter filter = new ClassElementFilter();
            filter.setOrder(new int[] { 
                    SourceElementFilter.CLASS, 
                    SourceElementFilter.INTERFACE,
                    SourceElementFilter.ENUM,
                    SourceElementFilter.ANNOTATION_TYPE,
                    Categories.FILTER_CATEGORIES
            });
            children.setFilter(filter);
            return children;
        } else {
            return new ClassChildren(factory, element);
        }
    }
    
    /** Create children for an enum node, with specified factory.
    * @param element a class element
    * @param factory the factory which will be used to create children
    * @return children for the class element
    */
    public static final Children createEnumChildren(JavaEnum element, SourceNodeFactory factory, boolean writable) {
        if (ElementNode.getSourceOptions().getCategoriesUsage()) {
            ClassChildren children = new Categories.CategorizingChildren(factory, element, writable);
            ClassElementFilter filter = new EnumFilter();
            filter.setOrder(new int[] { 
                    SourceElementFilter.CLASS, 
                    SourceElementFilter.INTERFACE,
                    SourceElementFilter.ENUM,
                    SourceElementFilter.ANNOTATION_TYPE,
                    Categories.FILTER_CATEGORIES
            });
            children.setFilter(filter);
            return children;
        } else {
            return new EnumChildren(factory, element);
        }
    }
    
    /** Create children for an enum node, with specified factory.
    * @param element a class element
    * @param factory the factory which will be used to create children
    * @return children for the class element
    */
    public static final Children createAnnotationTypeChildren(AnnotationType element, SourceNodeFactory factory, boolean writable) {
        if (ElementNode.getSourceOptions().getCategoriesUsage()) {
            ClassChildren children = new Categories.CategorizingChildren(factory, element, writable);
            ClassElementFilter filter = new AnnotationTypeFilter();
            filter.setOrder(new int[] { 
                    SourceElementFilter.CLASS, 
                    SourceElementFilter.INTERFACE,
                    SourceElementFilter.ENUM,
                    SourceElementFilter.ANNOTATION_TYPE,
                    Categories.FILTER_CATEGORIES
            });
            children.setFilter(filter);
            return children;
        } else {
            return new AnnotationTypeChildren(factory, element);
        }
    }

    static {
        CLASS_CATEGORIES = new ArrayList(4);
        CLASS_CATEGORIES.add(CATEGORY_FIELDS);
        CLASS_CATEGORIES.add(CATEGORY_CONSTRUCTORS);
        CLASS_CATEGORIES.add(CATEGORY_METHODS);
        
        INTERFACE_CATEGORIES = new ArrayList(2);
        INTERFACE_CATEGORIES.add(CATEGORY_FIELDS);
        INTERFACE_CATEGORIES.add(CATEGORY_METHODS);
        
        ENUM_CATEGORIES = new ArrayList(4);
        ENUM_CATEGORIES.add(CATEGORY_CONSTANTS);
        ENUM_CATEGORIES.add(CATEGORY_FIELDS);
        ENUM_CATEGORIES.add(CATEGORY_CONSTRUCTORS);
        ENUM_CATEGORIES.add(CATEGORY_METHODS);
        
        ANNTYPES_CATEGORIES = new ArrayList(2);
        ANNTYPES_CATEGORIES.add(CATEGORY_FIELDS);
        ANNTYPES_CATEGORIES.add(CATEGORY_ANN_TYPE_METHODS);
    }

    /*
     * Simple descendant of ClassChildren that distributes nodes from the class to various
     * categories. Since - when categories are used - only innerclass, inner interface
     * and categories can be displayed under 
     */
    static final class CategorizingChildren extends ClassChildren {
        boolean writeable;
        
        static {
            ClassChildren.propToFilter.put(ElementProperties.PROP_CLASS_OR_INTERFACE, 
            new Integer(FILTER_CATEGORIES));
        }
        
        CategorizingChildren(SourceNodeFactory factory, ClassDefinition data, boolean wr) {
            super(factory, data);
            writeable = wr;
        }
        
        protected Node[] createNodesImpl(Object key) {
            if (key == CATEGORY_FIELDS) {
                return new Node[] {
                        new ElementCategoryNode(0, getFactory(), element, writeable)
                };
            } else if (key == CATEGORY_METHODS) {
                return new Node[] {
                        new ElementCategoryNode(2, getFactory(), element, writeable)
                };
            } else if (key == CATEGORY_CONSTRUCTORS) {
                return new Node[] {
                    new ElementCategoryNode(1, getFactory(), element, writeable)
                };
            } else if (key == CATEGORY_CONSTANTS) {
                return new Node[] {
                    new ElementCategoryNode(3, getFactory(), element, writeable)
                };
            } else if (key == CATEGORY_ANN_TYPE_METHODS) {
                return new Node[] {
                    new ElementCategoryNode(4, getFactory(), element, writeable)
                };
            }
            return super.createNodesImpl(key);
        }
        
        protected List getKeysOfType(Collection/**/ elements, int type) {
            if (type != FILTER_CATEGORIES)
                return super.getKeysOfType(elements, type);
            if (element instanceof JavaEnum) {
                return ENUM_CATEGORIES;
            } else if (element instanceof AnnotationType) {
                    return ANNTYPES_CATEGORIES;
            } else if (element instanceof JavaClass && ((JavaClass) element).isInterface()) {
                return INTERFACE_CATEGORIES;
            } else {
                return CLASS_CATEGORIES;
            }
        }
    }

    /**
    * Category node - represents one section under class element node - fields,
    * constructors, methods.
    */
    static final class ElementCategoryNode extends AbstractNode {

        /** The class element for this node */
        ClassDefinition element;

        /** The type of the category node - for new types. */
        int newTypeIndex;
        
        private static ClassChildren createChildren(SourceNodeFactory f, ClassDefinition jc) {
            ClassChildren cc;
            if (jc instanceof AnnotationType) {
                cc = new AnnotationTypeChildren(f, (AnnotationType) jc);
            } else if (jc instanceof JavaEnum) {
                cc = new EnumChildren(f, (JavaEnum) jc);
            } else {
                cc = new ClassChildren(f, jc);
            }
            return cc;
        }
        
        /** Create new element category node for the specific category.
        * @param index The index of type (0=fields, 1=constructors, 2=methods)
        * @param factory The factory which is passed down to the class children object
        * @param element the class element which this node is created for
        */
        ElementCategoryNode(int index, SourceNodeFactory factory, ClassDefinition element, boolean writeable) {
            this(index, createChildren(factory, element));
            this.element = element;
            newTypeIndex = writeable ? index : -1;
            switch (index) {
                case 0: setName("Fields"); break; // NOI18N
                case 1: setName("Constructors"); break; // NOI18N
                case 2: setName("Methods"); break; // NOI18N
                case 3: setName("Constants"); break; // NOI18N
                case 4: setName("AnnTypeMethods"); break; // NOI18N
            }
        }

        /** Create new element node.
        * @param index The index of type (0=fields, 1=constructors, 2=methods)
        * @param children the class children of this node
        */
        private ElementCategoryNode(int index, ClassChildren children) {
            super(children);
            setDisplayName(NAMES[index]);
            setShortDescription(SHORTDESCRS[index]);
            ClassElementFilter filter = new ClassElementFilter();
            filter.setOrder(FILTERS[index]);
            children.setFilter(filter);
            systemActions = CATEGORY_ACTIONS;
            setIconBase(CATEGORY_ICONS[index]);
        }

        /** Disables copy for the whole category. Sub-elements need to be selected individually.
         */
        public boolean canCopy() {
            return false;
        }

        /* Get the new types that can be created in this node.
        * @return array of new type operations that are allowed
        */
        public NewType[] getNewTypes() {
            if (!SourceEditSupport.isWriteable(element) || !(element instanceof JavaClass)) {
                return new NewType[0];
            }
            
            JavaClass jc = (JavaClass) this.element;
            
            switch(newTypeIndex) {
                case 0:
                    return new NewType[] {
                               new SourceEditSupport.ElementNewType(jc, SourceEditSupport.NT_FIELD)
                           };
                case 1:
                    return new NewType[] {
                               new SourceEditSupport.ElementNewType(jc, SourceEditSupport.NT_INITIALIZER),
                               new SourceEditSupport.ElementNewType(jc, SourceEditSupport.NT_CONSTRUCTOR)
                           };
                case 2:
                    return new NewType[] {
                               new SourceEditSupport.ElementNewType(jc, SourceEditSupport.NT_METHOD)
                           };
                case 3:
                    return new NewType[] {
                               new SourceEditSupport.ElementNewType(jc, SourceEditSupport.NT_ENUMCONSTANT)
                           };
                case 4:
                    return new NewType[] {
                               new SourceEditSupport.ElementNewType(jc, SourceEditSupport.NT_ANNOTATION_TYPE_METHOD)
                           };
                default:
                    return super.getNewTypes();
            }
        }

        // XXX solve paste types
//        public void createPasteTypes(java.awt.datatransfer.Transferable t, java.util.List s) {
//            Node n = getParentNode();
//            if (n == null || !(n instanceof ClassElementNode)) {
//                return;
//            }
//            ((ClassElementNode)n).createPasteTypes(t, s);
//        }
    }
    
    private static String getString(String key) {
        return NbBundle.getMessage(Categories.class, key);
    }
    
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.