Commit b6befbdc authored by Skylot's avatar Skylot

gui: initial tabbed ui implementation

parent 2cfc208a
...@@ -7,16 +7,20 @@ import jadx.gui.utils.NLS; ...@@ -7,16 +7,20 @@ import jadx.gui.utils.NLS;
import jadx.gui.utils.Utils; import jadx.gui.utils.Utils;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu; import javax.swing.JMenu;
import javax.swing.JMenuBar; import javax.swing.JMenuBar;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JSplitPane; import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton; import javax.swing.JToggleButton;
import javax.swing.JToolBar; import javax.swing.JToolBar;
import javax.swing.JTree; import javax.swing.JTree;
...@@ -25,6 +29,7 @@ import javax.swing.ProgressMonitor; ...@@ -25,6 +29,7 @@ import javax.swing.ProgressMonitor;
import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.text.BadLocationException; import javax.swing.text.BadLocationException;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeCellRenderer;
...@@ -40,6 +45,8 @@ import java.awt.event.ActionListener; ...@@ -40,6 +45,8 @@ import java.awt.event.ActionListener;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.io.File; import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
...@@ -63,15 +70,13 @@ public class MainWindow extends JFrame { ...@@ -63,15 +70,13 @@ public class MainWindow extends JFrame {
private static final ImageIcon ICON_FLAT_PKG = Utils.openIcon("empty_logical_package_obj"); private static final ImageIcon ICON_FLAT_PKG = Utils.openIcon("empty_logical_package_obj");
private static final ImageIcon ICON_SEARCH = Utils.openIcon("magnifier"); private static final ImageIcon ICON_SEARCH = Utils.openIcon("magnifier");
private static final File WORK_DIR = new File(System.getProperty("user.dir"));
private final JadxWrapper wrapper; private final JadxWrapper wrapper;
private JPanel mainPanel; private JPanel mainPanel;
private JTree tree; private JTree tree;
private final JTabbedPane tabbedPane = new JTabbedPane();
private DefaultTreeModel treeModel; private DefaultTreeModel treeModel;
private RSyntaxTextArea textArea; private Map<JClass, Integer> openTabs = new HashMap<JClass, Integer>();
private JToolBar searchToolBar;
private SearchBar searchBar;
public MainWindow(JadxWrapper wrapper) { public MainWindow(JadxWrapper wrapper) {
this.wrapper = wrapper; this.wrapper = wrapper;
...@@ -85,7 +90,6 @@ public class MainWindow extends JFrame { ...@@ -85,7 +90,6 @@ public class MainWindow extends JFrame {
fileChooser.setAcceptAllFileFilterUsed(true); fileChooser.setAcceptAllFileFilterUsed(true);
fileChooser.setFileFilter(new FileNameExtensionFilter("supported files", "dex", "apk", "jar")); fileChooser.setFileFilter(new FileNameExtensionFilter("supported files", "dex", "apk", "jar"));
fileChooser.setToolTipText(NLS.str("file.open")); fileChooser.setToolTipText(NLS.str("file.open"));
// fileChooser.setCurrentDirectory(WORK_DIR);
int ret = fileChooser.showDialog(mainPanel, NLS.str("file.open")); int ret = fileChooser.showDialog(mainPanel, NLS.str("file.open"));
if (ret == JFileChooser.APPROVE_OPTION) { if (ret == JFileChooser.APPROVE_OPTION) {
openFile(fileChooser.getSelectedFile()); openFile(fileChooser.getSelectedFile());
...@@ -129,6 +133,7 @@ public class MainWindow extends JFrame { ...@@ -129,6 +133,7 @@ public class MainWindow extends JFrame {
} }
private void toggleSearch() { private void toggleSearch() {
SearchBar searchBar = getSearchBar((JPanel) tabbedPane.getSelectedComponent());
searchBar.toggle(); searchBar.toggle();
} }
...@@ -137,16 +142,100 @@ public class MainWindow extends JFrame { ...@@ -137,16 +142,100 @@ public class MainWindow extends JFrame {
if (obj instanceof JNode) { if (obj instanceof JNode) {
JNode node = (JNode) obj; JNode node = (JNode) obj;
if (node.getJParent() != null) { if (node.getJParent() != null) {
textArea.setText(node.getJParent().getCode()); showCode(node.getJParent(), node.getLine());
scrollToLine(node.getLine());
} else if (node.getClass() == JClass.class) { } else if (node.getClass() == JClass.class) {
textArea.setText(((JClass) node).getCode()); showCode((JClass) node, node.getLine());
scrollToLine(node.getLine()); }
}
}
private JPanel newCodePane() {
RSyntaxTextArea textArea = new RSyntaxTextArea();
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
textArea.setMarkOccurrences(true);
textArea.setBackground(BACKGROUND);
textArea.setCodeFoldingEnabled(true);
textArea.setAntiAliasingEnabled(true);
// textArea.setEditable(false);
// textArea.setHyperlinksEnabled(true);
textArea.setTabSize(4);
RTextScrollPane scrollPane = new RTextScrollPane(textArea);
scrollPane.setFoldIndicatorEnabled(true);
JPanel textPanel = new JPanel(new BorderLayout());
SearchBar searchBar = new SearchBar(textArea);
textPanel.add(searchBar, BorderLayout.NORTH);
textPanel.add(scrollPane);
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK);
Utils.addKeyBinding(textArea, key, "SearchAction", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
toggleSearch();
} }
});
return textPanel;
}
private SearchBar getSearchBar(JPanel panel) {
return (SearchBar) panel.getComponent(0);
}
private JTextArea getTextArea(JPanel panel) {
RTextScrollPane scrollPane = (RTextScrollPane) panel.getComponent(1);
return scrollPane.getTextArea();
}
private void showCode(JClass cls, int line) {
JPanel panel;
if (openTabs.containsKey(cls)) {
int id = openTabs.get(cls);
panel = (JPanel) tabbedPane.getComponentAt(id);
tabbedPane.setSelectedIndex(id);
} else {
panel = newCodePane();
tabbedPane.add(panel);
int id = tabbedPane.getTabCount() - 1;
openTabs.put(cls, id);
tabbedPane.setSelectedIndex(id);
tabbedPane.setTabComponentAt(id, makeTabComponent(cls, panel));
}
if (panel != null) {
JTextArea textArea = getTextArea(panel);
textArea.setText(cls.getCode());
scrollToLine(textArea, line);
} }
} }
private void scrollToLine(int line) { private Component makeTabComponent(final JClass cls, final Component comp) {
String name = cls.getCls().getFullName();
JPanel p = new JPanel();
JLabel label = new JLabel(name);
p.add(label);
JButton button = new JButton();
button.setIcon(ICON_CLOSE);
final int size = 12;
button.setPreferredSize(new Dimension(size, size));
button.setToolTipText("Close");
button.setUI(new BasicButtonUI());
button.setContentAreaFilled(false);
button.setFocusable(false);
button.setBorder(BorderFactory.createEtchedBorder());
button.setBorderPainted(false);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tabbedPane.remove(comp);
openTabs.remove(cls);
}
});
p.add(button);
p.doLayout();
return p;
}
private void scrollToLine(JTextArea textArea, int line) {
if (line < 2) { if (line < 2) {
return; return;
} }
...@@ -233,14 +322,6 @@ public class MainWindow extends JFrame { ...@@ -233,14 +322,6 @@ public class MainWindow extends JFrame {
searchButton.setToolTipText(NLS.str("search")); searchButton.setToolTipText(NLS.str("search"));
toolbar.add(searchButton); toolbar.add(searchButton);
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK);
Utils.addKeyBinding(textArea, key, "SearchAction", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
toggleSearch();
}
});
toolbar.addSeparator(); toolbar.addSeparator();
mainPanel.add(toolbar, BorderLayout.NORTH); mainPanel.add(toolbar, BorderLayout.NORTH);
...@@ -255,8 +336,6 @@ public class MainWindow extends JFrame { ...@@ -255,8 +336,6 @@ public class MainWindow extends JFrame {
DefaultMutableTreeNode treeRoot = new DefaultMutableTreeNode("Please open file"); DefaultMutableTreeNode treeRoot = new DefaultMutableTreeNode("Please open file");
treeModel = new DefaultTreeModel(treeRoot); treeModel = new DefaultTreeModel(treeRoot);
tree = new JTree(treeModel); tree = new JTree(treeModel);
// tree.setRootVisible(false);
// tree.setBackground(BACKGROUND);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(new TreeSelectionListener() { tree.addTreeSelectionListener(new TreeSelectionListener() {
@Override @Override
...@@ -281,24 +360,8 @@ public class MainWindow extends JFrame { ...@@ -281,24 +360,8 @@ public class MainWindow extends JFrame {
JScrollPane treeScrollPane = new JScrollPane(tree); JScrollPane treeScrollPane = new JScrollPane(tree);
splitPane.setLeftComponent(treeScrollPane); splitPane.setLeftComponent(treeScrollPane);
textArea = new RSyntaxTextArea(); tabbedPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); splitPane.setRightComponent(tabbedPane);
textArea.setMarkOccurrences(true);
textArea.setBackground(BACKGROUND);
textArea.setCodeFoldingEnabled(true);
textArea.setAntiAliasingEnabled(true);
textArea.setEditable(false);
// textArea.setHyperlinksEnabled(true);
textArea.setTabSize(4);
RTextScrollPane scrollPane = new RTextScrollPane(textArea);
scrollPane.setFoldIndicatorEnabled(true);
JPanel textPanel = new JPanel(new BorderLayout());
searchBar = new SearchBar(textArea);
textPanel.add(searchBar.getToolBar(), BorderLayout.NORTH);
textPanel.add(scrollPane);
splitPane.setRightComponent(textPanel);
setContentPane(mainPanel); setContentPane(mainPanel);
setTitle(DEFAULT_TITLE); setTitle(DEFAULT_TITLE);
......
...@@ -20,7 +20,7 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; ...@@ -20,7 +20,7 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rtextarea.SearchContext; import org.fife.ui.rtextarea.SearchContext;
import org.fife.ui.rtextarea.SearchEngine; import org.fife.ui.rtextarea.SearchEngine;
public class SearchBar { public class SearchBar extends JToolBar {
private static final Color COLOR_BG_ERROR = new Color(0xFFDFDE); private static final Color COLOR_BG_ERROR = new Color(0xFFDFDE);
private static final Color COLOR_BG_WARN = new Color(0xFFFDD9); private static final Color COLOR_BG_WARN = new Color(0xFFFDD9);
private static final Color COLOR_BG_NORMAL = new Color(0xFFFFFF); private static final Color COLOR_BG_NORMAL = new Color(0xFFFFFF);
...@@ -30,7 +30,6 @@ public class SearchBar { ...@@ -30,7 +30,6 @@ public class SearchBar {
private static final Icon ICON_CLOSE = Utils.openIcon("cross"); private static final Icon ICON_CLOSE = Utils.openIcon("cross");
private final RSyntaxTextArea rTextArea; private final RSyntaxTextArea rTextArea;
private final JToolBar toolBar;
private final JTextField searchField; private final JTextField searchField;
private final JCheckBox markAllCB; private final JCheckBox markAllCB;
...@@ -41,10 +40,9 @@ public class SearchBar { ...@@ -41,10 +40,9 @@ public class SearchBar {
public SearchBar(RSyntaxTextArea textArea) { public SearchBar(RSyntaxTextArea textArea) {
rTextArea = textArea; rTextArea = textArea;
toolBar = new JToolBar();
JLabel findLabel = new JLabel(NLS.str("search.find") + ":"); JLabel findLabel = new JLabel(NLS.str("search.find") + ":");
toolBar.add(findLabel); add(findLabel);
searchField = new JTextField(30); searchField = new JTextField(30);
searchField.addKeyListener(new KeyListener() { searchField.addKeyListener(new KeyListener() {
...@@ -76,7 +74,7 @@ public class SearchBar { ...@@ -76,7 +74,7 @@ public class SearchBar {
search(1); search(1);
} }
}); });
toolBar.add(searchField); add(searchField);
JButton prevButton = new JButton(NLS.str("search.previous")); JButton prevButton = new JButton(NLS.str("search.previous"));
prevButton.setIcon(ICON_UP); prevButton.setIcon(ICON_UP);
...@@ -86,7 +84,7 @@ public class SearchBar { ...@@ -86,7 +84,7 @@ public class SearchBar {
search(-1); search(-1);
} }
}); });
toolBar.add(prevButton); add(prevButton);
JButton nextButton = new JButton(NLS.str("search.next")); JButton nextButton = new JButton(NLS.str("search.next"));
nextButton.setIcon(ICON_DOWN); nextButton.setIcon(ICON_DOWN);
...@@ -96,23 +94,23 @@ public class SearchBar { ...@@ -96,23 +94,23 @@ public class SearchBar {
search(1); search(1);
} }
}); });
toolBar.add(nextButton); add(nextButton);
markAllCB = new JCheckBox(NLS.str("search.mark_all")); markAllCB = new JCheckBox(NLS.str("search.mark_all"));
markAllCB.addActionListener(new ForwardListener()); markAllCB.addActionListener(new ForwardListener());
toolBar.add(markAllCB); add(markAllCB);
regexCB = new JCheckBox(NLS.str("search.regex")); regexCB = new JCheckBox(NLS.str("search.regex"));
regexCB.addActionListener(new ForwardListener()); regexCB.addActionListener(new ForwardListener());
toolBar.add(regexCB); add(regexCB);
matchCaseCB = new JCheckBox(NLS.str("search.match_case")); matchCaseCB = new JCheckBox(NLS.str("search.match_case"));
matchCaseCB.addActionListener(new ForwardListener()); matchCaseCB.addActionListener(new ForwardListener());
toolBar.add(matchCaseCB); add(matchCaseCB);
wholeWordCB = new JCheckBox(NLS.str("search.whole_word")); wholeWordCB = new JCheckBox(NLS.str("search.whole_word"));
wholeWordCB.addActionListener(new ForwardListener()); wholeWordCB.addActionListener(new ForwardListener());
toolBar.add(wholeWordCB); add(wholeWordCB);
JButton closeButton = new JButton(); JButton closeButton = new JButton();
closeButton.setIcon(ICON_CLOSE); closeButton.setIcon(ICON_CLOSE);
...@@ -122,22 +120,19 @@ public class SearchBar { ...@@ -122,22 +120,19 @@ public class SearchBar {
toggle(); toggle();
} }
}); });
toolBar.add(closeButton); add(closeButton);
toolBar.setFloatable(false); setFloatable(false);
toolBar.setVisible(false); setVisible(false);
}
public JToolBar getToolBar() {
return toolBar;
} }
public boolean toggle() { public boolean toggle() {
boolean visible = !toolBar.isVisible(); boolean visible = !isVisible();
toolBar.setVisible(visible); setVisible(visible);
if (visible) { if (visible) {
searchField.requestFocus(); searchField.requestFocus();
searchField.selectAll();
} else { } else {
rTextArea.requestFocus(); rTextArea.requestFocus();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment