/*
* File : Actions.java
* Created : 18-dec-2001 10:48
* By : fbusquets
*
* JClic - Authoring and playing system for educational activities
*
* Copyright (C) 2000 - 2005 Francesc Busquets & Departament
* d'Educacio de la Generalitat de Catalunya
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details (see the LICENSE file).
*/
package edu.xtec.util;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JComponent;
/**
* Miscellaneous utilities for managing {@link javax.swing.Action} objects.
*
* EXAMPLES:
*
* Creation of a new action, with reference to a original key:
*
*
* AbstractAction beginAction=new AbstractAction(DefaultEditorKit.beginAction){
* public void actionPerformed(ActionEvent e){
* // ...
* }
* };
*
*
* Creation of a new action, with a new key:
*
*
* AbstractAction prevTargetAction=new AbstractAction("prev-target"){
* public void actionPerformed(ActionEvent e){
* // ...
* }
* };
*
*
* Action that references an existing one:
*
*
* Action kitUpAction=null;
* AbstractAction upAction=new AbstractAction(DefaultEditorKit.upAction){
* public void actionPerformed(ActionEvent e){
* if(kitUpAction!=null){
* // .... pre-action
* kitUpAction.actionPerformed(e);
* // .... post-action
* }
* }
* };
*
*
* Actions mapping:
*
*
* protected void setActions(){
* // get existing actions:
* kitUpAction=getActionMap().get(DefaultEditorKit.upAction);
*
* // actionKeys init:
* java.util.HashMap actionKeys=Actions.getActionKeys(this);
*
* // build new ActionMap:
* ActionMap am=new ActionMap();
* am.setParent(getActionMap());
* setActionMap(am);
*
* //Actions derived to trace (only for debug purposes):
* Actions.mapTraceAction(this, actionKeys, DefaultEditorKit.readOnlyAction);
* Actions.mapTraceAction(this, actionKeys, DefaultEditorKit.writableAction);
* Actions.mapTraceAction(this, actionKeys, "requestFocus");
* Actions.mapTraceAction(this, actionKeys, "toggle-componentOrientation");
*
* //Actions to disable:
* Actions.mapNullAction(this, actionKeys, DefaultEditorKit.beepAction);
*
* //New actions:
* Actions.mapAction(this, actionKeys, beginAction);
* Actions.mapAction(this, actionKeys, upAction);
*
* //Original actions mapped to other methods:
* Actions.mapAction(this, actionKeys, beginAction, DefaultEditorKit.previousWordAction);
* Actions.mapAction(this, actionKeys, prevTargetAction, DefaultEditorKit.beginParagraphAction);
*
* //Uncomment this line only if you want to hide all other actions:
* //am.setParent(null);
* //
*
* // Assign keystrokes to a new action:
* getInputMap().put(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_TAB, java.awt.Event.SHIFT_MASK), prevTargetAction.getValue(Action.NAME));
* }
*
* @author Francesc Busquets (fbusquets@xtec.cat)
* @version 13.08.08
*/
public abstract class Actions {
/**
* Collects the keys of all the actions linked to a specific
* {@link javax.swing.JComponent} and groups them in arrays by action names.
* @param jc The JComponent with the actions linked to.
* @return A HashMap formed by pairs of action names (key) and arrays of action keys
* (value). Usually each action name has only one action key associated to it, and
* the value of the pair is an object array with only one string, but this is not
* an imperative: several actions can be associated to a single name.
*/
public static Map getActionKeys(JComponent jc){
Map result=new HashMap();
ActionMap am=jc.getActionMap();
for(Object amk : am.allKeys()){
Action act=am.get(amk);
Object o=act.getValue(Action.NAME);
if(o==null)
o="";
String name=o.toString();
Object[] keys=result.get(name);
if(keys==null)
keys=new Object[]{amk};
else{
Object[] k2=new Object[keys.length+1];
int j;
for(j=0; j actionKeys, ActionMap am){
for(String key : actionKeys.keySet()){
System.out.println(key+":");
for(Object val : (Object[])actionKeys.get(key))
System.out.println(" - "+val+" >> "+am.get(val));
}
}
public static void mapAction(JComponent jc, Map actionKeys, Action act) {
if (actionKeys == null) {
actionKeys = getActionKeys(jc);
}
if (jc != null && act != null && actionKeys != null) {
ActionMap am = jc.getActionMap();
String name = (String)act.getValue(Action.NAME);
Object[] keys = actionKeys.get(name);
boolean replaced = false;
if (keys != null) {
for (Object key : keys) {
am.put(key, act);
if (key.equals(name)) {
replaced = true;
}
}
}
if (!replaced) {
am.put(name, act);
}
}
}
public static void mapAction(JComponent jc, Map actionKeys, Action act, String key) {
if (actionKeys == null) {
actionKeys = getActionKeys(jc);
}
if (jc != null && actionKeys != null) {
ActionMap am = jc.getActionMap();
Object[] keys = actionKeys.get(key);
boolean replaced = false;
if (keys != null) {
for (Object k : keys) {
am.put(k, act);
if (k.equals(key)) {
replaced = true;
}
}
}
if (!replaced) {
am.put(key, act);
}
}
}
public static class NullAction extends AbstractAction{
public NullAction(String name){
super(name);
}
public void actionPerformed(ActionEvent e){
// do nothing
}
}
public static void mapNullAction(JComponent jc, Map actionKeys, String s){
mapAction(jc, actionKeys, new edu.xtec.util.Actions.NullAction(s));
}
public static class TraceAction extends AbstractAction{
Action bkAction=null;
Object bkKey=null;
public TraceAction(Action act, Object key){
super((String)(key instanceof String ? key:""));
bkAction=act;
bkKey=key;
}
public void actionPerformed(ActionEvent e){
System.out.println("TRACE: "+(bkAction!=null ? bkAction.getValue(Action.NAME):"")+" "+bkKey);
if(bkAction!=null)
bkAction.actionPerformed(e);
}
}
public static void mapTraceAction(JComponent jc, Map actionKeys, String s){
mapAction(jc, actionKeys, new edu.xtec.util.Actions.TraceAction(jc.getActionMap().get(s), s));
}
public static void traceHierarchy(Component cmp, int level){
StringBuilder sb=new StringBuilder();
for(int i=0; i