|
|
|
@@ -1,14 +1,18 @@
|
|
|
|
|
package jadx.gui.ui;
|
|
|
|
|
|
|
|
|
|
import jadx.gui.treemodel.JClass;
|
|
|
|
|
import jadx.gui.utils.NLS;
|
|
|
|
|
import jadx.gui.utils.Utils;
|
|
|
|
|
|
|
|
|
|
import javax.swing.BorderFactory;
|
|
|
|
|
import javax.swing.ImageIcon;
|
|
|
|
|
import javax.swing.JButton;
|
|
|
|
|
import javax.swing.JLabel;
|
|
|
|
|
import javax.swing.JMenuItem;
|
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
|
import javax.swing.JPopupMenu;
|
|
|
|
|
import javax.swing.JTabbedPane;
|
|
|
|
|
import javax.swing.SwingUtilities;
|
|
|
|
|
import javax.swing.plaf.basic.BasicButtonUI;
|
|
|
|
|
import java.awt.Component;
|
|
|
|
|
import java.awt.FlowLayout;
|
|
|
|
@@ -16,51 +20,98 @@ import java.awt.event.ActionEvent;
|
|
|
|
|
import java.awt.event.ActionListener;
|
|
|
|
|
import java.awt.event.MouseAdapter;
|
|
|
|
|
import java.awt.event.MouseEvent;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.awt.event.MouseWheelEvent;
|
|
|
|
|
import java.awt.event.MouseWheelListener;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.LinkedHashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
class TabbedPane extends JTabbedPane {
|
|
|
|
|
|
|
|
|
|
private static final long serialVersionUID = -8833600618794570904L;
|
|
|
|
|
|
|
|
|
|
private static final ImageIcon ICON_CLOSE = Utils.openIcon("cross");
|
|
|
|
|
private static final ImageIcon ICON_CLOSE_INACTIVE = Utils.openIcon("cross_grayed");
|
|
|
|
|
|
|
|
|
|
private final MainWindow mainWindow;
|
|
|
|
|
private final Map<JClass, CodePanel> openTabs = new HashMap<JClass, CodePanel>();
|
|
|
|
|
private final Map<JClass, CodePanel> openTabs = new LinkedHashMap<JClass, CodePanel>();
|
|
|
|
|
|
|
|
|
|
TabbedPane(MainWindow window) {
|
|
|
|
|
mainWindow = window;
|
|
|
|
|
|
|
|
|
|
setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
|
|
|
|
|
|
|
|
|
|
addMouseWheelListener(new MouseWheelListener() {
|
|
|
|
|
public void mouseWheelMoved(MouseWheelEvent e) {
|
|
|
|
|
int direction = e.getWheelRotation();
|
|
|
|
|
int index = getSelectedIndex();
|
|
|
|
|
int maxIndex = getTabCount() - 1;
|
|
|
|
|
if ((index == 0 && direction < 0)
|
|
|
|
|
|| (index == maxIndex && direction > 0)) {
|
|
|
|
|
index = maxIndex - index;
|
|
|
|
|
} else {
|
|
|
|
|
index += direction;
|
|
|
|
|
}
|
|
|
|
|
setSelectedIndex(index);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MainWindow getMainWindow() {
|
|
|
|
|
return mainWindow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void showCode(final JClass cls, final int line) {
|
|
|
|
|
final CodePanel codePanel = getCodePanel(cls);
|
|
|
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
setSelectedComponent(codePanel);
|
|
|
|
|
CodeArea codeArea = codePanel.getCodeArea();
|
|
|
|
|
codeArea.scrollToLine(line);
|
|
|
|
|
codeArea.requestFocus();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void addCodePanel(CodePanel codePanel) {
|
|
|
|
|
add(codePanel);
|
|
|
|
|
openTabs.put(codePanel.getCls(), codePanel);
|
|
|
|
|
add(codePanel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void closeCodePanel(CodePanel codePanel) {
|
|
|
|
|
remove(codePanel);
|
|
|
|
|
openTabs.remove(codePanel.getCls());
|
|
|
|
|
remove(codePanel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void showCode(JClass cls, int line) {
|
|
|
|
|
private CodePanel getCodePanel(JClass cls) {
|
|
|
|
|
CodePanel panel = openTabs.get(cls);
|
|
|
|
|
if (panel == null) {
|
|
|
|
|
panel = new CodePanel(this, cls);
|
|
|
|
|
addCodePanel(panel);
|
|
|
|
|
setTabComponentAt(indexOfComponent(panel), makeTabComponent(panel));
|
|
|
|
|
}
|
|
|
|
|
return panel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setSelectedComponent(panel);
|
|
|
|
|
CodeArea codeArea = panel.getCodeArea();
|
|
|
|
|
codeArea.scrollToLine(line);
|
|
|
|
|
codeArea.requestFocus();
|
|
|
|
|
private CodePanel getCodePanel(int index) {
|
|
|
|
|
Component component = getComponent(index);
|
|
|
|
|
if (component instanceof CodePanel) {
|
|
|
|
|
return (CodePanel) component;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CodePanel getSelectedCodePanel() {
|
|
|
|
|
return (CodePanel) getSelectedComponent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Component makeTabComponent(final CodePanel codePanel) {
|
|
|
|
|
JClass cls = codePanel.getCls();
|
|
|
|
|
String name = cls.getCls().getFullName();
|
|
|
|
|
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 3, 0));
|
|
|
|
|
|
|
|
|
|
final JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 3, 0));
|
|
|
|
|
panel.setOpaque(false);
|
|
|
|
|
|
|
|
|
|
final JLabel label = new JLabel(name);
|
|
|
|
@@ -87,8 +138,11 @@ class TabbedPane extends JTabbedPane {
|
|
|
|
|
panel.addMouseListener(new MouseAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void mouseClicked(MouseEvent e) {
|
|
|
|
|
if (e.getButton() == MouseEvent.BUTTON2) {
|
|
|
|
|
if (SwingUtilities.isMiddleMouseButton(e)) {
|
|
|
|
|
closeCodePanel(codePanel);
|
|
|
|
|
} else if (SwingUtilities.isRightMouseButton(e)) {
|
|
|
|
|
JPopupMenu menu = createTabPopupMenu(codePanel);
|
|
|
|
|
menu.show(panel, e.getX(), e.getY());
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: make correct event delegation to tabbed pane
|
|
|
|
|
setSelectedComponent(codePanel);
|
|
|
|
@@ -102,11 +156,65 @@ class TabbedPane extends JTabbedPane {
|
|
|
|
|
return panel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CodePanel getSelectedCodePanel() {
|
|
|
|
|
return (CodePanel) getSelectedComponent();
|
|
|
|
|
}
|
|
|
|
|
private JPopupMenu createTabPopupMenu(final CodePanel codePanel) {
|
|
|
|
|
JPopupMenu menu = new JPopupMenu();
|
|
|
|
|
|
|
|
|
|
MainWindow getMainWindow() {
|
|
|
|
|
return mainWindow;
|
|
|
|
|
JMenuItem closeTab = new JMenuItem(NLS.str("tabs.close"));
|
|
|
|
|
closeTab.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
|
closeCodePanel(codePanel);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
menu.add(closeTab);
|
|
|
|
|
|
|
|
|
|
if (openTabs.size() > 1) {
|
|
|
|
|
JMenuItem closeOther = new JMenuItem(NLS.str("tabs.closeOthers"));
|
|
|
|
|
closeOther.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
|
List<CodePanel> codePanels = new ArrayList<CodePanel>(openTabs.values());
|
|
|
|
|
for (CodePanel panel : codePanels) {
|
|
|
|
|
if (panel != codePanel) {
|
|
|
|
|
closeCodePanel(panel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
menu.add(closeOther);
|
|
|
|
|
|
|
|
|
|
JMenuItem closeAll = new JMenuItem(NLS.str("tabs.closeAll"));
|
|
|
|
|
closeAll.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
|
List<CodePanel> codePanels = new ArrayList<CodePanel>(openTabs.values());
|
|
|
|
|
for (CodePanel panel : codePanels) {
|
|
|
|
|
closeCodePanel(panel);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
menu.add(closeAll);
|
|
|
|
|
menu.addSeparator();
|
|
|
|
|
|
|
|
|
|
CodePanel selectedCodePanel = getSelectedCodePanel();
|
|
|
|
|
for (final Map.Entry<JClass, CodePanel> entry : openTabs.entrySet()) {
|
|
|
|
|
final CodePanel cp = entry.getValue();
|
|
|
|
|
if (cp == selectedCodePanel) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
JClass jClass = entry.getKey();
|
|
|
|
|
final String clsName = jClass.getCls().getFullName();
|
|
|
|
|
JMenuItem item = new JMenuItem(clsName);
|
|
|
|
|
item.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
|
setSelectedComponent(cp);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
item.setIcon(jClass.getIcon());
|
|
|
|
|
menu.add(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|