gui: add log viewer

This commit is contained in:
Skylot
2015-05-31 17:11:46 +03:00
parent ac3f3e8385
commit 129a7c39af
9 changed files with 237 additions and 4 deletions
@@ -3,6 +3,7 @@ package jadx.gui;
import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.JadxSettingsAdapter;
import jadx.gui.ui.MainWindow;
import jadx.gui.utils.LogCollector;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
@@ -15,6 +16,7 @@ public class JadxGUI {
public static void main(String[] args) {
try {
LogCollector.register();
final JadxSettings jadxArgs = JadxSettingsAdapter.load();
// overwrite loaded settings by command line arguments
if (!jadxArgs.processArgs(args)) {
@@ -0,0 +1,108 @@
package jadx.gui.ui;
import ch.qos.logback.classic.Level;
import jadx.gui.utils.LogCollector;
import jadx.gui.utils.NLS;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
class LogViewer extends JDialog {
private static final long serialVersionUID = -2188700277429054641L;
private static final Level[] LEVEL_ITEMS = {Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR};
private static Level level = Level.WARN;
private RSyntaxTextArea textPane;
public LogViewer() {
initUI();
registerLogListener();
}
public final void initUI() {
textPane = new RSyntaxTextArea();
textPane.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
JPanel controlPane = new JPanel();
controlPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JComboBox cb = new JComboBox(LEVEL_ITEMS);
cb.setSelectedItem(level);
cb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int i = cb.getSelectedIndex();
level = LEVEL_ITEMS[i];
registerLogListener();
}
});
JLabel levelLabel = new JLabel(NLS.str("log.level"));
levelLabel.setLabelFor(cb);
controlPane.add(levelLabel);
controlPane.add(cb);
JScrollPane scrollPane = new JScrollPane(textPane);
JButton close = new JButton(NLS.str("tabs.close"));
close.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
close();
}
});
close.setAlignmentX(0.5f);
Container contentPane = getContentPane();
contentPane.add(controlPane, BorderLayout.PAGE_START);
contentPane.add(scrollPane, BorderLayout.CENTER);
contentPane.add(close, BorderLayout.PAGE_END);
setTitle("Log Viewer");
pack();
setSize(800, 600);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setModalityType(ModalityType.MODELESS);
setLocationRelativeTo(null);
}
private void registerLogListener() {
LogCollector logCollector = LogCollector.getInstance();
logCollector.resetListener();
textPane.setText("");
logCollector.registerListener(new LogCollector.ILogListener() {
@Override
public Level getFilterLevel() {
return level;
}
@Override
public void onAppend(final String logStr) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textPane.append(logStr);
textPane.updateUI();
}
});
}
});
}
private void close() {
LogCollector.getInstance().resetListener();
dispose();
}
public static void main(String[] args) {
new LogViewer().setVisible(true);
}
}
@@ -84,6 +84,7 @@ public class MainWindow extends JFrame {
private static final ImageIcon ICON_FORWARD = Utils.openIcon("icon_forward");
private static final ImageIcon ICON_PREF = Utils.openIcon("wrench");
private static final ImageIcon ICON_DEOBF = Utils.openIcon("lock_edit");
private static final ImageIcon ICON_LOG = Utils.openIcon("report");
private final JadxWrapper wrapper;
private final JadxSettings settings;
@@ -375,6 +376,19 @@ public class MainWindow extends JFrame {
};
find.addActionListener(findAction);
JMenu tools = new JMenu(NLS.str("menu.tools"));
tools.setMnemonic(KeyEvent.VK_T);
JMenuItem logItem = new JMenuItem(NLS.str("menu.log"), ICON_LOG);
ActionListener logAction = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new LogViewer().setVisible(true);
}
};
logItem.addActionListener(logAction);
tools.add(logItem);
JMenu help = new JMenu(NLS.str("menu.help"));
help.setMnemonic(KeyEvent.VK_H);
@@ -390,6 +404,7 @@ public class MainWindow extends JFrame {
menuBar.add(file);
menuBar.add(view);
menuBar.add(nav);
menuBar.add(tools);
menuBar.add(help);
setJMenuBar(menuBar);
@@ -470,6 +485,10 @@ public class MainWindow extends JFrame {
}
});
JButton logBtn = new JButton(ICON_LOG);
logBtn.setToolTipText(NLS.str("menu.log"));
logBtn.addActionListener(logAction);
updateLink = new Link("", JadxUpdate.JADX_RELEASES_URL);
updateLink.setVisible(false);
@@ -495,6 +514,9 @@ public class MainWindow extends JFrame {
toolbar.add(deobfToggleBtn);
toolbar.addSeparator();
toolbar.add(logBtn);
toolbar.addSeparator();
toolbar.add(prefButton);
toolbar.addSeparator();
@@ -9,6 +9,7 @@ import jadx.gui.treemodel.JNode;
import jadx.gui.utils.NLS;
import jadx.gui.utils.NameIndex;
import jadx.gui.utils.Position;
import jadx.gui.utils.TextStandardActions;
import javax.swing.BorderFactory;
import javax.swing.Box;
@@ -198,7 +199,7 @@ public class SearchDialog extends JDialog {
@Override
public Component getListCellRendererComponent(JList list,
Object obj, int index, boolean isSelected, boolean cellHasFocus) {
Object obj, int index, boolean isSelected, boolean cellHasFocus) {
if (!(obj instanceof JNode)) {
return null;
}
@@ -317,7 +318,7 @@ public class SearchDialog extends JDialog {
setSize(700, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setModalityType(ModalityType.APPLICATION_MODAL);
setModalityType(ModalityType.MODELESS);
}
private JCheckBox makeOptionsCheckBox(String name, final SearchOptions opt) {
@@ -0,0 +1,92 @@
package jadx.gui.utils;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.read.CyclicBufferAppender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.LoggerFactory;
public class LogCollector extends CyclicBufferAppender<ILoggingEvent> {
private static LogCollector instance = new LogCollector();
public static LogCollector getInstance() {
return instance;
}
public static void register() {
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
LoggerContext loggerContext = rootLogger.getLoggerContext();
PatternLayout layout = new PatternLayout();
layout.setContext(loggerContext);
layout.setPattern("%-5level: %msg%n");
layout.start();
instance.setContext(loggerContext);
instance.setLayout(layout);
instance.start();
rootLogger.addAppender(instance);
}
public interface ILogListener {
Level getFilterLevel();
void onAppend(String logStr);
}
private Layout<ILoggingEvent> layout;
@Nullable
private ILogListener listener;
public LogCollector() {
setName("LogCollector");
setMaxSize(50000);
}
@Override
protected void append(ILoggingEvent event) {
super.append(event);
if (listener != null
&& event.getLevel().isGreaterOrEqual(listener.getFilterLevel())) {
synchronized (this) {
listener.onAppend(layout.doLayout(event));
}
}
}
public void setLayout(Layout<ILoggingEvent> layout) {
this.layout = layout;
}
public void registerListener(@NotNull ILogListener listener) {
this.listener = listener;
synchronized (this) {
listener.onAppend(init(listener.getFilterLevel()));
}
}
public void resetListener() {
this.listener = null;
}
private String init(Level filterLevel) {
StringBuilder sb = new StringBuilder();
int length = getLength();
for (int i = 0; i < length; i++) {
ILoggingEvent event = get(i);
if (event.getLevel().isGreaterOrEqual(filterLevel)) {
sb.append(layout.doLayout(event));
}
}
return sb.toString();
}
}