/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: EditKeyBindings.java
*
* Copyright (c) 2003 Sun Microsystems and Static Free Software
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.user.dialogs;
import com.sun.electric.Main;
import com.sun.electric.tool.user.dialogs.options.PreferencePanel;
import com.sun.electric.tool.user.menus.EMenu;
import com.sun.electric.tool.user.menus.EMenuBar;
import com.sun.electric.tool.user.menus.EMenuItem;
import com.sun.electric.tool.user.ui.KeyBindings;
import com.sun.electric.tool.user.ui.KeyStrokePair;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
* Class to manage bindings of keystrokes to pulldown menus.
*/
public class EditKeyBindings extends PreferencePanel implements TreeSelectionListener {
private static final long serialVersionUID = 1L;
/** MenuBarGroup for building dialog tree */ EMenuBar menuBar;
/** class to encapsulate a tree node for displaying key bindings.
* The toString() method is overridden to show the key binding next to the
* command name. This class encapsulates both JMenuItem and Menu, note
* that both extend JMenuItem.
*/
private class KeyBoundTreeNode
{
private EMenuItem menuItem;
KeyBoundTreeNode(EMenuItem menuItem) {
this.menuItem = menuItem;
}
public EMenuItem getMenuItem() { return menuItem; }
/**
* Convert to String to show on dialog tree
*/
public String toString() {
if (menuItem != EMenuItem.SEPARATOR) {
StringBuffer buf = new StringBuffer(menuItem.getDescription());
KeyBindings bindings = menuBar.getKeyBindings(menuItem);
if (bindings == null) return buf.toString();
Iterator it = bindings.getKeyStrokePairs();
if (!it.hasNext()) return buf.toString();
buf.append(" [ "+bindings.bindingsToString()+" ]");
return buf.toString();
}
return "---------------"; // separator
}
}
/** Creates new form EditKeyBindings */
public EditKeyBindings(EMenuBar menuBar, java.awt.Frame parent, boolean modal) {
super(parent, modal);
this.menuBar = menuBar;
initComponents();
buildCommandsTree();
}
// -------------------------- Preference Panel Stuff -----------------------
public JPanel getUserPreferencesPanel() {
return editKeyBindingsPanel;
}
public String getName() { return "Key Bindings"; }
/**
* Method called when the factory reset is requested for just this panel.
* @return true if the panel can be reset "in place" without redisplay.
*/
public boolean resetThis()
{
menuBar.resetAllKeyBindings();
// update tree view
DefaultTreeModel model = (DefaultTreeModel)commandsTree.getModel();
model.reload();
EMenuItem item = getSelectedMenuItem();
updateListBox(item);
return true;
}
public void reset()
{
menuBar.resetAllKeyBindings();
}
// -------------------------------------------------------------------------
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
editKeyBindingsPanel = new javax.swing.JPanel();
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
commandsTree = new javax.swing.JTree();
jPanel2 = new javax.swing.JPanel();
add = new javax.swing.JButton();
remove = new javax.swing.JButton();
resetitem = new javax.swing.JButton();
jPanel4 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
bindingsJList = new javax.swing.JList();
getContentPane().setLayout(new java.awt.GridBagLayout());
setTitle("Edit Key Bindings");
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
exitForm(evt);
}
});
editKeyBindingsPanel.setLayout(new java.awt.GridBagLayout());
jPanel1.setLayout(new java.awt.GridLayout(1, 0));
jPanel1.setPreferredSize(new java.awt.Dimension(350, 363));
jScrollPane1.setViewportView(commandsTree);
jPanel1.add(jScrollPane1);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
editKeyBindingsPanel.add(jPanel1, gridBagConstraints);
jPanel2.setLayout(new java.awt.GridBagLayout());
jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
add.setText("Add");
add.setToolTipText("add a shortcut");
add.setPreferredSize(new java.awt.Dimension(68, 28));
add.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
addActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
jPanel2.add(add, gridBagConstraints);
remove.setText("Remove");
remove.setToolTipText("remove a shortcut");
remove.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
jPanel2.add(remove, gridBagConstraints);
resetitem.setText("Reset");
resetitem.setToolTipText("reset to default setting");
resetitem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
resetitemActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets(2, 4, 2, 4);
jPanel2.add(resetitem, gridBagConstraints);
jPanel4.setLayout(new java.awt.GridBagLayout());
jLabel1.setText("Shortcuts:");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
jPanel4.add(jLabel1, gridBagConstraints);
bindingsJList.setBorder(javax.swing.BorderFactory.createEtchedBorder());
bindingsJList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
jPanel4.add(bindingsJList, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridheight = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
jPanel2.add(jPanel4, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
editKeyBindingsPanel.add(jPanel2, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
getContentPane().add(editKeyBindingsPanel, gridBagConstraints);
pack();
}// </editor-fold>//GEN-END:initComponents
// -------------------------------- Actions ----------------------------------
/**
* Resets a menu item back to its default key bindings
* @param evt the event
*/
private void resetitemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetitemActionPerformed
// get currently selected node
EMenuItem item = getSelectedMenuItem();
if (item == null || item == EMenuItem.SEPARATOR || item instanceof EMenu) return;
// reset item to default bindings
menuBar.resetKeyBindings(item);
// update tree view and list box
DefaultTreeModel model = (DefaultTreeModel)commandsTree.getModel();
model.reload(getSelectedTreeNode());
updateListBox(item);
}//GEN-LAST:event_resetitemActionPerformed
/**
* Remove a key binding from the menu item
* @param evt the event
*/
private void removeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeActionPerformed
// get currently selected node
EMenuItem item = getSelectedMenuItem();
if (item == null || item == EMenuItem.SEPARATOR || item instanceof EMenu) {
JOptionPane.showMessageDialog(null, "Please select a menu item first", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
// get selected key binding
KeyStrokePair pair = getListBoxSelected();
if (pair == null) {
JOptionPane.showMessageDialog(null, "Please select the shortcut from the list to remove", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
// remove it and update view
menuBar.removeKeyBinding(item.getDescription(), pair);
DefaultTreeModel model = (DefaultTreeModel)commandsTree.getModel();
model.reload(getSelectedTreeNode());
updateListBox(item);
}//GEN-LAST:event_removeActionPerformed
/**
* Reset *All* menu items to their default Key Bindings
* @param evt the event
*/
/**
* Open dialog to add a key binding to the selected menu item
* @param evt the event
*/
private void addActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addActionPerformed
EMenuItem item = getSelectedMenuItem();
if (item == null || item == EMenuItem.SEPARATOR || item instanceof EMenu) return;
EditKeyBinding dialog = new EditKeyBinding(item, menuBar, Main.getCurrentJFrame(), true);
dialog.setVisible(true);
// update tree view
DefaultTreeModel model = (DefaultTreeModel)commandsTree.getModel();
model.reload(getSelectedTreeNode());
updateListBox(item);
}//GEN-LAST:event_addActionPerformed
/** Exit the Application */
private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
}//GEN-LAST:event_exitForm
// -------------------------------- Tree View Population -------------------------------
/** Build tree of menu commands */
private void buildCommandsTree() {
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
// convert menuBar to tree
for (EMenuItem menu: menuBar.getItems()) {
DefaultMutableTreeNode menuNode = new DefaultMutableTreeNode(new KeyBoundTreeNode(menu));
rootNode.add(menuNode);
addMenu(menuNode, (EMenu)menu);
}
EMenu hiddenMenu = menuBar.getHiddenMenu();
if(hiddenMenu != null) {
DefaultMutableTreeNode menuNode = new DefaultMutableTreeNode(new KeyBoundTreeNode(hiddenMenu));
rootNode.add(menuNode);
addMenu(menuNode, hiddenMenu);
}
commandsTree.setModel(new DefaultTreeModel(rootNode));
// single selection as default
commandsTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
// do not show top-level
commandsTree.setRootVisible(false);
commandsTree.setShowsRootHandles(true);
commandsTree.setToggleClickCount(3);
commandsTree.addTreeSelectionListener(this);
}
/** Adds menu items to parentNode, which represents Menu menu. */
private void addMenu(DefaultMutableTreeNode parentNode, EMenu menu) {
for (EMenuItem menuItem: menu.getItems()) {
DefaultMutableTreeNode menuItemNode = new DefaultMutableTreeNode(new KeyBoundTreeNode(menuItem));
parentNode.add(menuItemNode);
if (menuItem instanceof EMenu)
addMenu(menuItemNode, (EMenu)menuItem); // recurse
}
}
// ---------------------------- Tree Selection Listener -----------------------
/**
* Called when selection of Node in tree changes.
* It updates the list box to reflect the current tree selection.
*/
public void valueChanged(javax.swing.event.TreeSelectionEvent e) {
TreePath path = e.getPath();
if (path == null) return;
Object obj = path.getLastPathComponent();
DefaultMutableTreeNode node = (DefaultMutableTreeNode)obj;
Object n = node.getUserObject();
if (!(n instanceof KeyBoundTreeNode)) return;
KeyBoundTreeNode treeNode = (KeyBoundTreeNode)n;
updateListBox(treeNode.getMenuItem());
}
// ------------------------------- List Box stuff -----------------------------
/**
* Update list box with item's key bindings
* @param item display key bindings for this item
*/
private void updateListBox(EMenuItem item) {
if (item == null) {
bindingsJList.setListData(new Object [] {});
return;
}
KeyBindings bindings = menuBar.getKeyBindings(item);
if (bindings == null) {
bindingsJList.setListData(new Object [] {});
return;
}
ArrayList<KeyStrokePair> list = new ArrayList<KeyStrokePair>();
for (Iterator<KeyStrokePair> it = bindings.getKeyStrokePairs(); it.hasNext(); ) {
KeyStrokePair pair = it.next();
list.add(pair);
}
bindingsJList.setListData(list.toArray());
}
private KeyStrokePair getListBoxSelected() {
Object value = bindingsJList.getSelectedValue();
if (value == null) return null;
return (KeyStrokePair)value;
}
//-------------------------- Private Utility Methods ----------------------------
/**
* Get selected menu item in tree view
* @return the selected menu item, or null if none.
*/
private EMenuItem getSelectedMenuItem() {
DefaultMutableTreeNode node = getSelectedTreeNode();
if (node == null) return null;
Object obj = node.getUserObject();
if (!(obj instanceof KeyBoundTreeNode)) return null;
KeyBoundTreeNode treeNode = (KeyBoundTreeNode)obj;
EMenuItem item = treeNode.getMenuItem();
return item;
}
/** get selected DefaultMutableTreeNode.
* Returns null if no valid DefaultMutableTree node selected in tree.
*/
private DefaultMutableTreeNode getSelectedTreeNode() {
TreePath path = commandsTree.getSelectionPath();
if (path == null) return null;
DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
return node;
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton add;
private javax.swing.JList bindingsJList;
private javax.swing.JTree commandsTree;
private javax.swing.JPanel editKeyBindingsPanel;
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel4;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JButton remove;
private javax.swing.JButton resetitem;
// End of variables declaration//GEN-END:variables
}