feat(gui): ctrl+c copy highlighted word in code view (#1292)

This commit is contained in:
Skylot
2022-02-18 18:00:14 +00:00
parent 3c2c198a0e
commit d3a0a56b8b
5 changed files with 61 additions and 18 deletions
@@ -110,6 +110,7 @@ import jadx.gui.treemodel.JNode;
import jadx.gui.treemodel.JPackage;
import jadx.gui.treemodel.JResource;
import jadx.gui.treemodel.JRoot;
import jadx.gui.ui.codearea.AbstractCodeArea;
import jadx.gui.ui.codearea.AbstractCodeContentPanel;
import jadx.gui.ui.codearea.EditorViewState;
import jadx.gui.ui.dialog.ADBDialog;
@@ -936,7 +937,11 @@ public class MainWindow extends JFrame {
public void actionPerformed(ActionEvent e) {
ContentPanel panel = tabbedPane.getSelectedCodePanel();
if (panel instanceof AbstractCodeContentPanel) {
String preferText = ((AbstractCodeContentPanel) panel).getCodeArea().getSelectedText();
AbstractCodeArea codeArea = ((AbstractCodeContentPanel) panel).getCodeArea();
String preferText = codeArea.getSelectedText();
if (StringUtils.isEmpty(preferText)) {
preferText = codeArea.getWordUnderCaret();
}
if (!StringUtils.isEmpty(preferText)) {
SearchDialog.searchText(MainWindow.this, preferText);
return;
@@ -6,6 +6,8 @@ import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@@ -37,6 +39,7 @@ import jadx.gui.ui.panel.ContentPanel;
import jadx.gui.utils.DefaultPopupMenuListener;
import jadx.gui.utils.JumpPosition;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
public abstract class AbstractCodeArea extends RSyntaxTextArea {
private static final long serialVersionUID = -3980354865216031972L;
@@ -57,9 +60,16 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
setCloseCurlyBraces(true);
setAntiAliasingEnabled(true);
loadSettings();
JadxSettings settings = contentPanel.getTabbedPane().getMainWindow().getSettings();
setLineWrap(settings.isCodeAreaLineWrap());
addWrapLineMenuAction(settings);
addCaretActions();
addFastCopyAction();
}
private void addWrapLineMenuAction(JadxSettings settings) {
JPopupMenu popupMenu = getPopupMenu();
popupMenu.addSeparator();
JCheckBoxMenuItem wrapItem = new JCheckBoxMenuItem(NLS.str("popup.line_wrap"), getLineWrap());
@@ -88,7 +98,16 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
wrapItem.setState(getLineWrap());
}
});
}
private void setCodeAreaLineWrap(AbstractCodeArea codeArea, boolean wrap) {
codeArea.setLineWrap(wrap);
if (codeArea.isVisible()) {
codeArea.repaint();
}
}
private void addCaretActions() {
Caret caret = getCaret();
if (caret instanceof DefaultCaret) {
((DefaultCaret) caret).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
@@ -123,11 +142,20 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
});
}
private void setCodeAreaLineWrap(AbstractCodeArea codeArea, boolean wrap) {
codeArea.setLineWrap(wrap);
if (codeArea.isVisible()) {
codeArea.repaint();
}
/**
* Ctrl+C will copy highlighted word
*/
private void addFastCopyAction() {
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_C && UiUtils.isCtrlDown(e)) {
if (StringUtils.isEmpty(getSelectedText())) {
UiUtils.copyToClipboard(getWordUnderCaret());
}
}
}
});
}
private String highlightCaretWord(String lastText, int pos) {
@@ -1,8 +1,5 @@
package jadx.gui.ui.codearea;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.*;
@@ -29,6 +26,7 @@ import jadx.gui.treemodel.JField;
import jadx.gui.treemodel.JMethod;
import jadx.gui.treemodel.JNode;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
import static javax.swing.KeyStroke.getKeyStroke;
@@ -62,9 +60,7 @@ public final class FridaAction extends JNodeMenuAction<JNode> {
try {
String fridaSnippet = generateFridaSnippet();
LOG.info("Frida snippet:\n{}", fridaSnippet);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection(fridaSnippet);
clipboard.setContents(selection, selection);
UiUtils.copyToClipboard(fridaSnippet);
} catch (Exception e) {
LOG.error("Failed to generate Frida code snippet", e);
JOptionPane.showMessageDialog(codeArea.getMainWindow(), e.getLocalizedMessage(), NLS.str("error_dialog.title"),
@@ -1,8 +1,5 @@
package jadx.gui.ui.codearea;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.List;
@@ -25,6 +22,7 @@ import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JMethod;
import jadx.gui.treemodel.JNode;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
import static javax.swing.KeyStroke.getKeyStroke;
@@ -55,9 +53,7 @@ public class XposedAction extends JNodeMenuAction<JNode> {
try {
String xposedSnippet = generateXposedSnippet();
LOG.info("Xposed snippet:\n{}", xposedSnippet);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection(xposedSnippet);
clipboard.setContents(selection, selection);
UiUtils.copyToClipboard(xposedSnippet);
} catch (Exception e) {
LOG.error("Failed to generate Xposed code snippet", e);
JOptionPane.showMessageDialog(codeArea.getMainWindow(), e.getLocalizedMessage(), NLS.str("error_dialog.title"),
@@ -32,6 +32,7 @@ import com.formdev.flatlaf.extras.FlatSVGIcon;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.utils.StringUtils;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.ui.codearea.AbstractCodeArea;
@@ -253,6 +254,10 @@ public class UiUtils {
return CTRL_BNT_KEY;
}
public static boolean isCtrlDown(KeyEvent keyEvent) {
return keyEvent.getModifiersEx() == CTRL_BNT_KEY;
}
public static <T extends Window & RootPaneContainer> void addEscapeShortCutToDispose(T window) {
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
window.getRootPane().registerKeyboardAction(e -> window.dispose(), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
@@ -296,4 +301,17 @@ public class UiUtils {
JOptionPane.showMessageDialog(parent, message,
NLS.str("message.errorTitle"), JOptionPane.ERROR_MESSAGE);
}
public static void copyToClipboard(String text) {
if (StringUtils.isEmpty(text)) {
return;
}
try {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection(text);
clipboard.setContents(selection, selection);
} catch (Exception e) {
LOG.error("Failed copy text to clipboard", e);
}
}
}