/*
* WPCleaner: A tool to help on Wikipedia maintenance tasks.
* Copyright (C) 2013 Nicolas Vervelle
*
* See README.txt file for licensing information.
*/
package org.wikipediacleaner.gui.swing.options;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import org.wikipediacleaner.gui.swing.basic.Utilities;
import org.wikipediacleaner.i18n.GT;
import org.wikipediacleaner.utils.Configuration;
import org.wikipediacleaner.utils.ConfigurationValueShortcut;
/**
* A panel for shortcut options.
*/
public class ShortcutOptionsPanel extends OptionsPanel {
/**
* Serialization.
*/
private static final long serialVersionUID = 5269712919862161621L;
/**
* Construct a Shortcut Options panel.
*/
public ShortcutOptionsPanel() {
super(new GridBagLayout());
initialize();
}
/**
* Shortcuts
*/
private Vector<ConfigurationValueShortcut> shortcuts;
/**
* A notice to explain how to set up a shortcut.
*/
private JLabel notice;
/**
* Initialize the panel.
*/
private void initialize() {
setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), GT._("Shortcut options (restart needed)")));
shortcuts = new Vector<ConfigurationValueShortcut>();
// Initialize constraints
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridheight = 1;
constraints.gridwidth = 1;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.insets = new Insets(0, 0, 0, 0);
constraints.ipadx = 0;
constraints.ipady = 0;
constraints.weightx = 1;
constraints.weighty = 0;
// Create internal panel
JPanel panel = new JPanel(new GridBagLayout());
JScrollPane scrollPane = new JScrollPane(
panel,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setMinimumSize(new Dimension(200, 200));
scrollPane.setPreferredSize(new Dimension(300, 400));
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = 1;
constraints.weighty = 1;
add(scrollPane, constraints);
// Add line for add to watch list
addLine(
panel, constraints, GT._("Add to local watchlist"),
ConfigurationValueShortcut.ADD_TO_WATCH_LIST);
// Add line for apply
addLine(
panel, constraints, GT._("Apply"),
ConfigurationValueShortcut.APPLY);
// Add line for bug report
addLine(
panel, constraints, GT._("Idea? Bug?"),
ConfigurationValueShortcut.BUG_REPORT);
// Add line for close
addLine(
panel, constraints, GT._("Close"),
ConfigurationValueShortcut.CLOSE);
// Add line for current disambiguation list
addLine(
panel, constraints, GT._("Current disambiguation list"),
ConfigurationValueShortcut.CURRENT_DAB_LIST);
// Add line for disambiguation analysis
addLine(
panel, constraints, GT._("Disambiguation"),
ConfigurationValueShortcut.DAB_ANALYSIS);
// Add line for external viewer
addLine(
panel, constraints, GT._("External Viewer"),
ConfigurationValueShortcut.EXTERNAL_VIEWER);
// Add line for full analysis
addLine(
panel, constraints, GT._("Full analysis"),
ConfigurationValueShortcut.FULL_ANALYSIS);
// Add line for help
addLine(
panel, constraints, GT._("Help"),
ConfigurationValueShortcut.HELP);
// Add line for history
addLine(
panel, constraints, GT._("History"),
ConfigurationValueShortcut.HISTORY);
// Add line for login
addLine(
panel, constraints, GT._("Login"),
ConfigurationValueShortcut.LOGIN);
// Add line for logout
addLine(
panel, constraints, GT._("Logout"),
ConfigurationValueShortcut.LOGOUT);
// Add line for options
addLine(
panel, constraints, GT._("Options"),
ConfigurationValueShortcut.OPTIONS);
// Add line for random page
addLine(
panel, constraints, GT._("Random page"),
ConfigurationValueShortcut.RANDOM_PAGE);
// Add line for restore defaults
addLine(
panel, constraints, GT._("Restore defaults"),
ConfigurationValueShortcut.RESTORE_DEFAULTS);
// Add line for send
addLine(
panel, constraints, GT._("Send"),
ConfigurationValueShortcut.SEND);
// Add line for system options
addLine(
panel, constraints, GT._("System options"),
ConfigurationValueShortcut.SYSTEM_OPTIONS);
// Add line for validate
addLine(
panel, constraints, GT._("Validate"),
ConfigurationValueShortcut.VALIDATE);
// Add line for watch list
addLine(
panel, constraints, GT._("Local Watchlist"),
ConfigurationValueShortcut.WATCH_LIST);
// Add line for adding to list
addLine(
panel, constraints, GT._("Add to list"),
ConfigurationValueShortcut.LIST_ADD);
// Add line for removing from list
addLine(
panel, constraints, GT._("Remove from list"),
ConfigurationValueShortcut.LIST_REMOVE);
// Add line for first occurrence
addLine(
panel, constraints, GT._("First occurrence"),
ConfigurationValueShortcut.OCCURRENCE_FIRST);
// Add line for previous occurrence
addLine(
panel, constraints, GT._("Previous occurrence"),
ConfigurationValueShortcut.OCCURRENCE_PREVIOUS);
// Add line for next occurrence
addLine(
panel, constraints, GT._("Next occurrence"),
ConfigurationValueShortcut.OCCURRENCE_NEXT);
// Add line for last occurrence
addLine(
panel, constraints, GT._("Last occurrence"),
ConfigurationValueShortcut.OCCURRENCE_LAST);
// Add a notice
notice = new JLabel(GT._("Press key for shortcut or ESC to cancel"));
notice.setForeground(Color.RED);
notice.setVisible(false);
notice.setHorizontalAlignment(SwingConstants.CENTER);
constraints.gridx = 0;
constraints.gridwidth = columnCount;
panel.add(notice, constraints);
constraints.gridy++;
// Empty panel
JPanel emptyPanel = new JPanel();
emptyPanel.setMinimumSize(new Dimension(0, 0));
emptyPanel.setPreferredSize(new Dimension(0, 0));
constraints.fill = GridBagConstraints.BOTH;
constraints.insets = new Insets(0, 0, 0, 0);
constraints.gridx = 0;
constraints.gridwidth = columnCount;
constraints.weighty = 1;
panel.add(emptyPanel, constraints);
}
/**
* Restore all options to their default values.
*/
@Override
public void defaultValues() {
super.defaultValues();
for (int line = 0; line < shortcuts.size(); line++) {
setShortcut(line, shortcuts.get(line));
}
}
/**
* Apply new values to the options.
*/
@Override
public void apply() {
super.apply();
for (int line = 0; line < shortcuts.size(); line++) {
applyShortcut(shortcuts.get(line), line);
}
}
/**
* Apply new values for a shortcut.
*
* @param shortcut Shortcut.
* @param line Line.
*/
private void applyShortcut(ConfigurationValueShortcut shortcut, int line) {
Configuration config = Configuration.getConfiguration();
ConfigurationValueShortcut.ShortcutProperties configShortcut = getShortcut(line, shortcut.getName());
config.setShortcut(shortcut, configShortcut);
}
// ==========================================================================
// Managing the elements of a shortcut
// ==========================================================================
private final List<JCheckBox> chkEnabled = new ArrayList<JCheckBox>();
private final List<JToggleButton> chkCtrl = new ArrayList<JToggleButton>();
private final List<JToggleButton> chkAlt = new ArrayList<JToggleButton>();
private final List<JToggleButton> chkShift = new ArrayList<JToggleButton>();
private final List<KeyCodeButton> btnKey = new ArrayList<KeyCodeButton>();
// Count columns
private final static int columnEnabled = 0;
private final static int columnName = columnEnabled + 1;
private final static int columnCtrl = columnName + 1;
private final static int columnAlt = columnCtrl + 1;
private final static int columnShift = columnAlt + 1;
private final static int columnKey = columnShift + 1;
private final static int columnCount = columnKey + 1;
/**
* Add a line for a shortcut.
*
* @param panel Panel containing the shortcuts.
* @param constraints Grid bag constraints.
* @param name Descriptive name of the shortcut.
* @param shortcut Shortcut.
*/
private void addLine(
JPanel panel,
GridBagConstraints constraints,
String name,
ConfigurationValueShortcut shortcut) {
// Enabled check box
JCheckBox chk = Utilities.createJCheckBox("", true);
chkEnabled.add(chk);
constraints.gridx = columnEnabled;
constraints.weightx = 0;
panel.add(chk, constraints);
// Name
if (name != null) {
JLabel label = Utilities.createJLabel(name);
constraints.gridx = columnName;
constraints.weightx = 1;
panel.add(label, constraints);
}
// CTRL key
JToggleButton toggle = Utilities.createJToggleButton("CTRL");
chkCtrl.add(toggle);
constraints.gridx = columnCtrl;
constraints.weightx = 0;
panel.add(toggle, constraints);
// ALT key
toggle = Utilities.createJToggleButton("ALT");
chkAlt.add(toggle);
constraints.gridx = columnAlt;
constraints.weightx = 0;
panel.add(toggle, constraints);
// SHIFT key
toggle = Utilities.createJToggleButton("SHIFT");
chkShift.add(toggle);
constraints.gridx = columnShift;
constraints.weightx = 0;
panel.add(toggle, constraints);
// Key
KeyCodeButton button = new KeyCodeButton(0);
btnKey.add(button);
constraints.gridx = columnKey;
constraints.weightx = 0;
panel.add(button, constraints);
// Next line
constraints.gridy++;
int line = shortcuts.size();
shortcuts.add(shortcut);
setShortcut(line, shortcut);
}
/**
* Set the attributes for a shortcut.
*
* @param line Line number.
* @param shortcut Shortcut.
*/
private void setShortcut(int line, ConfigurationValueShortcut shortcut) {
Configuration config = Configuration.getConfiguration();
if (shortcut == null) {
return;
}
ConfigurationValueShortcut.ShortcutProperties properties = config.getShortcut(shortcut);
setEnabled(line, properties.getEnabled());
setCtrl(line, properties.getCtrlKey());
setAlt(line, properties.getAltKey());
setShift(line, properties.getShiftKey());
setKey(line, properties.getKey());
}
/**
* @param line Line number.
* @param name Shortcut name.
* @return Shortcut.
*/
private ConfigurationValueShortcut.ShortcutProperties getShortcut(
int line, String name) {
if ((line < 0) || (line >= shortcuts.size())) {
return null;
}
boolean enabled = true;
if (chkEnabled.get(line) != null) {
enabled = chkEnabled.get(line).isSelected();
}
boolean ctrl = false;
if (chkCtrl.get(line) != null) {
ctrl = chkCtrl.get(line).isSelected();
}
boolean alt = false;
if (chkAlt.get(line) != null) {
alt = chkAlt.get(line).isSelected();
}
boolean shift = false;
if (chkShift.get(line) != null) {
shift = chkShift.get(line).isSelected();
}
int key = 0;
if (btnKey.get(line) != null) {
key = btnKey.get(line).getKeyCode();
}
return new ConfigurationValueShortcut.ShortcutProperties(
enabled, name, ctrl, alt, shift, key);
}
/**
* Set the checkbox for the enabled column.
*
* @param line Line number.
* @param value Checkbox value.
*/
private void setEnabled(int line, boolean value) {
setToggleButton(chkEnabled, line, value);
}
/**
* Set the checkbox for the ctrl column.
*
* @param line Line number.
* @param value Checkbox value.
*/
private void setCtrl(int line, boolean value) {
setToggleButton(chkCtrl, line, value);
}
/**
* Set the checkbox for the alt column.
*
* @param line Line number.
* @param value Checkbox value.
*/
private void setAlt(int line, boolean value) {
setToggleButton(chkAlt, line, value);
}
/**
* Set the checkbox for the shift column.
*
* @param line Line number.
* @param value Checkbox value.
*/
private void setShift(int line, boolean value) {
setToggleButton(chkShift, line, value);
}
/**
* Set the value for the key column.
*
* @param line Line number.
* @param value Key value.
*/
private void setKey(int line, int value) {
if (btnKey == null) {
return;
}
if ((line < 0) || (line >= btnKey.size())) {
return;
}
KeyCodeButton btn = btnKey.get(line);
if (btn == null) {
return;
}
btn.setKeyCode(value);
}
/**
* Set the toggle button for a column.
*
* @param list List of checkboxes.
* @param line Line number.
* @param value Checkbox value.
*/
private void setToggleButton(List<? extends JToggleButton> list, int line, boolean value) {
if (list == null) {
return;
}
if ((line < 0) || (line >= list.size())) {
return;
}
JToggleButton chk = list.get(line);
if (chk == null) {
return;
}
chk.setSelected(value);
}
/**
* Display a notice.
*
* @param display True to display the notice.
*/
void showNotice(boolean display) {
notice.setVisible(display);
}
/**
* Button for editing a key code.
*/
private class KeyCodeButton extends JButton implements ActionListener, KeyEventDispatcher {
/**
* Serialization.
*/
private static final long serialVersionUID = -2362841546820504549L;
/**
* Key code.
*/
private int keyCode;
/**
* @param keyCode Key code.
*/
KeyCodeButton(int keyCode) {
super();
setKeyCode(keyCode);
addActionListener(this);
}
/**
* @param keyCode Key code.
*/
public void setKeyCode(int keyCode) {
this.keyCode = keyCode;
setText(KeyEvent.getKeyText(keyCode));
}
/**
* @return Key code.
*/
public int getKeyCode() {
return keyCode;
}
/**
* Action triggered when button is clicked.
*
* @param e Event.
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
showNotice(true);
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
}
/**
* Action triggered when keyboard is used.
*
* @param e Event.
* @return True if processing should end.
* @see java.awt.KeyEventDispatcher#dispatchKeyEvent(java.awt.event.KeyEvent)
*/
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_ALT) ||
(key == KeyEvent.VK_ALT_GRAPH) ||
(key == KeyEvent.VK_BACK_SPACE) ||
(key == KeyEvent.VK_BEGIN) ||
(key == KeyEvent.VK_CANCEL) ||
(key == KeyEvent.VK_CAPS_LOCK) ||
(key == KeyEvent.VK_CONTROL) ||
(key == KeyEvent.VK_DELETE) ||
(key == KeyEvent.VK_DOWN) ||
(key == KeyEvent.VK_END) ||
(key == KeyEvent.VK_ENTER) ||
(key == KeyEvent.VK_LEFT) ||
(key == KeyEvent.VK_PAGE_DOWN) ||
(key == KeyEvent.VK_PAGE_UP) ||
(key == KeyEvent.VK_RIGHT) ||
(key == KeyEvent.VK_SHIFT) ||
(key == KeyEvent.VK_TAB) ||
(key == KeyEvent.VK_UP) ||
(key == KeyEvent.VK_SHIFT)) {
return false;
}
if (key != KeyEvent.VK_ESCAPE) {
setKeyCode(key);
}
showNotice(false);
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this);
return false;
}
}
}