The Source for Java Technology Collaboration

Home » java.net Forums » Java Desktop Technologies » Swing & AWT

Thread: Is there a way to have a "default action map"?

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 5 - Last Post: Dec 8, 2005 1:30 PM by: idk
skelvin

Posts: 57
Is there a way to have a "default action map"?
Posted: Nov 30, 2005 3:35 AM
  Click to reply to this thread Reply

I am looking for a way to add sensible behavior for ctrl-backspace and ctrl-delete to all text components.

I can modify the default input maps for all text components by getting the input maps from UIManager, e.g.
UIManager.getDefaults().get("TextArea.focusInputMap");

So that's the first half of the job.

The action part is trickier:
I have written custom actions DeleteToPreviousWord and DeleteToNextWord, because there are no default actions with this functionality.
These actions work fine, when added to the action map of a single text component.
Now, is there a way to globally add these actions to the action maps of all components?

I'll try and have a look at auxiliary look and feels, maybe that is a way.

In the mean time any suggestions are greatly welcome.

leouser

Posts: 1,160
Re: Is there a way to have a "default action map"?
Posted: Nov 30, 2005 6:37 AM   in response to: skelvin
  Click to reply to this thread Reply

There doesn't seem to be a clear way to do this via the API. Each maps ultimate parent appears unique. I guess I would create a factory object and get my JTextComponents from it. Then the factory object could be the thing responsible for setting up the InputMaps and ActionMaps.

getJTextField( args... )
getJTextPane( args... )
getJEditorPane( args... )
setDefaultActionMap( ActionMap )
setDefaultInputMap( InputMap )

leouser

idk

Posts: 174
Re: Is there a way to have a "default action map"?
Posted: Nov 30, 2005 11:00 AM   in response to: skelvin
  Click to reply to this thread Reply

Hi,

Could you try something like this:
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.text.TextAction;
 
 
public class Test {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(
            new Runnable() {
                public void run() {
                    initUI();
                }
            });
    }
    static void initUI() {
        InputMap map = (InputMap) UIManager.getDefaults().get("TextArea.focusInputMap");
        InputMap myMap = new InputMap();
        map.setParent(myMap);
        myMap.put(KeyStroke.getKeyStroke("ctrl pressed D"), new MyTextAction());
        
        JFrame frame = new JFrame("test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JTextArea());
        frame.pack();
        frame.setVisible(true);
    }
    public static class MyTextAction extends TextAction {
        MyTextAction() {
            super("MyTextAction");
        }
        public void actionPerformed(ActionEvent e) {
            System.out.println("Action  performed on " + getTextComponent(e));
        }
    }
}
 


Thanks,
Igor

leouser

Posts: 1,160
Re: Is there a way to have a "default action map"?
Posted: Nov 30, 2005 2:06 PM   in response to: idk
  Click to reply to this thread Reply

Interesting, the code may well prove to be the "default action map" for text components. Im assuming that when the widget comes into focus that action map becomes the map for the widget. Cool stuff.

leouser

skelvin

Posts: 57
Re: Is there a way to have a "default action map"?
Posted: Dec 1, 2005 3:42 AM   in response to: idk
  Click to reply to this thread Reply

Igor, thanks a lot!
It works nicely, even for JEditorPane which use an editor kit.
Can you tell me why it works?
Is it a general rule: If you put an action as value in the input map, then it is used directly, skipping the mapping from input-map-value-TO-action-map-key-TO-action-value?

Previously I found that after I created the first JTextArea, UIManager.getDefaults().get("Text.Area.actionMap") does indeed return a default map, that I can use to add additional actions.
However that does not work for editor panes, because each is configured from their editor kit individual (no defaults).

Another attempt worked fine, but seems really hacky to me:
I created and added an auxiliary LAF that overrides LookAndFeel.getDefaults() and returned an instance of a subclass of UIDefaults. That subclass overrides UIDefaults.getUI(JComponent target) to install the actions on each target (that is a text component) separately, but then returns null, so that no additional UI is created.
The Multiplexing LAF is optimized to return the single original UI in that case, so that no overhead occurs after the initial creation.
So you can use the auxiliary LAF as a hook to intercept the creation of any JComponent - quite funny.

Your approach is by far the best, I only wonder why it works? Can you point me to some source code in the JDK?

idk

Posts: 174
Re: Is there a way to have a "default action map"?
Posted: Dec 8, 2005 1:30 PM   in response to: skelvin
  Click to reply to this thread Reply

Hi,

> I only wonder why it works?

My example uses only InputMap. It does not use ActionMap at all. It
uses the actual Action as a key in InputMap. I was surprised it works too.

It so happened that text-components can deal with it. If key in
InputMap is an Action this Action is used directly without going to
ActionMap. (see javax.swing.text.JTextComponent.KeymapActionMap)

Guess clearer solutions would be to modify both default ActionMap and default InputMap.

see javax.swing.plaf.basic.BasicTextUI.getInputMap and getActionMap

Default ActionMap is a parent of ActionMap created from the EditorKit.
(Default ActionMap is created when BasicTextUI.getActionMap is first invoked)

- Igor




 XML java.net RSS