Package syn3d.base

Source Code of syn3d.base.PluginManager

/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2004, by :
*     Corporate:
*         EADS Corporate Research Center
*     Individual:
*         Nicolas Brodu
*
* $Id: PluginManager.java,v 1.5 2005/09/02 11:57:30 ogor Exp $
*
* Changes
* -------
* 19-Mar-2004 : Creation date (NB);
*
*/
package syn3d.base;


import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import syn3d.nodes.NodeResourcesManager;

/**
* This is a central repository for Syn3D plugins
*
* @author nicolas brodu
*/
public class PluginManager {

    /** Vector of Syn3DPlugin objects, correspongin to all plugins already registerd */
    public  Vector plugins;
   
    /**
     * Vector of NodeFactory objects, constructed from the plugins capacities
     * This Vector is guaranteed to be alphabetically sorted
     */
    public  Vector nodeFactories;
   
   
    public PluginManager(){
       plugins = new Vector();
       nodeFactories = new Vector();
    }
   
    public void register(String className) {
    Class c;
    try {
      c = Class.forName(className);
    }
    catch (ClassNotFoundException cnfe) {
      return;
    }

    // Avoid duplicates. Can't use Set as we want to avoid duplication of class, not instance...
    if (getPlugin(c)!=null) return; // plugin already loaded
   
    Object o;
    try {
      o = c.newInstance();
    } catch (Exception e) {
      return;
    }
    if (o==null) return;
    if (!(o instanceof Syn3DPlugin)) return;

    // Now add this new plugin
    Syn3DPlugin p = (Syn3DPlugin)o;
    p.setPluginManager(this);
    plugins.add(p);
    String[] nodeTypes = p.getNodes();
    // Insert the new factories in alpha order
    for (int i=0; i<nodeTypes.length; ++i) {
        int insertPoint = 0;
        for(;insertPoint<nodeFactories.size(); ++insertPoint) {
            if (nodeFactories.get(insertPoint).toString().compareTo(nodeTypes[i]) > 0) break;
        }
        nodeFactories.add(insertPoint, new NodeFactory(p,nodeTypes[i]));
    }
   
    };
   
    public Syn3DPlugin getPlugin(Class c) {
    for (Iterator it = plugins.iterator(); it.hasNext();) {
        Syn3DPlugin p = (Syn3DPlugin)it.next();
        if (p.getClass().equals(c)) return p;
    }
        return null;
    }
   
   
    /** Return a Vector of NodeFactory objects capable of creating a child for the parent, in alphabetical order.
     * @param parent The ActiveNode for which a new child is desired
     * @return a Vector, possibly empty, of NodeFactory objects capable of creating a child for the parent.
     */
   
    public Vector getNodeFactoriesFor(ActiveNode parent) {
        Vector ret = new Vector();
    for (Iterator it = nodeFactories.iterator(); it.hasNext();) {
        NodeFactory nf = (NodeFactory)it.next();
        if (nf.canCreate(parent)) ret.add(nf);
    }
        return ret;
    }
   
    /**
     * Utility wrapper around getNodeFactoriesFor method to create a ready to use popup menu.
     * If the user selects an entry in the popup menu, the corresponding child will be created
     * in the parent, and the given listener will be notified.
     * @param parent The parent node for for which a new child is desired
     * @param listener An optional listener (possibly null) which will be notified if a child was created.
     *  The corresponding ActionEvent source is the new child, id = 1, and cmd = "childCreated". Use
     *  (ActiveNode(child)).getParent() on to get the parent back, if needed.
     * @return A ready to use popup menu, or null if no child can be created for this parent. The menu
     * is ready to be shown, but the caller may add more entries if necessary.
     */
    public JPopupMenu getChildMenu(final ActiveNode parent, final ActionListener listener) {
        JPopupMenu ret = new JPopupMenu();
        Vector factories = getNodeFactoriesFor(parent);
        if (factories.size()==0) return null;
        Vector currentItems = new Vector();
        // Process all factories to build the popup menu
    for (Iterator it = factories.iterator(); it.hasNext();) {
        final NodeFactory nf = (NodeFactory)it.next();
        String type = nf.getNodeType();
          // Dispatch entries using the "|" separators to build sub-menus
        StringTokenizer st = new StringTokenizer(type,"|");
        for (int depth = 0; st.hasMoreTokens(); ++depth) {
            String token = st.nextToken();
            JMenuItem item;
            // If more token exists, then this entry is a submenu, not just a single item
            if (st.hasMoreTokens()) {
                  // If the menu already exists continue
                if ((depth<currentItems.size())
                && (currentItems.get(depth) instanceof JMenu)
                && ((JMenu)currentItems.get(depth)).getText().equals(token))
                    continue;
                  // The menu does not correspond. Create a new one
                  item = new JMenu(token);
            }
            // So, it is a single item, either the last item in the list, or a at top-level
            else {
                item = new JMenuItem(token);
                // This is a single item, it can lead to child creation => add the adequate listener
              item.addActionListener(new ActionListener() {
                      public void actionPerformed(ActionEvent e) {
                          ActiveNode child = nf.create(parent);
                          if(child!=null){
                            listener.actionPerformed(new ActionEvent(child,1,"childCreated"));
                          }
                      }
              });
            }
                if (depth==0) {
                    // first entry => use top-level popup menu
                    ret.add(item);
                    // Remove any item in the list
                    currentItems.clear();
                } else {
                    // previous item is menu by construction. Add this new item
                    ((JMenu)currentItems.get(depth-1)).add(item);
                    // remove trailing items, including the old menu at this depth
                    while (depth<currentItems.size()) currentItems.remove(depth);
                }

                // Add this menu at its right place in all cases
                currentItems.add(item);
        }
    }
    // finished!
        return ret;
    }

    public void  showProperties(final ActiveNode parent, final ActionListener listener) {
      parent.doAction(NodeResourcesManager.getResources().getString("Properties"));
   
    }

}


TOP

Related Classes of syn3d.base.PluginManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.