blob: 5f5b2ffaf7a7451b0172162617f52ff9d187f907 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.options.keymap;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.RowSorterEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import org.netbeans.api.options.OptionsDisplayer;
import org.netbeans.core.options.keymap.api.ShortcutAction;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.Task;
import org.openide.util.TaskListener;
import org.openide.util.Utilities;
/**
*
* @author Max Sauer
*/
@OptionsPanelController.Keywords(keywords={"#KW_KeymapOptions"}, location=OptionsDisplayer.KEYMAPS)
public class KeymapPanel extends javax.swing.JPanel implements ActionListener, Popupable, ChangeListener {
// Delay times for incremental search [ms]
private static final int SEARCH_DELAY_TIME_LONG = 300; // < 3 chars
private static final int SEARCH_DELAY_TIME_SHORT = 20; // >= 3 chars
private volatile KeymapViewModel keymapModel;
private TableSorter sorter;
private JPopupMenu popup = new JPopupMenu();
private boolean ignoreActionEvents;
//search fields
private Popup searchPopup;
private SpecialkeyPanel specialkeyList;
/** Creates new form KeymapPanel */
public KeymapPanel() {
sorter = new TableSorter(getModel());
initComponents();
specialkeyList = new SpecialkeyPanel(this, searchSCField);
// close the popup when user clicks elsewhere
moreButton.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
hidePopup();
}
});
sorter.setTableHeader(actionsTable.getTableHeader());
sorter.getTableHeader().setReorderingAllowed(false);
actionsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
actionsTable.setAutoscrolls(true);
ActionListener al = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getModel().setSearchText(searchField.getText());
getModel().update();
}
};
final Timer searchDelayTimer = new Timer(SEARCH_DELAY_TIME_LONG, al);
searchDelayTimer.setRepeats(false);
searchField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
searchSCField.setText("");
((ShortcutListener)searchSCField.getKeyListeners()[0]).clear();
if (searchField.getText().length() > 3)
searchDelayTimer.setInitialDelay(SEARCH_DELAY_TIME_SHORT);
searchDelayTimer.restart();
}
@Override
public void removeUpdate(DocumentEvent e) {
if (searchField.getText().length() > 3)
searchDelayTimer.setInitialDelay(SEARCH_DELAY_TIME_LONG);
searchDelayTimer.restart();
}
@Override
public void changedUpdate(DocumentEvent e) {
searchSCField.setText("");
getModel().setSearchText(searchField.getText());
getModel().update();
}
});
searchSCField.addKeyListener(new ShortcutListener(false));
ActionListener al2 = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
narrowByShortcut();
}
};
final Timer searchDelayTimer2 = new Timer(SEARCH_DELAY_TIME_SHORT, al2);
searchDelayTimer2.setRepeats(false);
searchSCField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
searchField.setText("");
searchDelayTimer2.restart();
}
@Override
public void removeUpdate(DocumentEvent e) {
searchDelayTimer2.restart();
}
@Override
public void changedUpdate(DocumentEvent e) {
searchDelayTimer2.restart();
}
});
actionsTable.addMouseListener(new ButtonCellMouseListener(actionsTable));
actionsTable.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() != KeyEvent.VK_CONTEXT_MENU &&
e.getKeyCode() != KeyEvent.VK_F2) {
return;
}
int leadRow = actionsTable.getSelectionModel().getLeadSelectionIndex();
int leadColumn = actionsTable.getColumnModel().getSelectionModel().
getLeadSelectionIndex();
if (leadRow != -1 && leadColumn != -1 && !actionsTable.isEditing()) {
showPopupMenu(leadRow, leadColumn, -1, -1);
e.consume();
}
}
});
TableColumn column = actionsTable.getColumnModel().getColumn(1);
column.setCellEditor(new ButtonCellEditor(getModel()));
column.setCellRenderer(new ButtonCellRenderer(actionsTable.getDefaultRenderer(ButtonCellRenderer.class)));
setColumnWidths();
popupPanel = new ShortcutPopupPanel(actionsTable, popup);
popup.add(popupPanel);
cbProfile.addActionListener(this);
manageButton.addActionListener(this);
btnPrintAsHTML.setVisible(ExportShortcutsAction.getExportShortcutsToHTMLAction().isEnabled());
}
private ShortcutPopupPanel popupPanel;
private class KeymapTable extends JTable {
int lastRow;
int lastColumn;
@Override
public boolean editCellAt(int row, int column) {
lastRow = row;
lastColumn = column;
boolean editCellAt = super.editCellAt(row, column);
((DefaultCellEditor) getCellEditor(lastRow, lastColumn)).getComponent().requestFocus();
return editCellAt;
}
@Override
protected void processKeyEvent(KeyEvent e) {
if (!isEditing())
super.processKeyEvent(e);
else {
Component component = ((DefaultCellEditor) getCellEditor(lastRow, lastColumn)).getComponent();
component.requestFocus();
component.dispatchEvent(new KeyEvent(component, e.getID(), e.getWhen(), e.getModifiers(), e.getKeyCode(), e.getKeyChar()));
}
}
private String selectedActionId;
@Override
public void valueChanged(ListSelectionEvent e) {
super.valueChanged(e);
if (!e.getValueIsAdjusting()) {
int index = getSelectedRow();
selectedActionId = getActionId(index);
}
}
@Override
public void sorterChanged(RowSorterEvent e) {
String aid = selectedActionId;
int colIndex = getSelectedColumn();
super.sorterChanged(e);
restoreSelection(aid, colIndex);
}
private void restoreSelection(String id, int colIndex) {
if (id == null) {
clearSelection();
return;
}
TableModel tm = getModel();
for (int i = 0; i < tm.getRowCount(); i++) {
ActionHolder ah = (ActionHolder)tm.getValueAt(i, 0);
if (ah != null && id.equals(ah.getAction().getId())) {
changeSelection(i, colIndex, false, false);
break;
}
}
}
private String getActionId(int modelIndex) {
if (modelIndex >= 0 && modelIndex < getModel().getRowCount()) {
ActionHolder h = (ActionHolder)getModel().getValueAt(modelIndex, 0);
if (h != null) {
ShortcutAction sa = h.getAction();
return sa.getId();
}
}
return null;
}
@Override
public void tableChanged(TableModelEvent e) {
String aid = selectedActionId;
// preserve also table column selection:
int colIndex = getSelectedColumn();
super.tableChanged(e);
restoreSelection(aid, colIndex);
}
}
//todo: merge with update
private void narrowByShortcut() {
if (searchSCField.getText().length() != 0) {
final String searchText = searchSCField.getText();
getModel().runWithoutEvents(new Runnable() {
public void run() {
getModel().getDataVector().removeAllElements();
for (String categorySet : getModel().getCategories().keySet()) {
for (String category : getModel().getCategories().get(categorySet)) {
for (Object o : getMutableModel().getItems(category, false)) {
ShortcutAction sca = (ShortcutAction) o;
String[] shortcuts = getMutableModel().getShortcuts(sca);
for (int i = 0; i < shortcuts.length; i++) {
String shortcut = shortcuts[i];
if (searched(shortcut, searchText))
getModel().addRow(new Object[]{new ActionHolder(sca, false), shortcut, category, ""});
}
}
}
}
}
});
getModel().fireTableDataChanged();
} else
getModel().update();
}
KeymapViewModel getModel() {
if (keymapModel == null) {
KeymapViewModel tmpModel = new KeymapViewModel();
synchronized (this) {
if (keymapModel == null) {
keymapModel = tmpModel;
tmpModel.getMutableModel().addChangeListener(this);
}
}
}
return keymapModel;
}
MutableShortcutsModel getMutableModel() {
return getModel().getMutableModel();
}
//controller methods
void applyChanges() {
stopCurrentCellEditing();
getMutableModel().apply();
}
void cancel() {
stopCurrentCellEditing();
if (keymapModel == null)
return;
getMutableModel().cancel();
}
boolean dataValid() {
return true;
}
boolean isChanged() {
return getMutableModel().isChanged();
}
void update() {
//do not remember search state
getModel().setSearchText(""); //NOI18N
searchSCField.setText("");
((ShortcutListener)searchSCField.getKeyListeners()[0]).clear();
searchField.setText(""); //NOI18N
//setup profiles
refreshProfileCombo ();
class I implements Runnable, TaskListener {
int stage;
public void run() {
if (stage > 0) {
((CardLayout)actionsView.getLayout()).show(actionsView, "actions"); // NOI18N
} else {
getMutableModel().refreshActions();
Task t = getModel().postUpdate();
t.addTaskListener(this);
}
}
@Override
public void taskFinished(Task t) {
stage++;
SwingUtilities.invokeLater(this);
}
}
//update model
KeymapModel.RP.post(new I());
}
//controller method end
private void refreshProfileCombo() {
ignoreActionEvents = true;
String currentProfile = getMutableModel().getCurrentProfile();
List keymaps = getMutableModel().getProfiles();
ComboBoxModel model = new DefaultComboBoxModel(keymaps.toArray());
currentProfile = getMutableModel().getProfileDisplayName(currentProfile);
cbProfile.setModel(model);
cbProfile.setSelectedItem(currentProfile);
ignoreActionEvents = false;
}
private void stopCurrentCellEditing() {
int row = actionsTable.getEditingRow();
int col = actionsTable.getEditingColumn();
if (row != -1)
actionsTable.getCellEditor(row,col).stopCellEditing();
}
/**
* @param shortcut shortcut compared with searched text
* @return true if search text is empty || shortcut starts with or contains
* searchtext
*/
private boolean searched(String shortcut, String searchText) {
//shortcut.equals(searchSCField.getText())
if (searchText.length() == 0 || shortcut.startsWith(searchText) ||
shortcut.contains(searchText))
return true;
else
return false;
}
/**
* Adjust column widths
*/
private void setColumnWidths() {
TableColumn column = null;
for (int i = 0; i < actionsTable.getColumnCount(); i++) {
column = actionsTable.getColumnModel().getColumn(i);
switch (i) {
case 0:
column.setPreferredWidth(250);
break;
case 1:
column.setPreferredWidth(175);
break;
case 2:
column.setPreferredWidth(60);
break;
case 3:
column.setPreferredWidth(60);
break;
}
}
}
/** 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.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
lProfile = new javax.swing.JLabel();
cbProfile = new javax.swing.JComboBox();
manageButton = new javax.swing.JButton();
spShortcuts = new javax.swing.JScrollPane();
liShortcuts = new javax.swing.JList();
searchField = new javax.swing.JTextField();
searchLabel = new javax.swing.JLabel();
searchSCLabel = new javax.swing.JLabel();
searchSCField = new javax.swing.JTextField();
moreButton = new javax.swing.JButton();
actionsView = new javax.swing.JPanel();
jPanel1 = new javax.swing.JPanel();
actionProgress = new javax.swing.JProgressBar();
waitLabel = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
actionsTable = new KeymapTable();
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
btnPrintAsHTML = new javax.swing.JButton();
jSeparator1 = new javax.swing.JSeparator();
lProfile.setLabelFor(cbProfile);
org.openide.awt.Mnemonics.setLocalizedText(lProfile, org.openide.util.NbBundle.getMessage(KeymapPanel.class, "CTL_Keymap_Name")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(manageButton, org.openide.util.NbBundle.getMessage(KeymapPanel.class, "CTL_Duplicate")); // NOI18N
spShortcuts.setViewportView(liShortcuts);
searchField.setText(org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.searchField.text")); // NOI18N
searchLabel.setLabelFor(searchField);
org.openide.awt.Mnemonics.setLocalizedText(searchLabel, org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.searchLabel.text")); // NOI18N
searchSCLabel.setLabelFor(searchSCField);
org.openide.awt.Mnemonics.setLocalizedText(searchSCLabel, org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.searchSCLabel.text")); // NOI18N
searchSCField.setText(org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.searchSCField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(moreButton, org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.moreButton.text")); // NOI18N
moreButton.setBorder(javax.swing.BorderFactory.createEtchedBorder());
moreButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
moreButtonActionPerformed(evt);
}
});
actionsView.setLayout(new java.awt.CardLayout());
actionProgress.setIndeterminate(true);
actionProgress.setString(org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.actionProgress.string")); // NOI18N
waitLabel.setFont(new java.awt.Font("Dialog", 2, 12)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(waitLabel, org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.waitLabel.text")); // NOI18N
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(waitLabel)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap(225, Short.MAX_VALUE)
.addComponent(actionProgress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(224, Short.MAX_VALUE))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(0, 57, Short.MAX_VALUE)
.addComponent(waitLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(actionProgress, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 90, Short.MAX_VALUE))
);
actionsView.add(jPanel1, "wait");
jScrollPane1.setPreferredSize(new java.awt.Dimension(453, 100));
actionsTable.setModel(sorter);
jScrollPane1.setViewportView(actionsTable);
actionsView.add(jScrollPane1, "actions");
org.openide.awt.Mnemonics.setLocalizedText(btnPrintAsHTML, org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.btnPrintAsHTML.text")); // NOI18N
btnPrintAsHTML.setToolTipText(org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.btnPrintAsHTML.toolTipText")); // NOI18N
btnPrintAsHTML.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnPrintAsHTMLActionPerformed(evt);
}
});
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(spShortcuts, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(83, 83, 83)
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(lProfile)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cbProfile, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnPrintAsHTML)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(manageButton))))
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(searchLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(searchSCLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(searchSCField, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(moreButton))
.addComponent(actionsView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {searchField, searchSCField});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(manageButton, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lProfile)
.addComponent(cbProfile, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnPrintAsHTML)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(moreButton)
.addComponent(searchSCField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(searchSCLabel)
.addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(searchLabel))
.addGap(10, 10, 10)
.addComponent(actionsView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))
.addGroup(layout.createSequentialGroup()
.addGap(87, 87, 87)
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(spShortcuts, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(filler1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
searchField.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(KeymapPanel.class, "KeymapPanel.searchField.AccessibleContext.accessibleDescription")); // NOI18N
}// </editor-fold>//GEN-END:initComponents
public void hidePopup() {
if (searchPopup != null) {
searchPopup.hide();
searchPopup = null;
}
}
/**
* Shows popup with ESC and TAB keys
*/
private void moreButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moreButtonActionPerformed
if (searchPopup != null) {
return;
}
JComponent tf = (JComponent) evt.getSource();
Point p = new Point(tf.getX(), tf.getY());
SwingUtilities.convertPointToScreen(p, this);
Rectangle usableScreenBounds = Utilities.getUsableScreenBounds();
if (p.x + specialkeyList.getWidth() > usableScreenBounds.width) {
p.x = usableScreenBounds.width - specialkeyList.getWidth();
}
if (p.y + specialkeyList.getHeight() > usableScreenBounds.height) {
p.y = usableScreenBounds.height - specialkeyList.getHeight();
}
//show special key popup
searchPopup = PopupFactory.getSharedInstance().getPopup(this, specialkeyList, p.x, p.y);
searchPopup.show();
}//GEN-LAST:event_moreButtonActionPerformed
private void btnPrintAsHTMLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPrintAsHTMLActionPerformed
if (getMutableModel().getCurrentProfile()!=null){
ExportShortcutsAction.exportShortcutsOfProfileToHTML(getMutableModel().getCurrentProfile());
}
}//GEN-LAST:event_btnPrintAsHTMLActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JProgressBar actionProgress;
private javax.swing.JTable actionsTable;
private javax.swing.JPanel actionsView;
private javax.swing.JButton btnPrintAsHTML;
private javax.swing.JComboBox cbProfile;
private javax.swing.Box.Filler filler1;
private javax.swing.Box.Filler filler2;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JLabel lProfile;
private javax.swing.JList liShortcuts;
private javax.swing.JButton manageButton;
private javax.swing.JButton moreButton;
private javax.swing.JTextField searchField;
private javax.swing.JLabel searchLabel;
private javax.swing.JTextField searchSCField;
private javax.swing.JLabel searchSCLabel;
private javax.swing.JScrollPane spShortcuts;
private javax.swing.JLabel waitLabel;
// End of variables declaration//GEN-END:variables
@Override
public Popup getPopup() {
return searchPopup;
}
class ButtonCellMouseListener implements MouseListener {
private JTable table;
public ButtonCellMouseListener(JTable table) {
this.table = table;
}
@Override
public void mouseClicked(MouseEvent e) {
forwardEvent(e);
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private void forwardEvent(MouseEvent e) {
Point p = new Point(e.getX(), e.getY());
int row = table.rowAtPoint(p);
int col = table.columnAtPoint(p);
if (showPopupMenu(row, col, e.getX(), e.getY())) {
e.consume();
}
}
}
private boolean showPopupMenu(int row, int col, int x, int y) {
JTable table = actionsTable;
if (col != 1) {
return false;
}
Object valueAt = table.getValueAt(row, col);
ShortcutCellPanel scCell = (ShortcutCellPanel) table.getCellRenderer(row, col).getTableCellRendererComponent(table, valueAt, true, true, row, col);
Rectangle cellRect = table.getCellRect(row, col, false);
JButton button = scCell.getButton();
if (x < 0 || x > (cellRect.x + cellRect.width - button.getWidth())) { //inside changeButton
boolean isShortcutSet = scCell.getTextField().getText().length() != 0;
final ShortcutPopupPanel panel = (ShortcutPopupPanel) popup.getComponents()[0];
panel.setDisplayAddAlternative(isShortcutSet);
panel.setRow(row);
if (x == -1 || y == -1) {
x = button.getX() + 1;
y = button.getY() + 1;
}
panel.setCustomProfile(keymapModel.getMutableModel().isCustomProfile(keymapModel.getMutableModel().getCurrentProfile()));
popup.show(table, x, y);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panel.requestFocus();
}
});
popup.requestFocus();
return true;
}
return false;
}
static String loc (String key) {
return NbBundle.getMessage (KeymapPanel.class, key);
}
@Override
public void actionPerformed(ActionEvent e) {
if (ignoreActionEvents) {
return;
}
Object source = e.getSource();
if (source == cbProfile) {
String profile = (String) cbProfile.getSelectedItem();
if (profile != null)
getMutableModel().setCurrentProfile(profile);
getModel().update();
} else if (source == manageButton) {
//remember previous profile state, in case user will cancel dialog
Map<String, Map<ShortcutAction, Set<String>>> modifiedProfiles = getMutableModel().getModifiedProfiles();
Set<String> deletedProfiles = getMutableModel().getDeletedProfiles();
//show manage profiles dialog
final ProfilesPanel profilesPanel = new ProfilesPanel(this);
DialogDescriptor dd = new DialogDescriptor(
profilesPanel,
NbBundle.getMessage(KeymapPanel.class, "CTL_Manage_Keymap_Profiles"),
true, new Object[] { DialogDescriptor.CLOSED_OPTION }, DialogDescriptor.CLOSED_OPTION,
DialogDescriptor.BOTTOM_ALIGN,
new HelpCtx("org.netbeans.modules.options.keymap.ProfilesPanel"),
null
);
DialogDisplayer.getDefault().notify(dd);
final String selectedProfile = profilesPanel.getSelectedProfile();
getMutableModel().setCurrentProfile(selectedProfile);
refreshProfileCombo();
keymapModel.update();
}
return;
}
public void stateChanged(ChangeEvent e) {
if (e.getSource() == getMutableModel()) {
firePropertyChange(OptionsPanelController.PROP_CHANGED, Boolean.FALSE, Boolean.TRUE);
}
}
}