001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.ui.config;
038:
039: import edu.rice.cs.drjava.ui.MainFrame;
040: import javax.swing.*;
041: import edu.rice.cs.drjava.config.*;
042: import edu.rice.cs.drjava.*;
043: import java.awt.*;
044: import java.awt.event.*;
045: import java.util.Hashtable;
046:
047: /**
048: * Graphical form of a KeyStrokeOption.
049: * @version $Id: KeyStrokeOptionComponent.java 4255 2007-08-28 19:17:37Z mgricken $
050: */
051: public class KeyStrokeOptionComponent extends
052: OptionComponent<KeyStroke> implements Comparable {
053: private static final int DIALOG_HEIGHT = 185;
054: /**
055: * TODO: should this be synchronized?
056: */
057: public static final Hashtable<KeyStroke, KeyStrokeOptionComponent> _keyToKSOC = new Hashtable<KeyStroke, KeyStrokeOptionComponent>();
058: private JButton _button;
059: private JTextField _keyField;
060: private JPanel _panel;
061: private static GetKeyDialog _getKeyDialog = null;
062:
063: private KeyStroke _key;
064:
065: public KeyStrokeOptionComponent(KeyStrokeOption opt, String text,
066: final Frame parent) {
067: super (opt, text, parent);
068:
069: _key = DrJava.getConfig().getSetting(opt);
070:
071: _button = new JButton();
072: _button.addActionListener(new ActionListener() {
073: public void actionPerformed(ActionEvent ae) {
074:
075: if (_getKeyDialog == null) {
076: _getKeyDialog = new GetKeyDialog(parent,
077: "Specify Shortcut", true);
078: }
079:
080: String oldText = _keyField.getText();
081: _getKeyDialog.promptKey(KeyStrokeOptionComponent.this );
082: if (!_keyField.getText().equals(oldText)) {
083: notifyChangeListeners();
084: }
085: }
086: });
087: _button.setText("...");
088: _button.setMaximumSize(new Dimension(10, 10));
089: _button.setMinimumSize(new Dimension(10, 10));
090:
091: _keyField = new JTextField();
092: _keyField.setEditable(false);
093: _keyField.setBackground(Color.white);
094: _keyField.setHorizontalAlignment(JTextField.CENTER);
095: _keyField.setText(_option.format(_key));
096: _panel = new JPanel(new BorderLayout());
097: _panel.add(_keyField, BorderLayout.CENTER);
098: _panel.add(_button, BorderLayout.EAST);
099:
100: GridLayout gl = new GridLayout(1, 0);
101: gl.setHgap(15);
102: _keyToKSOC.put(_key, this );
103: }
104:
105: /**
106: * Constructor that allows for a tooltip description.
107: */
108: public KeyStrokeOptionComponent(KeyStrokeOption opt, String text,
109: Frame parent, String description) {
110: this (opt, text, parent);
111: setDescription(description);
112: }
113:
114: /**
115: * Sets the tooltip description text for this option.
116: * @param description the tooltip text
117: */
118: public void setDescription(String description) {
119: _panel.setToolTipText(description);
120: _button.setToolTipText(description);
121: _keyField.setToolTipText(description);
122: _label.setToolTipText(description);
123: }
124:
125: /**
126: * Returns a custom string representation of this option component.
127: */
128: public String toString() {
129: return "<KSOC>label:" + getLabelText() + "ks: "
130: + getKeyStroke() + "jb: " + _button.getText()
131: + "</KSOC>\n";
132: }
133:
134: /**
135: * Updates the config object with the new setting.
136: * @return true if the new value is set successfully
137: */
138: public boolean updateConfig() {
139: if (!_key.equals(getConfigKeyStroke())) {
140: DrJava.getConfig().setSetting(_option, _key);
141: setValue(_key);
142: }
143: return true;
144: }
145:
146: /**
147: * Displays the given value.
148: */
149: public void setValue(KeyStroke value) {
150: _key = value;
151: _keyField.setText(_option.format(value));
152: }
153:
154: /**
155: * Compares two KeyStrokeOptionComponents based on the text of their labels.
156: * @return Comparison based on labels, or 1 if o is not a KeyStrokeOptionComponent
157: */
158: public int compareTo(Object o) {
159: if (o instanceof KeyStrokeOptionComponent) {
160: KeyStrokeOptionComponent other = (KeyStrokeOptionComponent) o;
161: return this .getLabelText().compareTo(other.getLabelText());
162: } else
163: return 1;
164: }
165:
166: /**
167: * Returns the currently selected KeyStroke.
168: */
169: public KeyStroke getKeyStroke() {
170: return _key;
171: }
172:
173: /**
174: * Returns the KeyStroke current set in the Config settings.
175: */
176: public KeyStroke getConfigKeyStroke() {
177: return DrJava.getConfig().getSetting(_option);
178: }
179:
180: /**
181: * Return's this OptionComponent's configurable component.
182: */
183: public JComponent getComponent() {
184: return _panel;
185: }
186:
187: /**
188: * A dialog that allows the user to type in a keystroke to be bound
189: * to the action that was clicked. If the user types a keystroke that
190: * is bound to another action, the dialog will display that information.
191: */
192: private class GetKeyDialog extends JDialog {
193: private InputField _inputField;
194: private JButton _clearButton;
195: private JButton _cancelButton;
196: private JButton _okButton;
197: private JLabel _instructionLabel;
198: private JLabel _currentLabel;
199: private JLabel _actionLabel;
200: private JPanel _inputAndClearPanel;
201: // private JPanel _labelsPanel;
202: private JPanel _cancelAndOKPanel;
203: private KeyStroke _currentKeyStroke;
204: private KeyStrokeOptionComponent _ksoc;
205:
206: // private Frame frame;
207:
208: public GetKeyDialog(Frame f, String title, boolean modal) {
209: super (f, title, modal);
210: // frame = f;
211:
212: _inputField = new InputField();
213: _clearButton = new JButton("Clear");
214: _clearButton.addActionListener(new ActionListener() {
215: public void actionPerformed(ActionEvent ae) {
216: _inputField.setText("");
217: _actionLabel.setText("<none>");
218: _currentKeyStroke = KeyStrokeOption.NULL_KEYSTROKE;
219: _inputField.requestFocusInWindow();
220: }
221: });
222: _cancelButton = new JButton("Cancel");
223: _cancelButton.addActionListener(new ActionListener() {
224: public void actionPerformed(ActionEvent ae) {
225: _inputField.requestFocusInWindow();
226: GetKeyDialog.this .dispose();
227: }
228: });
229: _okButton = new JButton("OK");
230: _okButton.addActionListener(new ActionListener() {
231: public void actionPerformed(ActionEvent ae) {
232: if (!_ksoc.getKeyStroke().equals(_currentKeyStroke)) {
233: _keyToKSOC.remove(_ksoc.getKeyStroke());
234:
235: KeyStrokeOptionComponent conflict = _keyToKSOC
236: .get(_currentKeyStroke);
237:
238: if (conflict != null) {
239: _keyToKSOC.remove(_currentKeyStroke);
240: conflict
241: .setValue(KeyStrokeOption.NULL_KEYSTROKE);
242: }
243: _keyToKSOC.put(_currentKeyStroke, _ksoc);
244: _ksoc.setValue(_currentKeyStroke);
245: }
246: _inputField.requestFocusInWindow();
247: GetKeyDialog.this .dispose();
248: }
249: });
250: _instructionLabel = new JLabel(
251: "Type in the keystroke you want to use "
252: + "and click \"OK\"");
253: _currentLabel = new JLabel(
254: "Current action bound to the keystroke:");
255: _actionLabel = new JLabel("<none>");
256:
257: _inputAndClearPanel = new JPanel(new BorderLayout());
258: _inputAndClearPanel.add(_inputField, BorderLayout.CENTER);
259: _inputAndClearPanel.add(_clearButton, BorderLayout.EAST);
260:
261: //_labelsPanel = new JPanel();
262: //_labelsPanel.add(_currentLabel);
263: //_labelsPanel.add(_actionLabel);
264:
265: _cancelAndOKPanel = new JPanel(new GridLayout(1, 0));
266: _cancelAndOKPanel.add(_okButton);
267: _cancelAndOKPanel.add(_cancelButton);
268:
269: JPanel panel = (JPanel) this .getContentPane();
270:
271: panel.setLayout(new GridLayout(0, 1));
272: panel.add(_instructionLabel);
273: panel.add(_inputAndClearPanel);
274: //panel.add(_labelsPanel);
275: panel.add(_currentLabel);
276: panel.add(_actionLabel);
277: panel.add(_cancelAndOKPanel);
278: this .setSize((int) _instructionLabel.getPreferredSize()
279: .getWidth() + 30, DIALOG_HEIGHT);
280: //centerOnScreen();
281: this .pack();
282: }
283:
284: public void promptKey(KeyStrokeOptionComponent k) {
285: _ksoc = k;
286: _instructionLabel
287: .setText("Type in the keystroke you want to use for \""
288: + k.getLabelText() + "\" and click \"OK\"");
289: _currentKeyStroke = k.getKeyStroke();
290: _actionLabel.setText(k.getLabelText());
291: _inputField.setText(_option.format(_currentKeyStroke));
292: //this.setLocation(frame.getLocation());
293: this .setSize((int) _instructionLabel.getPreferredSize()
294: .getWidth() + 30, DIALOG_HEIGHT);
295: MainFrame.setPopupLoc(this , getOwner());
296: this .setVisible(true);
297: }
298:
299: /**
300: * A textfield that takes in one keystroke at a time and displays
301: * its formatted String version. It updates the label that displays
302: * what action the currently displayed keystroke is bound to.
303: */
304: private class InputField extends JTextField {
305: /*public boolean getFocusTraversalKeysEnabled() {
306: return false;
307: }*/
308:
309: public void processKeyEvent(KeyEvent e) {
310: KeyStroke ks = KeyStroke.getKeyStrokeForEvent(e);
311: if (e.getID() == KeyEvent.KEY_PRESSED) {
312: this .setText(_option.format(ks));
313: KeyStrokeOptionComponent configKs = _keyToKSOC
314: .get(ks);
315: if (configKs == null)
316: _actionLabel.setText("<none>");
317: else {
318: String name = configKs.getLabelText();//KeyBindingManager.Singleton.getName(configKs.getConfigKeyStroke());
319: _actionLabel.setText(name);
320: }
321: _currentKeyStroke = ks;
322: }
323: }
324: }
325: }
326:
327: }
|