File: DelegateAction.java

package info (click to toggle)
libjide-oss-java 3.7.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 13,264 kB
  • sloc: java: 89,463; xml: 268; makefile: 35
file content (244 lines) | stat: -rw-r--r-- 10,647 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*
 * @(#)DelegateAction.java 10/2/2006
 *
 * Copyright 2002 - 2006 JIDE Software Inc. All rights reserved.
 */

package com.jidesoft.swing;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * DelegateAction is a special AbstractAction which can do something then delegate to another action depending on the
 * return value of {@link #delegateActionPerformed(java.awt.event.ActionEvent)}. There are two usages of it. First, you
 * can use {@link #replaceAction(javax.swing.JComponent, int, javax.swing.KeyStroke, DelegateAction)} to replace the action
 * associated with the specified keystroke with the DelegateAction. The DelegateAction will be triggered when the
 * keystroke is pressed. After DelegateAction is done, it can return true or false. If false, the original action
 * associated with the keystroke will be triggered as well. This solves the problem that {@link
 * JComponent#registerKeyboardAction(java.awt.event.ActionListener, String, javax.swing.KeyStroke, int)} will replace the
 * original action so that the original action will never be triggered.
 * <p/>
 * The second way to use DelegateAction is to delegate the action from one component to another component using {@link
 * #replaceAction(javax.swing.JComponent, int, javax.swing.JComponent, int, javax.swing.KeyStroke, DelegateAction)}. In this
 * case, the keystroke on the first component parameter will be triggered the DelegateAction. If DelegateAction returns
 * false, the registered action on the second component parameter will be triggered. If you pass in {@link
 * PassthroughDelegateAction}, the registered action on the second component will always be triggered.
 * <p/>
 * Please notes, if you call replaceAction several times on the same component with the same keystroke, it will form a
 * chain of DelegateActions. In this case, the first call will be the first DelegateAction. In the other words, the
 * first one will have the highest priority and will be triggered first. Ideally, we should assign a priority to each
 * DelegateAction. But for the sake of simplicity, we decided not doing it for now. So because of this, this class is
 * not ready to be used as public API. We have to make it public because different packages in JIDE need to use it. If
 * you want to use, please use it with caution. We don't guarantee that we will not change the public methods on this
 * classes.
 * <p/>
 */
abstract public class DelegateAction extends AbstractAction {
    private static final long serialVersionUID = -3867985431184738600L;
    private Action _action;
    private JComponent _target;

    public DelegateAction() {
    }

    public DelegateAction(Action action) {
        _action = action;
    }

    public DelegateAction(Action action, JComponent target) {
        _action = action;
        _target = target;
    }

    /**
     * Returns true if either delegateIsEnabled or the action is enabled.
     * <p/>
     * {@inheritDoc}
     */
    // Should be final like actionPerformed but not done for backward compatibility.
    @Override
    public boolean isEnabled() {
        return isDelegateEnabled() || (_action != null && _action.isEnabled());
    }

    final public void actionPerformed(ActionEvent e) {
        if (!delegateActionPerformed(e)) {
            if (_action != null) {
                if (_target == null) {
                    _action.actionPerformed(e);
                }
                else {
                    _action.actionPerformed(new ActionEvent(getTarget(), e.getID(), e.getActionCommand(), e.getWhen(), e.getModifiers()));
                }
            }
        }
    }

    protected Action getAction() {
        return _action;
    }

    protected void setAction(Action action) {
        _action = action;
    }

    protected JComponent getTarget() {
        return _target;
    }

    protected void setTarget(JComponent target) {
        _target = target;
    }

    /**
     * Checks if an action can be performed. Returns true if delegateActionPerformed would perform an action. Otherwise
     * returns false.
     *
     * @return <code>true</code> if the action can be performed.
     */
    // Should be abstract like delegateActionPerformed but not done for backward compatibility.
    public boolean isDelegateEnabled() {
        return super.isEnabled();
    }

    /**
     * Performs an action. Returns true if no further action should be taken for this keystroke. Otherwise, returns
     * false.
     *
     * @param e the action event.
     * @return true if no further action should be taken for this keystroke. Otherwise, returns false.
     */
    abstract public boolean delegateActionPerformed(ActionEvent e);

    public static class PassthroughDelegateAction extends DelegateAction {
        private static final long serialVersionUID = -1555177105658867899L;

        @Override
        public boolean delegateActionPerformed(ActionEvent e) {
            return false;
        }

        @Override
        public boolean isDelegateEnabled() {
            return false;
        }
    }

    public static void replaceAction(JComponent component, int condition, KeyStroke keyStroke, DelegateAction delegateAction) {
        replaceAction(component, condition, component, condition, keyStroke, delegateAction);
    }

    public static void replaceAction(JComponent component, int condition, KeyStroke keyStroke, DelegateAction delegateAction, boolean first) {
        replaceAction(component, condition, component, condition, keyStroke, delegateAction, first);
    }

    public static void replaceAction(JComponent component, int condition, JComponent target, int targetCondition, KeyStroke keyStroke) {
        replaceAction(component, condition, target, targetCondition, keyStroke, new DelegateAction.PassthroughDelegateAction(), false);
    }

    public static void replaceAction(JComponent component, int condition, JComponent target, int targetCondition, KeyStroke keyStroke, DelegateAction delegateAction) {
        replaceAction(component, condition, target, targetCondition, keyStroke, delegateAction, false);
    }

    public static void replaceAction(JComponent component, int condition, JComponent target, int targetCondition, KeyStroke keyStroke, DelegateAction delegateAction, boolean first) {
        ActionListener action = component.getActionForKeyStroke(keyStroke);
        if (action != delegateAction && action instanceof Action) {
            if (!first && action instanceof DelegateAction) {
                Action childAction = ((DelegateAction) action).getAction();
                while (childAction != null) {
                    if (childAction == delegateAction) {
                        return;
                    }
                    if (childAction instanceof DelegateAction) {
                        childAction = ((DelegateAction) childAction).getAction();
                    }
                    else {
                        childAction = null;
                    }
                }
                delegateAction.setAction(((DelegateAction) action).getAction());
                ((DelegateAction) action).setAction(delegateAction);
                delegateAction = (DelegateAction) action;
            }
            else {
                delegateAction.setAction((Action) action);
            }
        }

        if (target != component) {
            delegateAction.setTarget(target);
            replaceAction(component, condition, keyStroke, delegateAction);
        }
        else {
            Object actionCommand = target.getInputMap(targetCondition).get(keyStroke);
            if (actionCommand == null) {
                component.registerKeyboardAction(delegateAction, keyStroke, condition);
            }
            else {
                component.getActionMap().put(actionCommand, delegateAction);
            }
        }
    }

    public static void restoreAction(JComponent component, int condition, KeyStroke keyStroke) {
        if (component == null) {
            return;
        }
        ActionListener action = component.getActionForKeyStroke(keyStroke);
        if (action instanceof DelegateAction) {
            Action actualAction = ((DelegateAction) action).getAction();
            if (actualAction != null) {
                component.registerKeyboardAction(actualAction, keyStroke, condition);
            }
            else {
                component.unregisterKeyboardAction(keyStroke);
            }
        }
    }

    public static void restoreAction(JComponent component, int condition, KeyStroke keyStroke, Class<?> actionClass) {
        ActionListener action = component.getActionForKeyStroke(keyStroke);
        ActionListener parent = action;
        ActionListener top = action;
        while (action instanceof DelegateAction) {
            if (actionClass.isAssignableFrom(action.getClass())) {
                if (top == action) {
                    Action a = ((DelegateAction) action).getAction();
                    if (a == null) {
                        component.unregisterKeyboardAction(keyStroke);
                    }
                    else {
                        component.registerKeyboardAction(a, keyStroke, condition);
                    }
                }
                else {
                    ((DelegateAction) parent).setAction(((DelegateAction) action).getAction());
                }
                break;
            }
            parent = action;
            action = ((DelegateAction) action).getAction();
        }
    }

    public static void restoreAction(JComponent component, int condition, KeyStroke keyStroke, Action actionToBeRemoved) {
        ActionListener action = component.getActionForKeyStroke(keyStroke);
        ActionListener parent = action;
        ActionListener top = action;
        while (action instanceof DelegateAction) {
            if (actionToBeRemoved == action) {
                if (top == action) {
                    component.registerKeyboardAction(((DelegateAction) action).getAction(), keyStroke, condition);
                }
                else {
                    ((DelegateAction) parent).setAction(((DelegateAction) action).getAction());
                }
                break;
            }
            parent = action;
            action = ((DelegateAction) action).getAction();
        }
    }
}