/* ========================
* 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-2007, by :
* Corporate:
* EADS Astrium
* Individual:
* Claude Cazenave
*
* $Id: AbstractNodeAction.java,v 1.6 2008/10/15 17:22:34 cazenave Exp $
*
* Changes
* -------
* 9 janv. 08 : Initial public release
*
*/
package jsynoptic.plugins.java3d.tree;
import java.awt.Component;
import java.awt.Point;
import java.util.HashMap;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.KeyStroke;
import jsynoptic.ui.JSynoptic;
import simtools.ui.MenuResourceBundle;
import simtools.ui.ResourceFinder;
/**
* A Node action is a swing AbstractAction with a reference to a Tree Node This
* action is initialized according to Tree resources
*/
public abstract class AbstractNodeAction extends AbstractAction {
final static HashMap<String, Object[]> _actions = new HashMap<String, Object[]>();
// Reuse some jsynoptic main ui resources
public static MenuResourceBundle sharedResources = ResourceFinder.getMenu(JSynoptic.class);
public static void addActions(String className, Object... actions) {
_actions.put(className, actions);
}
private AbstractNode _node;
protected String _resourceKey;
private Point _location;
/**
* By default the resource key is equal to the class name excluding the
* package names e.g. : jsynoptic.plugins.java3d.tree.NodeAction resource
* key=NodeAction
*/
protected AbstractNodeAction() {
_resourceKey = getClass().getName();
int k = _resourceKey.lastIndexOf('.');
if (k >= 0) {
_resourceKey = _resourceKey.substring(k + 1);
}
k = _resourceKey.lastIndexOf('$');
if (k >= 0) {
_resourceKey = _resourceKey.substring(k + 1);
}
_location=null;
}
public Point getLocation(){
return _location;
}
void setLocation(Component relativeLocationComponent, int x, int y){
if(relativeLocationComponent!=null && relativeLocationComponent.isVisible()){
Point rp=relativeLocationComponent.getLocationOnScreen();
_location=new Point(rp);
_location.x+=x;
_location.y+=y;
}
else{
_location=new Point(x,y);
}
}
protected void init() {
putValue(Action.NAME, Tree.resources.getStringValue(_resourceKey
+ "Text"));
ImageIcon i = Tree.resources.getIcon(_resourceKey + "Image");
if (i != null) {
putValue(Action.SMALL_ICON, i);
}
KeyStroke k = Tree.resources.getKeyStroke(_resourceKey + "Shortcut");
if (k != null) {
putValue(Action.ACCELERATOR_KEY, k);
}
String tip = Tree.resources.getStringValue(_resourceKey + "Tip");
putValue(Action.SHORT_DESCRIPTION, tip);
}
public AbstractNode getNode() {
return _node;
}
/**
* Get actions The prefix is used to retrieve group of actions shared
* between objects. If the prefix is set the action list key is equal to
* prefix@graphObjectClassName. If there is no action list using this key
* then look for a generic action list using the prefix only. The returned
* list of action can contain String to describe a group of action to be
* added to the returned list or null to isolate members of the list (for
* instance using a menu separator) or a NodeAction class
*
* @param graphObject
* the graph object to retrieve the actions
* @param prefix
* an optional prefix to retrieve group of actions
* @return the actions
*/
public static Object[] getActions(Object graphObject, String prefix) {
Object[] actions = _actions.get(getActionKey(graphObject, prefix));
if (actions == null && prefix != null) { // generic actions
actions = _actions.get(prefix);
}
if (actions == null) {
// look for sub types
Class<?> c = graphObject.getClass().getSuperclass();
while (c != Object.class) {
actions = _actions.get(getActionKey(c, prefix));
if (actions != null) {
// keep for next call
_actions.put(getActionKey(graphObject, prefix), actions);
break;
}
c = c.getSuperclass();
}
}
// System.out.print("getActions "+((prefix==null)?"":(prefix+"@")));
// if(graphObject==null){
// System.out.print("root");
// }
// else {
// System.out.print(graphObject.getClass().getName());
// }
// System.out.print(" =");
// if(actions==null){
// System.out.println("none");
// }
// else{
// for(Object o : actions){
// if(o==null){
// System.out.print(" | ");
// }
// else if (o instanceof Class){
// System.out.print(" "+((Class)o).getName());
// }
// else{
// System.out.print(" "+o);
// }
// }
// System.out.println();
// }
return actions;
}
private static String getActionKey(Object graphObjectOrClass, String prefix) {
String res = null;
if (graphObjectOrClass == null) { // root node
res = prefix;
} else {
if (graphObjectOrClass instanceof Class) {
res = ((Class<?>) graphObjectOrClass).getName();
} else {
res = graphObjectOrClass.getClass().getName();
}
if (prefix != null) {
res = prefix + "@" + res;
}
}
return res;
}
public static AbstractNodeAction createAction(Class<?> c, AbstractNode n) {
Object a = null;
try {
a = c.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Invalid node action class : "
+ c.getName(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Invalid node action class : "
+ c.getName(), e);
}
if (!(a instanceof AbstractNodeAction)) {
throw new RuntimeException("Invalid node action class : "
+ c.getName());
}
AbstractNodeAction na = (AbstractNodeAction) a;
na._node = n;
na.init();
return na;
}
}