未验证 提交 d3a0a56b 编写于 作者: S Skylot

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

上级 3c2c198a
...@@ -110,6 +110,7 @@ import jadx.gui.treemodel.JNode; ...@@ -110,6 +110,7 @@ import jadx.gui.treemodel.JNode;
import jadx.gui.treemodel.JPackage; import jadx.gui.treemodel.JPackage;
import jadx.gui.treemodel.JResource; import jadx.gui.treemodel.JResource;
import jadx.gui.treemodel.JRoot; import jadx.gui.treemodel.JRoot;
import jadx.gui.ui.codearea.AbstractCodeArea;
import jadx.gui.ui.codearea.AbstractCodeContentPanel; import jadx.gui.ui.codearea.AbstractCodeContentPanel;
import jadx.gui.ui.codearea.EditorViewState; import jadx.gui.ui.codearea.EditorViewState;
import jadx.gui.ui.dialog.ADBDialog; import jadx.gui.ui.dialog.ADBDialog;
...@@ -936,7 +937,11 @@ public class MainWindow extends JFrame { ...@@ -936,7 +937,11 @@ public class MainWindow extends JFrame {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
ContentPanel panel = tabbedPane.getSelectedCodePanel(); ContentPanel panel = tabbedPane.getSelectedCodePanel();
if (panel instanceof AbstractCodeContentPanel) { 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)) { if (!StringUtils.isEmpty(preferText)) {
SearchDialog.searchText(MainWindow.this, preferText); SearchDialog.searchText(MainWindow.this, preferText);
return; return;
......
...@@ -6,6 +6,8 @@ import java.awt.Rectangle; ...@@ -6,6 +6,8 @@ import java.awt.Rectangle;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.event.FocusListener; import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
...@@ -37,6 +39,7 @@ import jadx.gui.ui.panel.ContentPanel; ...@@ -37,6 +39,7 @@ import jadx.gui.ui.panel.ContentPanel;
import jadx.gui.utils.DefaultPopupMenuListener; import jadx.gui.utils.DefaultPopupMenuListener;
import jadx.gui.utils.JumpPosition; import jadx.gui.utils.JumpPosition;
import jadx.gui.utils.NLS; import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
public abstract class AbstractCodeArea extends RSyntaxTextArea { public abstract class AbstractCodeArea extends RSyntaxTextArea {
private static final long serialVersionUID = -3980354865216031972L; private static final long serialVersionUID = -3980354865216031972L;
...@@ -57,9 +60,16 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea { ...@@ -57,9 +60,16 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
setCloseCurlyBraces(true); setCloseCurlyBraces(true);
setAntiAliasingEnabled(true); setAntiAliasingEnabled(true);
loadSettings(); loadSettings();
JadxSettings settings = contentPanel.getTabbedPane().getMainWindow().getSettings(); JadxSettings settings = contentPanel.getTabbedPane().getMainWindow().getSettings();
setLineWrap(settings.isCodeAreaLineWrap()); setLineWrap(settings.isCodeAreaLineWrap());
addWrapLineMenuAction(settings);
addCaretActions();
addFastCopyAction();
}
private void addWrapLineMenuAction(JadxSettings settings) {
JPopupMenu popupMenu = getPopupMenu(); JPopupMenu popupMenu = getPopupMenu();
popupMenu.addSeparator(); popupMenu.addSeparator();
JCheckBoxMenuItem wrapItem = new JCheckBoxMenuItem(NLS.str("popup.line_wrap"), getLineWrap()); JCheckBoxMenuItem wrapItem = new JCheckBoxMenuItem(NLS.str("popup.line_wrap"), getLineWrap());
...@@ -88,7 +98,16 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea { ...@@ -88,7 +98,16 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
wrapItem.setState(getLineWrap()); wrapItem.setState(getLineWrap());
} }
}); });
}
private void setCodeAreaLineWrap(AbstractCodeArea codeArea, boolean wrap) {
codeArea.setLineWrap(wrap);
if (codeArea.isVisible()) {
codeArea.repaint();
}
}
private void addCaretActions() {
Caret caret = getCaret(); Caret caret = getCaret();
if (caret instanceof DefaultCaret) { if (caret instanceof DefaultCaret) {
((DefaultCaret) caret).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); ((DefaultCaret) caret).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
...@@ -123,11 +142,20 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea { ...@@ -123,11 +142,20 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
}); });
} }
private void setCodeAreaLineWrap(AbstractCodeArea codeArea, boolean wrap) { /**
codeArea.setLineWrap(wrap); * Ctrl+C will copy highlighted word
if (codeArea.isVisible()) { */
codeArea.repaint(); 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) { private String highlightCaretWord(String lastText, int pos) {
......
package jadx.gui.ui.codearea; 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.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.*; import java.util.*;
...@@ -29,6 +26,7 @@ import jadx.gui.treemodel.JField; ...@@ -29,6 +26,7 @@ import jadx.gui.treemodel.JField;
import jadx.gui.treemodel.JMethod; import jadx.gui.treemodel.JMethod;
import jadx.gui.treemodel.JNode; import jadx.gui.treemodel.JNode;
import jadx.gui.utils.NLS; import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
import static javax.swing.KeyStroke.getKeyStroke; import static javax.swing.KeyStroke.getKeyStroke;
...@@ -62,9 +60,7 @@ public final class FridaAction extends JNodeMenuAction<JNode> { ...@@ -62,9 +60,7 @@ public final class FridaAction extends JNodeMenuAction<JNode> {
try { try {
String fridaSnippet = generateFridaSnippet(); String fridaSnippet = generateFridaSnippet();
LOG.info("Frida snippet:\n{}", fridaSnippet); LOG.info("Frida snippet:\n{}", fridaSnippet);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); UiUtils.copyToClipboard(fridaSnippet);
StringSelection selection = new StringSelection(fridaSnippet);
clipboard.setContents(selection, selection);
} catch (Exception e) { } catch (Exception e) {
LOG.error("Failed to generate Frida code snippet", e); LOG.error("Failed to generate Frida code snippet", e);
JOptionPane.showMessageDialog(codeArea.getMainWindow(), e.getLocalizedMessage(), NLS.str("error_dialog.title"), JOptionPane.showMessageDialog(codeArea.getMainWindow(), e.getLocalizedMessage(), NLS.str("error_dialog.title"),
......
package jadx.gui.ui.codearea; 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.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.List; import java.util.List;
...@@ -25,6 +22,7 @@ import jadx.gui.treemodel.JClass; ...@@ -25,6 +22,7 @@ import jadx.gui.treemodel.JClass;
import jadx.gui.treemodel.JMethod; import jadx.gui.treemodel.JMethod;
import jadx.gui.treemodel.JNode; import jadx.gui.treemodel.JNode;
import jadx.gui.utils.NLS; import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
import static javax.swing.KeyStroke.getKeyStroke; import static javax.swing.KeyStroke.getKeyStroke;
...@@ -55,9 +53,7 @@ public class XposedAction extends JNodeMenuAction<JNode> { ...@@ -55,9 +53,7 @@ public class XposedAction extends JNodeMenuAction<JNode> {
try { try {
String xposedSnippet = generateXposedSnippet(); String xposedSnippet = generateXposedSnippet();
LOG.info("Xposed snippet:\n{}", xposedSnippet); LOG.info("Xposed snippet:\n{}", xposedSnippet);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); UiUtils.copyToClipboard(xposedSnippet);
StringSelection selection = new StringSelection(xposedSnippet);
clipboard.setContents(selection, selection);
} catch (Exception e) { } catch (Exception e) {
LOG.error("Failed to generate Xposed code snippet", e); LOG.error("Failed to generate Xposed code snippet", e);
JOptionPane.showMessageDialog(codeArea.getMainWindow(), e.getLocalizedMessage(), NLS.str("error_dialog.title"), JOptionPane.showMessageDialog(codeArea.getMainWindow(), e.getLocalizedMessage(), NLS.str("error_dialog.title"),
......
...@@ -32,6 +32,7 @@ import com.formdev.flatlaf.extras.FlatSVGIcon; ...@@ -32,6 +32,7 @@ import com.formdev.flatlaf.extras.FlatSVGIcon;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.utils.StringUtils;
import jadx.core.utils.Utils; import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.ui.codearea.AbstractCodeArea; import jadx.gui.ui.codearea.AbstractCodeArea;
...@@ -253,6 +254,10 @@ public class UiUtils { ...@@ -253,6 +254,10 @@ public class UiUtils {
return CTRL_BNT_KEY; 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) { public static <T extends Window & RootPaneContainer> void addEscapeShortCutToDispose(T window) {
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
window.getRootPane().registerKeyboardAction(e -> window.dispose(), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW); window.getRootPane().registerKeyboardAction(e -> window.dispose(), stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
...@@ -296,4 +301,17 @@ public class UiUtils { ...@@ -296,4 +301,17 @@ public class UiUtils {
JOptionPane.showMessageDialog(parent, message, JOptionPane.showMessageDialog(parent, message,
NLS.str("message.errorTitle"), JOptionPane.ERROR_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);
}
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册