001: /*
002: * ShortcutsOptionPane.java - Shortcuts options panel
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 1999, 2000, 2001 Slava Pestov
007: * Copyright (C) 2001 Dirk Moebius
008: *
009: * This program is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; either version 2
012: * of the License, or any later version.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with this program; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
022: */
023:
024: package org.gjt.sp.jedit.options;
025:
026: import org.gjt.sp.jedit.*;
027: import org.gjt.sp.jedit.gui.FilteredTableModel;
028: import org.gjt.sp.jedit.gui.GrabKeyDialog;
029: import org.gjt.sp.jedit.gui.GrabKeyDialog.KeyBinding;
030: import org.gjt.sp.util.Log;
031: import org.gjt.sp.util.StandardUtilities;
032:
033: import javax.swing.*;
034: import javax.swing.event.DocumentEvent;
035: import javax.swing.event.DocumentListener;
036: import javax.swing.table.AbstractTableModel;
037: import java.awt.*;
038: import java.awt.event.ActionEvent;
039: import java.awt.event.ActionListener;
040: import java.awt.event.MouseAdapter;
041: import java.awt.event.MouseEvent;
042: import java.util.Collections;
043: import java.util.Comparator;
044: import java.util.List;
045: import java.util.Vector;
046:
047: /**
048: * Key binding editor.
049: * @author Slava Pestov
050: * @version $Id: ShortcutsOptionPane.java 10737 2007-09-24 19:19:15Z kpouer $
051: */
052: public class ShortcutsOptionPane extends AbstractOptionPane {
053: public ShortcutsOptionPane() {
054: super ("shortcuts");
055: }
056:
057: // protected members
058: protected void _init() {
059: allBindings = new Vector<KeyBinding>();
060:
061: setLayout(new BorderLayout(12, 12));
062:
063: initModels();
064:
065: selectModel = new JComboBox(models);
066: selectModel.addActionListener(new ActionHandler());
067: selectModel.setToolTipText(jEdit
068: .getProperty("options.shortcuts.select.tooltip"));
069: Box north = Box.createHorizontalBox();
070: north.add(new JLabel(jEdit
071: .getProperty("options.shortcuts.select.label")));
072: north.add(Box.createHorizontalStrut(6));
073: north.add(selectModel);
074:
075: filterTF = new JTextField(40);
076: filterTF.setToolTipText(jEdit
077: .getProperty("options.shortcuts.filter.tooltip"));
078: filterTF.getDocument().addDocumentListener(
079: new DocumentListener() {
080: public void changedUpdate(DocumentEvent e) {
081: setFilter();
082: }
083:
084: public void insertUpdate(DocumentEvent e) {
085: setFilter();
086: }
087:
088: public void removeUpdate(DocumentEvent e) {
089: setFilter();
090: }
091: });
092: JButton clearButton = new JButton(jEdit
093: .getProperty("options.shortcuts.clear.label"));
094: clearButton.addActionListener(new ActionListener() {
095: public void actionPerformed(ActionEvent arg0) {
096: filterTF.setText("");
097: filterTF.requestFocus();
098: }
099: });
100:
101: JPanel filterPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
102: filterPanel.add(new JLabel(jEdit
103: .getProperty("options.shortcuts.filter.label")));
104: filterPanel.add(filterTF);
105: filterPanel.add(clearButton);
106:
107: keyTable = new JTable(filteredModel);
108: filteredModel.setTable(keyTable);
109: keyTable.getTableHeader().setReorderingAllowed(false);
110: keyTable.getTableHeader().addMouseListener(
111: new HeaderMouseHandler());
112: keyTable.addMouseListener(new TableMouseHandler());
113: Dimension d = keyTable.getPreferredSize();
114: d.height = Math.min(d.height, 200);
115: JScrollPane scroller = new JScrollPane(keyTable);
116: scroller.setPreferredSize(d);
117: JPanel tableFilterPanel = new JPanel(new BorderLayout());
118: tableFilterPanel.add(BorderLayout.NORTH, filterPanel);
119: tableFilterPanel.add(BorderLayout.CENTER, scroller);
120:
121: add(BorderLayout.NORTH, north);
122: add(BorderLayout.CENTER, tableFilterPanel);
123: try {
124: selectModel.setSelectedIndex(jEdit.getIntegerProperty(
125: "options.shortcuts.select.index", 0));
126: } catch (IllegalArgumentException eae) {
127: }
128: }
129:
130: private void setFilter() {
131: filteredModel.setFilter(filterTF.getText());
132: }
133:
134: protected void _save() {
135: if (keyTable.getCellEditor() != null)
136: keyTable.getCellEditor().stopCellEditing();
137:
138: for (ShortcutsModel model : models)
139: model.save();
140:
141: Macros.loadMacros();
142: }
143:
144: private void initModels() {
145: Vector<KeyBinding[]> allBindings = new Vector<KeyBinding[]>();
146: models = new Vector<ShortcutsModel>();
147: ActionSet[] actionSets = jEdit.getActionSets();
148: for (int i = 0; i < actionSets.length; i++) {
149: ActionSet actionSet = actionSets[i];
150: if (actionSet.getActionCount() != 0) {
151: String modelLabel = actionSet.getLabel();
152: if (modelLabel == null) {
153: Log.log(Log.ERROR, this , "Empty action set: "
154: + actionSet.getPluginJAR());
155: }
156: ShortcutsModel model = createModel(modelLabel,
157: actionSet.getActionNames());
158: models.addElement(model);
159: allBindings.addAll(model.getBindings());
160: }
161: }
162: if (models.size() > 1)
163: models.addElement(new ShortcutsModel("All", allBindings));
164: Collections
165: .sort(models, new MiscUtilities.StringICaseCompare());
166: ShortcutsModel currentModel = models.elementAt(0);
167: filteredModel = new FilteredTableModel<ShortcutsModel>(
168: currentModel) {
169: public String prepareFilter(String filter) {
170: return filter.toLowerCase();
171: }
172:
173: public boolean passFilter(int row, String filter) {
174: String name = delegated.getBindingAt(row, 0).label
175: .toLowerCase();
176: return name.contains(filter);
177: }
178: };
179: }
180:
181: private ShortcutsModel createModel(String modelLabel,
182: String[] actions) {
183: Vector<GrabKeyDialog.KeyBinding[]> bindings = new Vector<GrabKeyDialog.KeyBinding[]>(
184: actions.length);
185:
186: for (int i = 0; i < actions.length; i++) {
187: String name = actions[i];
188: EditAction ea = jEdit.getAction(name);
189: String label = ea.getLabel();
190: // Skip certain actions this way
191: if (label == null)
192: continue;
193:
194: label = GUIUtilities.prettifyMenuLabel(label);
195: addBindings(name, label, bindings);
196: }
197:
198: return new ShortcutsModel(modelLabel, bindings);
199: }
200:
201: private void addBindings(String name, String label,
202: List<GrabKeyDialog.KeyBinding[]> bindings) {
203: GrabKeyDialog.KeyBinding[] b = new GrabKeyDialog.KeyBinding[2];
204:
205: b[0] = createBinding(name, label, jEdit.getProperty(name
206: + ".shortcut"));
207: b[1] = createBinding(name, label, jEdit.getProperty(name
208: + ".shortcut2"));
209:
210: bindings.add(b);
211: }
212:
213: private GrabKeyDialog.KeyBinding createBinding(String name,
214: String label, String shortcut) {
215: if (shortcut != null && shortcut.length() == 0)
216: shortcut = null;
217:
218: GrabKeyDialog.KeyBinding binding = new GrabKeyDialog.KeyBinding(
219: name, label, shortcut, false);
220:
221: allBindings.addElement(binding);
222: return binding;
223: }
224:
225: // private members
226: private JTable keyTable;
227: private Vector<ShortcutsModel> models;
228: private FilteredTableModel filteredModel;
229: private JComboBox selectModel;
230: private Vector<GrabKeyDialog.KeyBinding> allBindings;
231: private JTextField filterTF;
232:
233: class HeaderMouseHandler extends MouseAdapter {
234: public void mouseClicked(MouseEvent evt) {
235: ShortcutsModel shortcutsModel = (ShortcutsModel) filteredModel
236: .getDelegated();
237: switch (keyTable.getTableHeader().columnAtPoint(
238: evt.getPoint())) {
239: case 0:
240: shortcutsModel.sort(0);
241: break;
242: case 1:
243: shortcutsModel.sort(1);
244: break;
245: case 2:
246: shortcutsModel.sort(2);
247: break;
248: }
249: setFilter();
250: }
251: }
252:
253: class TableMouseHandler extends MouseAdapter {
254: public void mouseClicked(MouseEvent evt) {
255: int row = keyTable.getSelectedRow();
256: int col = keyTable.getSelectedColumn();
257: if (col != 0 && row != -1) {
258: GrabKeyDialog gkd = new GrabKeyDialog(GUIUtilities
259: .getParentDialog(ShortcutsOptionPane.this ),
260: ((ShortcutsModel) filteredModel.getDelegated())
261: .getBindingAt(filteredModel
262: .getTrueRow(row), col - 1),
263: allBindings, null);
264: if (gkd.isOK())
265: filteredModel.setValueAt(gkd.getShortcut(), row,
266: col);
267: }
268: }
269: }
270:
271: class ActionHandler implements ActionListener {
272: public void actionPerformed(ActionEvent evt) {
273: ShortcutsModel newModel = (ShortcutsModel) selectModel
274: .getSelectedItem();
275: if (filteredModel.getDelegated() != newModel) {
276: jEdit.setIntegerProperty(
277: "options.shortcuts.select.index", selectModel
278: .getSelectedIndex());
279: filteredModel.setDelegated(newModel);
280: setFilter();
281: }
282: }
283: }
284:
285: class ShortcutsModel extends AbstractTableModel {
286: private Vector<GrabKeyDialog.KeyBinding[]> bindings;
287: private String name;
288:
289: ShortcutsModel(String name,
290: Vector<GrabKeyDialog.KeyBinding[]> bindings) {
291: this .name = name;
292: this .bindings = bindings;
293: sort(0);
294: }
295:
296: public Vector<GrabKeyDialog.KeyBinding[]> getBindings() {
297: return bindings;
298: }
299:
300: public void sort(int col) {
301: Collections.sort(bindings, new KeyCompare(col));
302: }
303:
304: public int getColumnCount() {
305: return 3;
306: }
307:
308: public int getRowCount() {
309: return bindings.size();
310: }
311:
312: public Object getValueAt(int row, int col) {
313: switch (col) {
314: case 0:
315: return getBindingAt(row, 0).label;
316: case 1:
317: return getBindingAt(row, 0).shortcut;
318: case 2:
319: return getBindingAt(row, 1).shortcut;
320: default:
321: return null;
322: }
323: }
324:
325: public void setValueAt(Object value, int row, int col) {
326: if (col == 0)
327: return;
328:
329: getBindingAt(row, col - 1).shortcut = (String) value;
330:
331: // redraw the whole table because a second shortcut
332: // might have changed, too
333: fireTableDataChanged();
334: }
335:
336: public String getColumnName(int index) {
337: switch (index) {
338: case 0:
339: return jEdit.getProperty("options.shortcuts.name");
340: case 1:
341: return jEdit.getProperty("options.shortcuts.shortcut1");
342: case 2:
343: return jEdit.getProperty("options.shortcuts.shortcut2");
344: default:
345: return null;
346: }
347: }
348:
349: public void save() {
350: for (GrabKeyDialog.KeyBinding[] binding : bindings) {
351: jEdit.setProperty(binding[0].name + ".shortcut",
352: binding[0].shortcut);
353: jEdit.setProperty(binding[1].name + ".shortcut2",
354: binding[1].shortcut);
355: }
356: }
357:
358: public GrabKeyDialog.KeyBinding getBindingAt(int row, int nr) {
359: GrabKeyDialog.KeyBinding[] binding = bindings
360: .elementAt(row);
361: return binding[nr];
362: }
363:
364: public String toString() {
365: return name;
366: }
367:
368: class KeyCompare implements
369: Comparator<GrabKeyDialog.KeyBinding[]> {
370: int col;
371:
372: KeyCompare(int col) {
373: this .col = col;
374: }
375:
376: public int compare(GrabKeyDialog.KeyBinding[] k1,
377: GrabKeyDialog.KeyBinding[] k2) {
378: String label1 = k1[0].label.toLowerCase();
379: String label2 = k2[0].label.toLowerCase();
380:
381: if (col == 0)
382: return StandardUtilities.compareStrings(label1,
383: label2, true);
384: else {
385: String shortcut1, shortcut2;
386: if (col == 1) {
387: shortcut1 = k1[0].shortcut;
388: shortcut2 = k2[0].shortcut;
389: } else {
390: shortcut1 = k1[1].shortcut;
391: shortcut2 = k2[1].shortcut;
392: }
393:
394: if (shortcut1 == null && shortcut2 != null)
395: return 1;
396: else if (shortcut2 == null && shortcut1 != null)
397: return -1;
398: else if (shortcut1 == null)
399: return StandardUtilities.compareStrings(label1,
400: label2, true);
401: else
402: return StandardUtilities.compareStrings(
403: shortcut1, shortcut2, true);
404: }
405: }
406: }
407: }
408: }
|