KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > bluej > editor > moe > FunctionDialog


1 // Copyright (c) 2000, 2005 BlueJ Group, Deakin University
2
//
3
// This software is made available under the terms of the "MIT License"
4
// A copy of this license is included with this source distribution
5
// in "license.txt" and is also available at:
6
// http://www.opensource.org/licenses/mit-license.html
7
// Any queries should be directed to Michael Kolling mik@bluej.org
8

9 package bluej.editor.moe;
10
11 import javax.swing.FocusManager JavaDoc;
12 import java.awt.*;
13 import java.awt.event.*;
14 import javax.swing.*; // all the GUI components
15
//import javax.swing.KeyStroke;
16
import javax.swing.event.ListSelectionListener JavaDoc;
17 import javax.swing.event.ListSelectionEvent JavaDoc;
18
19 import java.util.Properties JavaDoc;
20
21 import bluej.Config;
22 import bluej.utility.Debug;
23 import bluej.utility.DialogManager;
24 import bluej.utility.EscapeDialog;
25 import bluej.utility.FixedMultiLineLabel;
26
27 /**
28 ** Dialog to display user functions. The dialog displays function names,
29 ** help text and key bindings.
30 **
31 ** @author Michael Kolling
32 **
33 **/

34
35 public final class FunctionDialog extends EscapeDialog
36
37 implements ActionListener, ListSelectionListener JavaDoc, ItemListener
38 {
39     // -------- CONSTANTS --------
40

41     static final String JavaDoc title = Config.getString("editor.functions.title");
42     static final String JavaDoc close = Config.getString("close");
43     static final String JavaDoc defaultsLabel = Config.getString("editor.functions.defaults");
44     static final String JavaDoc categoriesLabel = Config.getString("editor.functions.categories");
45     static final String JavaDoc keyLabel = Config.getString("editor.functions.keys");
46     static final String JavaDoc addKeyLabel = Config.getString("editor.functions.addkey");
47     static final String JavaDoc delKeyLabel = Config.getString("editor.functions.delkey");
48
49     // -------- INSTANCE VARIABLES --------
50

51     private FocusManager JavaDoc focusMgr;
52     private JButton defaultsButton;
53     private JButton closeButton;
54     private JButton addKeyButton;
55     private JButton delKeyButton;
56     private JComboBox categoryMenu;
57     private JList functionList;
58     private JList keyList;
59     private FixedMultiLineLabel helpLabel;
60
61     private MoeActions actions; // The Moe action manager
62
private Action currentAction; // the action currently selected
63
private KeyStroke[] currentKeys; // key strokes currently displayed
64

65     private Action[] functions; // all user functions
66
private int[] categoryIndex; // an array of indexes into "functions"
67
private int firstDisplayedFunc; // index of first function in list
68
private Properties JavaDoc help;
69
70     // ------------- METHODS --------------
71

72     public FunctionDialog(JFrame parent, Action[] actiontable,
73                           String JavaDoc[] categories, int[] categoryIndex)
74     {
75         super(parent, title, true);
76         focusMgr = FocusManager.getCurrentManager();
77         actions = MoeActions.getActions(null);
78         currentAction = null;
79         currentKeys = null;
80         functions = actiontable;
81         this.categoryIndex = categoryIndex;
82         makeDialog(categories);
83         openHelpFile();
84     }
85
86     /**
87      * Handle click on Close button.
88      */

89     private void handleClose()
90     {
91         removeKeyListener();
92         if(!actions.save())
93             DialogManager.showError(this, "cannot-save-keys");
94         setVisible(false);
95     }
96
97     /**
98      * Handle click on Defaults button.
99      */

100     private void handleDefaults()
101     {
102         int answer = DialogManager.askQuestion(this, "default-keys");
103         if(answer == 0) {
104             actions.setDefaultKeyBindings();
105             handleFuncListSelect();
106         }
107     }
108
109     /**
110      * Handle click in functions list.
111      */

112     private void handleFuncListSelect()
113     {
114         int index = functionList.getSelectedIndex();
115         if(index == -1)
116             return; // deselection event - ignore
117

118         // find selected action
119

120         currentAction = functions[firstDisplayedFunc + index];
121
122         // display keys and help text
123

124         updateKeyList(currentAction);
125         String JavaDoc helpText =
126             getHelpText((String JavaDoc)currentAction.getValue(Action.NAME));
127         helpLabel.setText(helpText);
128     }
129
130     /**
131      * Handle click in key bindings list.
132      */

133     private void handleKeyListSelect()
134     {
135         delKeyButton.setEnabled(true);
136     }
137
138     /**
139      * Handle click on Add Key button.
140      */

141     private void handleAddKey()
142     {
143         helpLabel.setText(getHelpText("press-key"));
144         addKeyListener();
145     }
146
147     /**
148      * Handle click on Delete Key button.
149      */

150     private void handleDelKey()
151     {
152         if(currentKeys == null)
153             return; // something went wrong here...
154

155         int index = keyList.getSelectedIndex();
156         if(index == -1)
157             return; // deselection event - ignore
158

159         actions.removeKeyStrokeBinding(currentKeys[index]);
160         updateKeyList(currentAction);
161     }
162
163     /**
164      * Display key bindings in the key list
165      */

166     private void updateKeyList(Action action)
167     {
168         currentKeys = actions.getKeyStrokesForAction(action);
169         if(currentKeys == null)
170             clearKeyList();
171         else {
172             String JavaDoc[] keyStrings = getKeyStrings(currentKeys);
173             keyList.setListData(keyStrings);
174             delKeyButton.setEnabled(false);
175         }
176         addKeyButton.setEnabled(true);
177     }
178
179     /**
180      * Translate KeyStrokes into String representation.
181      */

182     private String JavaDoc[] getKeyStrings(KeyStroke[] keys)
183     {
184         String JavaDoc[] keyStrings = new String JavaDoc[keys.length];
185         for(int i = 0; i < keys.length; i++) {
186             int modifiers = keys[i].getModifiers();
187             keyStrings[i] = KeyEvent.getKeyModifiersText(modifiers);
188             if(keyStrings[i].length() > 0)
189                 keyStrings[i] += "+";
190             keyStrings[i] += KeyEvent.getKeyText(keys[i].getKeyCode());
191         }
192         return keyStrings;
193     }
194
195     private void clearKeyList()
196     {
197         keyList.setListData(new String JavaDoc[0]);
198     }
199
200     private void clearHelpText()
201     {
202         helpLabel.setText(null);
203     }
204
205     private void openHelpFile()
206     {
207         help = Config.getMoeHelp();
208     }
209
210     private String JavaDoc getHelpText(String JavaDoc function)
211     {
212         if(help == null)
213             return null;
214         return help.getProperty(function);
215     }
216
217     private void addKeyListener()
218     {
219         FocusManager.setCurrentManager(new KeyCatcher());
220     }
221
222     private void removeKeyListener()
223     {
224         FocusManager.setCurrentManager(focusMgr);
225     }
226
227     public boolean isFocusTraversable()
228     {
229         return true;
230     }
231
232     // ======== EVENT HANDLING INTERFACES =========
233

234     // ----- ActionListener interface -----
235

236     /**
237      * A button was pressed. Find out which one and do the appropriate
238      * thing.
239      */

240     public void actionPerformed(ActionEvent event)
241     {
242         Object JavaDoc src = event.getSource();
243
244         if(src == closeButton)
245             handleClose();
246         else if(src == defaultsButton)
247             handleDefaults();
248         else if(src == addKeyButton)
249             handleAddKey();
250         else if(src == delKeyButton)
251             handleDelKey();
252     }
253
254     // ----- ItemListener interface -----
255

256     /**
257      * The selected item in the category menu has changed.
258      */

259     public void itemStateChanged(ItemEvent evt)
260     {
261         int selected = categoryMenu.getSelectedIndex();
262
263         firstDisplayedFunc = categoryIndex[selected];
264         int lastFunc = categoryIndex[selected + 1];
265
266         String JavaDoc[] names = new String JavaDoc[lastFunc - firstDisplayedFunc];
267
268         for(int i = firstDisplayedFunc; i < lastFunc; i++) {
269             names[i-firstDisplayedFunc] =
270                 (String JavaDoc)functions[i].getValue(Action.NAME);
271         }
272         functionList.setListData(names);
273         clearKeyList();
274         clearHelpText();
275         addKeyButton.setEnabled(false);
276         delKeyButton.setEnabled(false);
277         currentAction = null;
278         currentKeys = null;
279     }
280
281     // ----- ListSelectionListener interface -----
282

283     /**
284      * The selected item in a list has changed.
285      */

286     public void valueChanged(ListSelectionEvent JavaDoc event)
287     {
288         if(event.getValueIsAdjusting()) // ignore mouse down, dragging, etc.
289
return;
290
291         Object JavaDoc src = event.getSource();
292
293         if(src == functionList)
294             handleFuncListSelect();
295         else if(src == keyList)
296             handleKeyListSelect();
297     }
298
299     // ----- end of ListSelectionListener interface -----
300

301     private void makeDialog(String JavaDoc[] categories)
302     {
303         JPanel mainPanel = (JPanel)getContentPane(); // has BorderLayout
304
mainPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
305
306         // create help text area at bottom
307

308         JPanel helpPanel = new JPanel(new GridLayout());
309         helpPanel.setBorder(BorderFactory.createCompoundBorder(
310                                BorderFactory.createEmptyBorder(10,0,0,0),
311                                BorderFactory.createLineBorder(Color.black)));
312         helpLabel = new FixedMultiLineLabel(4);
313         helpLabel.setBackground(MoeEditor.infoColor);
314         helpPanel.add(helpLabel);
315         mainPanel.add(helpPanel, BorderLayout.SOUTH);
316
317         // create control area on right (key bindings and buttons)
318

319         JPanel controlPanel = new JPanel(new BorderLayout());
320
321         // create area for main buttons (close, defaults)
322

323         JPanel buttonPanel = new JPanel();
324         buttonPanel.setLayout(new GridLayout(0,1,5,5));
325
326         closeButton = new JButton(close);
327         closeButton.addActionListener(this);
328         buttonPanel.add(closeButton);
329
330         defaultsButton = new JButton(defaultsLabel);
331         defaultsButton.addActionListener(this);
332         buttonPanel.add(defaultsButton);
333
334         JPanel buttonFramePanel = new JPanel();
335         buttonFramePanel.setLayout(new BorderLayout(0,0));
336         //buttonFramePanel.setBorder(BorderFactory.createEmptyBorder(0,10,0,0));
337
buttonFramePanel.add(buttonPanel, BorderLayout.NORTH);
338
339         controlPanel.add(buttonFramePanel, BorderLayout.EAST);
340
341         // create area for key bindings
342

343         JPanel keyPanel = new JPanel();
344         keyPanel.setLayout(new BorderLayout());
345         keyPanel.setBorder(BorderFactory.createTitledBorder(
346                                                             BorderFactory.createEtchedBorder(),
347                                                             keyLabel));
348
349         keyList = new JList();
350         keyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
351         keyList.setPrototypeCellValue("shift-ctrl-delete");
352         keyList.addListSelectionListener(this);
353         keyList.setVisibleRowCount(4);
354         JScrollPane scrollPane;
355         scrollPane = new JScrollPane(keyList);
356         keyPanel.add(scrollPane, BorderLayout.CENTER);
357
358         JPanel keyButtonPanel = new JPanel();
359         addKeyButton = new JButton(addKeyLabel);
360         addKeyButton.addActionListener(this);
361         addKeyButton.setMargin(new Insets(2,2,2,2));
362         keyButtonPanel.add(addKeyButton);
363
364         delKeyButton = new JButton(delKeyLabel);
365         delKeyButton.addActionListener(this);
366         delKeyButton.setMargin(new Insets(2,2,2,2));
367         keyButtonPanel.add(delKeyButton);
368
369         keyPanel.add(keyButtonPanel, BorderLayout.SOUTH);
370
371         controlPanel.add(keyPanel, BorderLayout.SOUTH);
372
373         mainPanel.add(controlPanel, BorderLayout.EAST);
374
375         // create function list area
376

377         JPanel funcPanel = new JPanel(new BorderLayout());
378         funcPanel.setBorder(BorderFactory.createEmptyBorder(0,0,0,10));
379
380         functionList = new JList();
381         functionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
382         functionList.addListSelectionListener(this);
383         functionList.setVisibleRowCount(12);
384         scrollPane = new JScrollPane(functionList);
385
386         funcPanel.add(scrollPane, BorderLayout.CENTER);
387
388         JPanel categoryPanel = new JPanel();
389
390         JLabel label = new JLabel(categoriesLabel);
391         categoryPanel.add(label);
392         categoryMenu = new JComboBox();
393         categoryMenu.addItemListener(this);
394         for(int i=0; i<categories.length; i++)
395             categoryMenu.addItem(categories[i]);
396         categoryPanel.add(categoryMenu);
397
398         funcPanel.add(categoryPanel, BorderLayout.NORTH);
399
400         mainPanel.add(funcPanel, BorderLayout.CENTER);
401         getRootPane().setDefaultButton(closeButton);
402
403         addWindowListener(new WindowAdapter() {
404             public void windowClosing(WindowEvent E) {
405                 setVisible(false);
406             }
407         });
408
409         pack();
410         DialogManager.centreDialog(this);
411     }
412
413
414     class KeyCatcher extends FocusManager JavaDoc {
415
416         public void processKeyEvent(Component focusedComponent,
417                                     KeyEvent e)
418         {
419             if(e.getID() != KeyEvent.KEY_PRESSED)
420                 return;
421
422             int keyCode = e.getKeyCode();
423
424             if(keyCode == KeyEvent.VK_CAPS_LOCK || // the keys we want to ignore...
425
keyCode == KeyEvent.VK_SHIFT ||
426                keyCode == KeyEvent.VK_CONTROL ||
427                keyCode == KeyEvent.VK_META ||
428                keyCode == KeyEvent.VK_ALT ||
429                keyCode == KeyEvent.VK_ALT_GRAPH ||
430                keyCode == KeyEvent.VK_COMPOSE ||
431                keyCode == KeyEvent.VK_NUM_LOCK ||
432                keyCode == KeyEvent.VK_SCROLL_LOCK ||
433                keyCode == KeyEvent.VK_UNDEFINED
434                )
435                 return;
436
437             if(currentAction == null)
438                 Debug.message("FunctionDialog: currentAction is null...");
439             else {
440                 KeyStroke key = KeyStroke.getKeyStrokeForEvent(e);
441                 if(isPrintable(key, e))
442                     helpLabel.setText(getHelpText("cannot-redefine"));
443                 else {
444                     actions.addActionForKeyStroke(key, currentAction);
445                     handleFuncListSelect();
446                 }
447             }
448             e.consume();
449             removeKeyListener();
450         }
451
452         private boolean isPrintable(KeyStroke key, KeyEvent e)
453         {
454             // all control and alt keys are non-printable
455
int modifiers = key.getModifiers();
456             if(modifiers != 0 && modifiers != Event.SHIFT_MASK)
457                 return false;
458
459             // action keys are non-printable
460
if(e.isActionKey())
461                 return false;
462
463             // some action keys that the above function not recognises
464
int keyCode = e.getKeyCode();
465             if(keyCode == KeyEvent.VK_BACK_SPACE ||
466                keyCode == KeyEvent.VK_DELETE ||
467                keyCode == KeyEvent.VK_ENTER ||
468                keyCode == KeyEvent.VK_TAB ||
469                keyCode == KeyEvent.VK_ESCAPE)
470                 return false;
471
472             // otherwise it's printable
473
return true;
474         }
475
476         public void focusNextComponent(Component c) {}
477         public void focusPreviousComponent(Component c) {}
478     }
479
480 } // end class FunctionDialog
481
Popular Tags