package chatty.gui.components.userinfo; import chatty.gui.components.settings.Editor; import chatty.gui.components.settings.GenericComboSetting; import chatty.gui.components.settings.SettingsDialog; import chatty.util.settings.Settings; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.KeyboardFocusManager; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.AbstractAction; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.plaf.basic.BasicComboBoxRenderer; /** * * @author tduva */ public class BanReasons extends JPanel { private final GenericComboSetting<String> combo = new GenericComboSetting<>(); private final Settings settings; private final Editor settingEditor; private final JTextField customReasonInput = new JTextField(); private final GridBagConstraints customInputGbc; private String currentReasons; private final int[] codes = new int[]{KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_3, KeyEvent.VK_4, KeyEvent.VK_5, KeyEvent.VK_6, KeyEvent.VK_7, KeyEvent.VK_8, KeyEvent.VK_9}; public BanReasons(final Window parent, Settings settings) { this.settings = settings; setLayout(new GridBagLayout()); JButton editButton = new JButton(); editButton.setIcon(new ImageIcon(SettingsDialog.class.getResource("edit.png"))); editButton.setMargin(new Insets(0,2,0,2)); editButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { editReasons(); } }); settingEditor = new Editor(parent); settingEditor.setAllowEmpty(true); settingEditor.setAllowLinebreaks(true); final GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; add(combo, gbc); gbc.gridx = 1; gbc.fill = GridBagConstraints.VERTICAL; add(editButton, gbc); customInputGbc = new GridBagConstraints(); customInputGbc.gridx = 0; customInputGbc.gridy = 1; customInputGbc.gridwidth = 2; customInputGbc.fill = GridBagConstraints.HORIZONTAL; add(customReasonInput, customInputGbc); /** * Custom renderer to display the value of the items for the * selected item, instead of the label (hide the shortcut). */ combo.setRenderer(new BasicComboBoxRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, hasFocus); if (index == -1 && value != null) { String text = ((GenericComboSetting.Entry<String>)value).value; if (text != null && !text.isEmpty()) { setText(text); } } return this; } }); /** * Add/remove custom reason input box if last item is selected. */ combo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (combo.getItemCount() > 1 && combo.getSelectedIndex() == combo.getItemCount() - 1) { addCustomInput(); } else { removeCustomInput(); } } }); /** * When the popup is open, allow shortcuts to select items. */ combo.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (!combo.isPopupVisible()) { return; } for (int i=0;i<codes.length;i++) { if (codes[i] == e.getKeyCode()) { int indexToSelect = i+1; if (combo.getItemCount() > indexToSelect+1) { combo.setPopupVisible(false); combo.setSelectedIndex(indexToSelect); } e.consume(); } } if (e.getKeyCode() == KeyEvent.VK_C) { combo.setSelectedIndex(combo.getItemCount() - 1); e.consume(); } } }); // TODO: Disable for now until it can be configured // combo.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("R"), combo); combo.getActionMap().put(combo, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { if (parent.getFocusOwner().getClass() == JTextField.class) { return; } if (!combo.isPopupVisible() && combo.getSelectedIndex() != 0) { combo.setSelectedIndex(0); } combo.requestFocusInWindow(); combo.setPopupVisible(!combo.isPopupVisible()); } }); customReasonInput.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { KeyboardFocusManager.getCurrentKeyboardFocusManager().focusPreviousComponent(); } }); customReasonInput.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_UP) { combo.requestFocusInWindow(); combo.setPopupVisible(true); combo.setSelectedIndex(combo.getItemCount() - 2); } } }); } private void editReasons() { String currentReasons = settings.getString("banReasons"); String editedReasons = settingEditor.showDialog( "Edit Preset Ban Reasons (one per line):", currentReasons, null); if (editedReasons != null) { settings.setString("banReasons", editedReasons); updateReasonsFromSettings(); } } public void updateReasonsFromSettings() { String reasons = settings.getString("banReasons"); if (reasons.equals(currentReasons)) { return; } String[] split = reasons.split("\n"); combo.removeAllItems(); // combo.add("", "Select a Ban Reason (optional) [R]"); combo.add("", "Select a Ban Reason (optional)"); for (int i=0;i<split.length;i++) { if (!split[i].trim().isEmpty()) { String shortcut = "-"; if (codes.length > i) { shortcut = KeyEvent.getKeyText(codes[i]); } combo.add(split[i], "["+shortcut+"] "+split[i]); } } combo.add("[C] Non-preset reason:"); currentReasons = reasons; } public String getSelectedReason() { int index = combo.getSelectedIndex(); if (index == 0 || index == -1) { return ""; } if (index == combo.getItemCount() - 1) { return customReasonInput.getText(); } return combo.getSettingValue(); } public void reset() { if (combo.getItemCount() > 0) { combo.setSelectedIndex(0); } } public void addCustomInput() { add(customReasonInput, customInputGbc); revalidate(); customReasonInput.requestFocusInWindow(); customReasonInput.setSelectionStart(0); customReasonInput.setSelectionEnd(customReasonInput.getText().length()); } public void removeCustomInput() { remove(customReasonInput); revalidate(); } }