View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
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 the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  package org.xnap.gui.component;
20  
21  import java.awt.Event;
22  import java.awt.FlowLayout;
23  import java.awt.GridBagLayout;
24  import java.awt.event.ActionEvent;
25  import java.awt.event.ActionListener;
26  import java.awt.event.FocusAdapter;
27  import java.awt.event.FocusEvent;
28  import java.awt.event.KeyAdapter;
29  import java.awt.event.KeyEvent;
30  
31  import javax.swing.AbstractAction;
32  import javax.swing.Action;
33  import javax.swing.JCheckBox;
34  import javax.swing.JLabel;
35  import javax.swing.JPanel;
36  import javax.swing.JToggleButton;
37  import javax.swing.KeyStroke;
38  import javax.swing.event.ChangeEvent;
39  import javax.swing.event.ChangeListener;
40  
41  import org.xnap.XNap;
42  import org.xnap.gui.util.GridBagHelper;
43  
44  public class KeyStrokePanel extends JPanel 
45  	implements ChangeListener, ActionListener {
46      
47      //--- Data field(s) ---
48  
49  	private JCheckBox ctrlCheckBox;
50      private JCheckBox shiftCheckBox;
51  	private JCheckBox metaCheckBox;
52  	private JCheckBox altCheckBox;
53  	private JToggleButton charButton;
54  	private KeyStroke defaultKeyStroke;
55  	int keyCode;
56  	private CharButtonListener keyListener = new CharButtonListener();
57      protected transient ChangeEvent changeEvent;
58      
59      //--- Constructor(s) ---
60  
61      public KeyStrokePanel()
62      {
63  		setLayout(new GridBagLayout());
64  
65  		ctrlCheckBox 
66  			= new JCheckBox(KeyEvent.getKeyModifiersText(Event.CTRL_MASK));
67  		ctrlCheckBox.addActionListener(this);
68  		GridBagHelper.addComponent(this, ctrlCheckBox);
69  
70  		altCheckBox 
71  			= new JCheckBox(KeyEvent.getKeyModifiersText(Event.ALT_MASK));
72  		altCheckBox.addActionListener(this);
73  		GridBagHelper.addComponent(this, altCheckBox);
74  
75  		metaCheckBox
76  			= new JCheckBox(KeyEvent.getKeyModifiersText(Event.META_MASK));
77  		metaCheckBox.addActionListener(this);
78  		GridBagHelper.addComponent(this, metaCheckBox);
79  		
80  		shiftCheckBox
81  			= new JCheckBox(KeyEvent.getKeyModifiersText(Event.SHIFT_MASK));
82  		shiftCheckBox.addActionListener(this);
83  		GridBagHelper.addComponent(this, shiftCheckBox);
84  
85  		charButton = new JToggleButton(" ");
86  		charButton.addChangeListener(this);
87  		charButton.addFocusListener(new UntoggleListener());
88  		GridBagHelper.addComponent(this, charButton);
89  		
90  		// XXX: workaround to horizontally fill space
91  		GridBagHelper.add(this, new JLabel());
92  
93  		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
94  		buttonPanel.add(new XNapButton(new DefaultAction()));
95  		buttonPanel.add(new XNapButton(new NoneAction()));
96  		GridBagHelper.addPanel(this, buttonPanel);
97      }
98  
99  	/***
100 	 *  @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
101 	 */
102 	public void actionPerformed(ActionEvent e)
103 	{
104 		fireChangeEvent();
105 	}
106 
107     /***
108      */
109     public void addChangeListener(ChangeListener l) 
110     {
111         listenerList.add(ChangeListener.class, l);
112     }
113     
114     /***
115      * 
116      */
117     public void removeChangeListener(ChangeListener l) 
118     {
119         listenerList.remove(ChangeListener.class, l);
120     }
121 
122     protected void fireChangeEvent() {
123         Object[] listeners = listenerList.getListenerList();
124 
125         for (int i = listeners.length - 2; i >= 0; i -= 2) {
126             if (listeners[i] == ChangeListener.class) {
127 				// Lazily create the event:
128                 if (changeEvent == null) {
129                     changeEvent = new ChangeEvent(this);
130                 }
131                 ((ChangeListener)listeners[i + 1]).stateChanged(changeEvent);
132             }          
133         }
134     }   
135 
136     public KeyStroke getKeyStroke()
137 	{
138     	if (keyCode == KeyEvent.VK_UNDEFINED) {
139 			return null;
140     	}
141     	else {
142     		int m = 0;
143     		m |= (ctrlCheckBox.isSelected()) ? Event.CTRL_MASK : 0;
144     		m |= (altCheckBox.isSelected()) ? Event.ALT_MASK : 0;
145     		m |= (metaCheckBox.isSelected()) ? Event.META_MASK : 0;
146     		m |= (shiftCheckBox.isSelected()) ? Event.SHIFT_MASK : 0;
147     		return KeyStroke.getKeyStroke(keyCode, m);
148     	}
149     }
150     
151 	public void setKeyStroke(KeyStroke keyStroke)
152 	{
153 		if (keyStroke != null) {
154 			int m = keyStroke.getModifiers();
155 			ctrlCheckBox.setSelected((m & Event.CTRL_MASK) != 0);
156 			altCheckBox.setSelected((m & Event.ALT_MASK) != 0);
157 			metaCheckBox.setSelected((m & Event.META_MASK) != 0);
158 			shiftCheckBox.setSelected((m & Event.SHIFT_MASK) != 0);
159 			keyCode = keyStroke.getKeyCode();
160 			charButton.setText(KeyEvent.getKeyText(keyCode));
161 		}
162 		else {
163 			ctrlCheckBox.setSelected(false);
164 			altCheckBox.setSelected(false);
165 			metaCheckBox.setSelected(false);
166 			shiftCheckBox.setSelected(false);
167 			charButton.setText(" ");
168 			keyCode = KeyEvent.VK_UNDEFINED;
169 		}
170 	}
171 	
172 	public void setDefaultKeyStroke(KeyStroke defaultKeyStroke)
173 	{
174 		this.defaultKeyStroke = defaultKeyStroke;
175 	}
176 
177 	public void stateChanged(ChangeEvent e) 
178 	{
179 		if (charButton.isSelected()) {
180 			// record the key that is pressed next
181 			charButton.addKeyListener(keyListener);
182 		}
183 		else {
184 			charButton.removeKeyListener(keyListener);
185 			fireChangeEvent();
186 		}
187 	}
188 
189 	private class CharButtonListener extends KeyAdapter {
190 
191 		public void keyPressed(KeyEvent e) 
192 		{
193 			keyCode = e.getKeyCode();
194 			
195 			charButton.setSelected(false);
196 			charButton.setText(KeyEvent.getKeyText(keyCode));
197 			//  charButton.setText(KeyStroke.getKeyStrokeForEvent(e).toString());
198 		}
199 
200 	}
201 
202 	private class UntoggleListener extends FocusAdapter {
203 
204 		public void focusLost(FocusEvent e)
205 		{
206 			charButton.setSelected(false);
207 		}
208 
209 	}
210 
211     /***
212      * Reperforms a search.
213      */
214     private class DefaultAction extends AbstractAction {
215 
216         public DefaultAction() 
217 		{
218             putValue(Action.NAME, XNap.tr("Default"));
219             putValue(Action.SHORT_DESCRIPTION, XNap.tr("Reset to default"));
220         }
221 
222         public void actionPerformed(ActionEvent event) 
223 		{
224 			setKeyStroke(defaultKeyStroke);
225 			fireChangeEvent();
226         }
227     }
228 
229     /***
230      * Reperforms a search.
231      */
232     private class NoneAction extends AbstractAction {
233 
234         public NoneAction() 
235 		{
236             putValue(Action.NAME, XNap.tr("None"));
237             putValue(Action.SHORT_DESCRIPTION,
238 					 XNap.tr("Assigns no keystroke"));
239         }
240 
241         public void actionPerformed(ActionEvent event) 
242 		{
243         	setKeyStroke(null);
244 			fireChangeEvent();
245 		}
246         
247     }
248 
249 	/***
250 	 * @param stroke
251 	 * @return
252 	 */
253 	public static String toString(KeyStroke stroke)
254 	{
255 		StringBuffer sb = new StringBuffer();
256 
257 		int m = stroke.getModifiers();
258 		if ((m & Event.CTRL_MASK) != 0) {
259 			sb.append(KeyEvent.getKeyModifiersText(Event.CTRL_MASK));
260 			sb.append("+");
261 		}
262 		if ((m & Event.ALT_MASK) != 0) {
263 			sb.append(KeyEvent.getKeyModifiersText(Event.ALT_MASK));
264 			sb.append("+");
265 		}
266 		if ((m & Event.META_MASK) != 0) {
267 			sb.append(KeyEvent.getKeyModifiersText(Event.META_MASK));
268 			sb.append("+");
269 		}
270 		if ((m & Event.SHIFT_MASK) != 0) {
271 			sb.append(KeyEvent.getKeyModifiersText(Event.SHIFT_MASK));
272 			sb.append("+");
273 		}
274 		sb.append(KeyEvent.getKeyText(stroke.getKeyCode()));
275 		return sb.toString();
276 	}
277 
278 }