From ac3f3e8385b08a13ea72c7bdca62234bc18aef35 Mon Sep 17 00:00:00 2001 From: Skylot Date: Sun, 31 May 2015 16:12:54 +0300 Subject: [PATCH] gui: add common popup actions for text fields. --- .../src/main/java/jadx/gui/ui/SearchBar.java | 2 + .../main/java/jadx/gui/ui/SearchDialog.java | 1 + .../jadx/gui/utils/TextStandardActions.java | 154 ++++++++++++++++++ .../resources/i18n/Messages_en_US.properties | 8 + 4 files changed, 165 insertions(+) create mode 100644 jadx-gui/src/main/java/jadx/gui/utils/TextStandardActions.java diff --git a/jadx-gui/src/main/java/jadx/gui/ui/SearchBar.java b/jadx-gui/src/main/java/jadx/gui/ui/SearchBar.java index 227bed7c0..d8ff5fa2c 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/SearchBar.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/SearchBar.java @@ -1,5 +1,6 @@ package jadx.gui.ui; +import jadx.gui.utils.TextStandardActions; import jadx.gui.utils.NLS; import jadx.gui.utils.Utils; @@ -73,6 +74,7 @@ class SearchBar extends JToolBar { search(1); } }); + new TextStandardActions(searchField); add(searchField); JButton prevButton = new JButton(NLS.str("search.previous")); diff --git a/jadx-gui/src/main/java/jadx/gui/ui/SearchDialog.java b/jadx-gui/src/main/java/jadx/gui/ui/SearchDialog.java index 456245073..82c77dc4f 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/SearchDialog.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/SearchDialog.java @@ -236,6 +236,7 @@ public class SearchDialog extends JDialog { searchField = new JTextField(); searchField.setAlignmentX(LEFT_ALIGNMENT); searchField.getDocument().addDocumentListener(new SearchFieldListener()); + new TextStandardActions(searchField); JCheckBox clsChBox = makeOptionsCheckBox(NLS.str("search_dialog.class"), SearchOptions.CLASS); JCheckBox mthChBox = makeOptionsCheckBox(NLS.str("search_dialog.method"), SearchOptions.METHOD); diff --git a/jadx-gui/src/main/java/jadx/gui/utils/TextStandardActions.java b/jadx-gui/src/main/java/jadx/gui/utils/TextStandardActions.java new file mode 100644 index 000000000..11d843ea6 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/utils/TextStandardActions.java @@ -0,0 +1,154 @@ +package jadx.gui.utils; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; +import javax.swing.event.UndoableEditEvent; +import javax.swing.event.UndoableEditListener; +import javax.swing.text.JTextComponent; +import javax.swing.undo.UndoManager; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +@SuppressWarnings("serial") +public class TextStandardActions { + + private final JTextComponent textComponent; + + private final JPopupMenu popup = new JPopupMenu(); + private final UndoManager undoManager; + + private Action undoAction; + private Action redoAction; + private Action cutAction; + private Action copyAction; + private Action pasteAction; + private Action deleteAction; + private Action selectAllAction; + + public TextStandardActions(JTextComponent textComponent) { + this.textComponent = textComponent; + this.undoManager = new UndoManager(); + + initActions(); + addPopupItems(); + addKeyActions(); + + registerListeners(); + } + + private void initActions() { + undoAction = new AbstractAction(NLS.str("popup.undo")) { + @Override + public void actionPerformed(ActionEvent ae) { + if (undoManager.canUndo()) { + undoManager.undo(); + } + } + }; + redoAction = new AbstractAction(NLS.str("popup.redo")) { + @Override + public void actionPerformed(ActionEvent ae) { + if (undoManager.canRedo()) { + undoManager.redo(); + } + } + }; + cutAction = new AbstractAction(NLS.str("popup.cut")) { + @Override + public void actionPerformed(ActionEvent ae) { + textComponent.cut(); + } + }; + copyAction = new AbstractAction(NLS.str("popup.copy")) { + @Override + public void actionPerformed(ActionEvent ae) { + textComponent.copy(); + } + }; + pasteAction = new AbstractAction(NLS.str("popup.paste")) { + @Override + public void actionPerformed(ActionEvent ae) { + textComponent.paste(); + } + }; + deleteAction = new AbstractAction(NLS.str("popup.delete")) { + @Override + public void actionPerformed(ActionEvent ae) { + textComponent.replaceSelection(""); + } + }; + selectAllAction = new AbstractAction(NLS.str("popup.select_all")) { + @Override + public void actionPerformed(ActionEvent ae) { + textComponent.selectAll(); + } + }; + } + + void addPopupItems() { + popup.add(undoAction); + popup.add(redoAction); + popup.addSeparator(); + popup.add(cutAction); + popup.add(copyAction); + popup.add(pasteAction); + popup.add(deleteAction); + popup.addSeparator(); + popup.add(selectAllAction); + } + + private void addKeyActions() { + KeyStroke undoKey = KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK); + textComponent.getInputMap().put(undoKey, undoAction); + KeyStroke redoKey = KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK); + textComponent.getInputMap().put(redoKey, redoAction); + } + + private void registerListeners() { + textComponent.addMouseListener(new MouseAdapter() { + public void mouseReleased(MouseEvent e) { + if (e.getModifiers() == InputEvent.BUTTON3_MASK + && e.getSource() == textComponent) { + process(e); + } + } + }); + textComponent.getDocument().addUndoableEditListener(new UndoableEditListener() { + public void undoableEditHappened(UndoableEditEvent event) { + undoManager.addEdit(event.getEdit()); + } + }); + } + + private void process(MouseEvent e) { + textComponent.requestFocus(); + + boolean enabled = textComponent.isEnabled(); + boolean editable = textComponent.isEditable(); + boolean nonempty = !(textComponent.getText() == null || textComponent.getText().equals("")); + boolean marked = textComponent.getSelectedText() != null; + boolean pasteAvailable = Toolkit.getDefaultToolkit().getSystemClipboard() + .getContents(null).isDataFlavorSupported(DataFlavor.stringFlavor); + + undoAction.setEnabled(enabled && editable && undoManager.canUndo()); + redoAction.setEnabled(enabled && editable && undoManager.canRedo()); + cutAction.setEnabled(enabled && editable && marked); + copyAction.setEnabled(enabled && marked); + pasteAction.setEnabled(enabled && editable && pasteAvailable); + deleteAction.setEnabled(enabled && editable && marked); + selectAllAction.setEnabled(enabled && nonempty); + + int nx = e.getX(); + if (nx > 500) { + nx = nx - popup.getSize().width; + } + popup.show(e.getComponent(), nx, e.getY() - popup.getSize().height); + } +} diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 958db49cd..7ab25d097 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -68,3 +68,11 @@ preferences.cancel=Cancel msg.open_file=Please open file msg.saving_sources=Saving sources + +popup.undo=Undo +popup.redo=Redo +popup.cut=Cut +popup.copy=Copy +popup.paste=Paste +popup.delete=Delete +popup.select_all=Select All