Source code: novaworx/gui/ProgramAction.java
1 /*
2 Novaworx Development Environment
3 Copyright (C) 2000-2003 Mark Soderquist
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to:
17
18 Free Software Foundation, Inc.
19 59 Temple Place, Suite 330
20 Boston, MA 02111-1307 USA
21 */
22
23 package novaworx.gui;
24
25 import java.awt.event.*;
26 import java.util.*;
27 import javax.swing.*;
28 import novaworx.swing.*;
29
30 /**
31 This class is used to handle the visual aspects of actions. Since components may
32 treat an action specifically this class allows a component specific action to be
33 set as the acting action.
34
35 The idea being that when a component gains focus it will
36 register the actions that it handles with the appropriate instance of this class.
37 When the component looses focus then the component will unregister the actions that
38 it handles. This works fine in theory but is a little problematic in reality.
39 The most noticable issue is when a menu item gains the focus it will cause the
40 component that was focused to loose focus and therefore disable the acctions it
41 can handle by the time the user selects the menu item.
42 */
43 public class ProgramAction extends XAction {
44
45 public static final int NONE = -1;
46
47 /**
48 The command to be sent.
49 */
50 private String msCommand;
51
52 /**
53 The stack of listeners.
54 */
55 private Stack moListenerStack;
56
57 /**
58 Construct a program action.
59 */
60 public ProgramAction( String sCommand, String sName ) {
61 this( sCommand, sName, null );
62 }
63
64 /**
65 Construct a program action.
66 */
67 public ProgramAction( String sCommand, String sName, Icon cIcon ) {
68 this( sCommand, sName, cIcon, NONE );
69 }
70
71 /**
72 Construct a program action.
73 */
74 public ProgramAction( String sCommand, String sName, Icon cIcon, int nMnemonic ) {
75 this( sCommand, sName, cIcon, nMnemonic, NONE );
76 }
77
78 /**
79 Construct a program action.
80 */
81 public ProgramAction( String sCommand, String sName, Icon cIcon, int nMnemonic, int nKey ) {
82 this( sCommand, sName, cIcon, nMnemonic, nKey, NONE );
83 }
84
85 /**
86 Construct a program action.
87 */
88 public ProgramAction( String sCommand, String sName, Icon cIcon, int nMnemonic, int nKey, int nMask ) {
89 super( sName, cIcon );
90 msCommand = sCommand;
91 moListenerStack = new Stack();
92
93 setEnabled( false );
94
95 if( nMnemonic != NONE ) putValue( MNEMONIC_KEY, new Integer( nMnemonic ) );
96 if( nKey != NONE & nMask == NONE) putValue( ACCELERATOR_KEY, KeyStroke.getKeyStroke( nKey, 0 ) );
97 if( nKey != NONE & nMask != NONE) putValue( ACCELERATOR_KEY, KeyStroke.getKeyStroke( nKey, nMask ) );
98 }
99
100 /**
101 Construct a program action.
102 */
103 public ProgramAction( String sCommand, String sName, Icon cIcon, int nMnemonic, String asKeySequence ) {
104 super( sName, cIcon );
105 msCommand = sCommand;
106 moListenerStack = new Stack();
107
108 setEnabled( false );
109
110 if( nMnemonic != NONE ) putValue( MNEMONIC_KEY, new Integer( nMnemonic ) );
111 if( asKeySequence != null ) putValue( SHORTCUT_KEY_SEQUENCE, asKeySequence );
112 }
113
114 /**
115 Get the command associated with this action.
116 */
117 public String getCommand() {
118 return msCommand;
119 }
120
121 /**
122 Called by the <code>KeyEventGrabber</code>.
123
124 @return Whether the event was dispatched to any listeners.
125 */
126 public boolean performAction( ActionEvent aoEvent ) {
127 //System.out.println( "Called ProgramAction.performAction()..." );
128 if( !isEnabled() ) return false;
129
130 ActionListener oListener = null;
131 if( moListenerStack.size() > 0 ) oListener = (ActionListener)moListenerStack.peek();
132
133 if( oListener != null ) {
134 ActionEvent oNewEvent = new ActionEvent( aoEvent.getSource(), aoEvent.getID(), msCommand );
135 oListener.actionPerformed( oNewEvent );
136 return true;
137 }
138
139 return false;
140 }
141
142 /**
143 Do whatever this action is going to do.
144 */
145 public void actionPerformed( ActionEvent aoEvent ) {
146 boolean bResult = performAction( aoEvent );
147 }
148
149 /**
150 Set the enabled flag.
151 This is now save to call from any thread.
152 */
153 public void setEnabled( boolean abEnabled ) {
154 SwingUtilities.invokeLater( new SetEnabled( abEnabled ) );
155 }
156
157 /**
158 Add an <code>ActionListener</code>.
159
160 @param aoListener The ActionListener that will handle this action.
161 */
162 public void pushListener( ActionListener aoListener ) {
163 pushListener( aoListener, true );
164 }
165
166 /**
167 Add an <code>ActionListener</code>.
168
169 @param aoListener The ActionListener that will handle this action.
170 @param abEnabled Whether the action should be enabled or not.
171 */
172 public void pushListener( ActionListener aoListener, boolean abEnabled ) {
173 if( aoListener == null ) throw new IllegalArgumentException( "Null ActionListener not allowed." );
174 if( !moListenerStack.contains( aoListener ) ) moListenerStack.push( aoListener );
175 setEnabled( aoListener != null & abEnabled );
176 }
177
178 /**
179 Get the current <code>ActionListener</code>.
180
181 @return The <code>ActionListener</code> that is handling this action.
182 */
183 public ActionListener peekListener() {
184 return (ActionListener)moListenerStack.peek();
185 }
186
187 /**
188 Remove an <code>ActionListener</code>.
189
190 @param aoListener The ActionListener to remove.
191 */
192 public ActionListener pullListener( ActionListener aoListener ) {
193 moListenerStack.remove( aoListener );
194 if( moListenerStack.isEmpty() ) setEnabled( false );
195 return aoListener;
196 }
197
198 /**
199 Remove an <code>ActionListener</code>.
200
201 @param aoListener The ActionListener to remove.
202 */
203 public ActionListener pullListener( ActionListener aoListener, boolean abEnabled ) {
204 moListenerStack.remove( aoListener );
205 if( !moListenerStack.isEmpty() ) setEnabled( abEnabled );
206 return aoListener;
207 }
208
209 /**
210 Get the current action listener.
211
212 @return The ActionListener that is handling this action.
213 */
214 public ActionListener getListener() {
215 return peekListener();
216 }
217
218 /**
219 The class to set the enabled flag from the event dispatch thread.
220 */
221 private class SetEnabled implements Runnable {
222
223 /**
224 The enabled state.
225 */
226 private boolean mbEnabled;
227
228 /**
229 Create the <code>SetEnabled</code> class.
230 */
231 public SetEnabled( boolean abEnabled ) {
232 mbEnabled = abEnabled;
233 }
234
235 /**
236 Called by the thread.
237 */
238 public void run() {
239 ProgramAction.super.setEnabled( mbEnabled );
240 }
241
242 }
243
244 }