2021-06-26 01:13:46 +00:00
|
|
|
package the.bytecode.club.bytecodeviewer.gui.util;
|
2015-11-11 04:16:45 +00:00
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
import java.awt.BorderLayout;
|
|
|
|
import java.awt.Font;
|
|
|
|
import java.awt.event.InputEvent;
|
2021-04-12 22:31:22 +00:00
|
|
|
import java.util.Objects;
|
2021-04-12 20:19:12 +00:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import javax.swing.JComboBox;
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
import javax.swing.JViewport;
|
2019-04-17 06:45:15 +00:00
|
|
|
import javax.swing.event.CaretEvent;
|
|
|
|
import javax.swing.event.CaretListener;
|
|
|
|
import javax.swing.event.ChangeEvent;
|
|
|
|
import javax.swing.event.ChangeListener;
|
2021-04-12 20:19:12 +00:00
|
|
|
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
|
|
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
|
|
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
2021-06-26 01:13:46 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.components.MethodsRenderer;
|
|
|
|
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
|
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
|
2021-04-12 20:19:12 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.util.MethodParser;
|
2019-04-17 06:45:15 +00:00
|
|
|
|
2021-06-26 01:13:46 +00:00
|
|
|
import static the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane.BLANK_COLOR;
|
2019-04-17 06:45:15 +00:00
|
|
|
|
2021-06-26 03:33:06 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
|
|
|
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
|
|
|
|
* *
|
|
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
2015-11-11 04:16:45 +00:00
|
|
|
/**
|
2018-01-31 15:03:53 +00:00
|
|
|
* Allows us to run a background thread
|
2018-01-31 15:41:24 +00:00
|
|
|
*
|
2015-11-11 04:16:45 +00:00
|
|
|
* @author Konloch
|
2019-04-17 06:45:15 +00:00
|
|
|
* @author DreamSworK
|
2015-11-11 04:16:45 +00:00
|
|
|
*/
|
2021-06-26 01:13:46 +00:00
|
|
|
public abstract class PaneUpdaterThread implements Runnable
|
|
|
|
{
|
2019-04-17 06:45:15 +00:00
|
|
|
public ClassViewer viewer;
|
2021-06-26 01:13:46 +00:00
|
|
|
public SearchableRSyntaxTextArea updateUpdaterTextArea;
|
2019-04-17 06:45:15 +00:00
|
|
|
public JComboBox<Integer> methodsList;
|
2021-06-26 01:13:46 +00:00
|
|
|
private Thread thread;
|
|
|
|
public int paneIndex;
|
|
|
|
public int decompilerViewIndex;
|
|
|
|
|
|
|
|
public PaneUpdaterThread(int paneIndex, int decompilerViewIndex)
|
|
|
|
{
|
|
|
|
this.paneIndex = paneIndex;
|
|
|
|
this.decompilerViewIndex = decompilerViewIndex;
|
|
|
|
}
|
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
public abstract void doShit();
|
2021-06-26 01:13:46 +00:00
|
|
|
|
|
|
|
public void startNewThread()
|
|
|
|
{
|
|
|
|
thread = new Thread(this);
|
|
|
|
thread.start();
|
|
|
|
}
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
@Override
|
2021-06-26 01:13:46 +00:00
|
|
|
public void run()
|
|
|
|
{
|
|
|
|
if(decompilerViewIndex == 0)
|
|
|
|
return;
|
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
doShit();
|
2021-06-26 01:13:46 +00:00
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
synchronizePane();
|
2021-06-26 01:13:46 +00:00
|
|
|
|
|
|
|
attachCtrlMouseWheelZoom(updateUpdaterTextArea.getScrollPane(), updateUpdaterTextArea); //freezes the UI for some reason
|
2021-06-22 00:46:57 +00:00
|
|
|
//probably cause BCV is doing dumb shit with the swing thread
|
2019-04-25 21:27:35 +00:00
|
|
|
}
|
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
public void attachCtrlMouseWheelZoom(RTextScrollPane scrollPane, RSyntaxTextArea panelArea) {
|
|
|
|
if (scrollPane == null)
|
2019-04-25 21:27:35 +00:00
|
|
|
return;
|
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
scrollPane.addMouseWheelListener(e -> {
|
|
|
|
if (panelArea == null || panelArea.getText().isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) {
|
|
|
|
Font font = panelArea.getFont();
|
|
|
|
int size = font.getSize();
|
|
|
|
if (e.getWheelRotation() > 0) { //Up
|
|
|
|
panelArea.setFont(new Font(font.getName(), font.getStyle(), --size >= 2 ? --size : 2));
|
|
|
|
} else { //Down
|
|
|
|
panelArea.setFont(new Font(font.getName(), font.getStyle(), ++size));
|
2019-04-25 21:27:35 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-12 22:31:22 +00:00
|
|
|
e.consume();
|
2019-04-25 21:27:35 +00:00
|
|
|
});
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
public final CaretListener caretListener = new CaretListener() {
|
2019-04-17 06:45:15 +00:00
|
|
|
@Override
|
2021-04-12 20:19:12 +00:00
|
|
|
public void caretUpdate(CaretEvent e) {
|
2021-06-26 01:13:46 +00:00
|
|
|
MethodParser methods = viewer.methods.get(paneIndex);
|
2021-04-12 20:19:12 +00:00
|
|
|
if (methods != null) {
|
2021-06-26 01:13:46 +00:00
|
|
|
int methodLine = methods.findActiveMethod(updateUpdaterTextArea.getCaretLineNumber());
|
2021-04-12 20:19:12 +00:00
|
|
|
if (methodLine != -1) {
|
|
|
|
if (BytecodeViewer.viewer.showClassMethods.isSelected()) {
|
|
|
|
if (methodsList != null) {
|
2021-04-12 22:31:22 +00:00
|
|
|
if (methodLine != (int) Objects.requireNonNull(methodsList.getSelectedItem())) {
|
2019-04-17 06:45:15 +00:00
|
|
|
methodsList.setSelectedItem(methodLine);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-12 20:19:12 +00:00
|
|
|
if (BytecodeViewer.viewer.synchronizedViewing.isSelected()) {
|
2019-04-17 06:45:15 +00:00
|
|
|
int panes = 2;
|
2021-06-26 01:13:46 +00:00
|
|
|
if (viewer.resourceViewPanel3.panel != null)
|
2019-04-17 06:45:15 +00:00
|
|
|
panes = 3;
|
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
for (int i = 0; i < panes; i++) {
|
2021-06-26 01:13:46 +00:00
|
|
|
if (i != paneIndex) {
|
2019-04-17 06:45:15 +00:00
|
|
|
ClassViewer.selectMethod(viewer, i, methods.getMethod(methodLine));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public final ChangeListener viewportListener = new ChangeListener() {
|
|
|
|
@Override
|
|
|
|
public void stateChanged(ChangeEvent e) {
|
|
|
|
int panes = 2;
|
2021-06-26 01:13:46 +00:00
|
|
|
if (viewer.resourceViewPanel3.panel != null)
|
2019-04-17 06:45:15 +00:00
|
|
|
panes = 3;
|
|
|
|
|
|
|
|
if (BytecodeViewer.viewer.synchronizedViewing.isSelected()) {
|
2021-06-26 01:13:46 +00:00
|
|
|
if (updateUpdaterTextArea.isShowing() && (updateUpdaterTextArea.hasFocus() || updateUpdaterTextArea.getMousePosition() != null)) {
|
|
|
|
int caretLine = updateUpdaterTextArea.getCaretLineNumber();
|
|
|
|
int maxViewLine = ClassViewer.getMaxViewLine(updateUpdaterTextArea);
|
|
|
|
int activeViewLine = ClassViewer.getViewLine(updateUpdaterTextArea);
|
2021-04-12 20:19:12 +00:00
|
|
|
int activeLine = (activeViewLine == maxViewLine && caretLine > maxViewLine) ? caretLine :
|
|
|
|
activeViewLine;
|
2019-04-17 06:45:15 +00:00
|
|
|
int activeLineDelta = -1;
|
|
|
|
MethodParser.Method activeMethod = null;
|
2021-06-26 01:13:46 +00:00
|
|
|
MethodParser activeMethods = viewer.methods.get(paneIndex);
|
2019-04-17 06:45:15 +00:00
|
|
|
if (activeMethods != null) {
|
|
|
|
int activeMethodLine = activeMethods.findActiveMethod(activeLine);
|
|
|
|
if (activeMethodLine != -1) {
|
|
|
|
activeLineDelta = activeLine - activeMethodLine;
|
|
|
|
activeMethod = activeMethods.getMethod(activeMethodLine);
|
2021-06-26 01:13:46 +00:00
|
|
|
ClassViewer.selectMethod(updateUpdaterTextArea, activeMethodLine);
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < panes; i++) {
|
2021-06-26 01:13:46 +00:00
|
|
|
if (i != paneIndex) {
|
2019-04-17 06:45:15 +00:00
|
|
|
int setLine = -1;
|
|
|
|
|
|
|
|
RSyntaxTextArea area = null;
|
2021-04-12 20:19:12 +00:00
|
|
|
switch (i) {
|
|
|
|
case 0:
|
2021-06-26 01:13:46 +00:00
|
|
|
area = viewer.resourceViewPanel1.updateThread.updateUpdaterTextArea;
|
2021-04-12 20:19:12 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2021-06-26 01:13:46 +00:00
|
|
|
area = viewer.resourceViewPanel2.updateThread.updateUpdaterTextArea;
|
2021-04-12 20:19:12 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2021-06-26 01:13:46 +00:00
|
|
|
area = viewer.resourceViewPanel3.updateThread.updateUpdaterTextArea;
|
2021-04-12 20:19:12 +00:00
|
|
|
break;
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (area != null) {
|
|
|
|
if (activeMethod != null && activeLineDelta >= 0) {
|
|
|
|
MethodParser methods = viewer.methods.get(i);
|
|
|
|
if (methods != null) {
|
|
|
|
int methodLine = methods.findMethod(activeMethod);
|
|
|
|
if (methodLine != -1) {
|
|
|
|
int viewLine = ClassViewer.getViewLine(area);
|
|
|
|
if (activeLineDelta != viewLine - methodLine) {
|
|
|
|
setLine = methodLine + activeLineDelta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-12 20:19:12 +00:00
|
|
|
} else if (activeLine != ClassViewer.getViewLine(area)) {
|
2019-04-17 06:45:15 +00:00
|
|
|
setLine = activeLine;
|
|
|
|
}
|
|
|
|
if (setLine >= 0) {
|
|
|
|
ClassViewer.setViewLine(area, setLine);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2021-06-26 01:13:46 +00:00
|
|
|
|
|
|
|
public void synchronizePane()
|
|
|
|
{
|
|
|
|
if(decompilerViewIndex == 5 || decompilerViewIndex < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
JViewport viewport = updateUpdaterTextArea.getScrollPane().getViewport();
|
2019-04-17 06:45:15 +00:00
|
|
|
viewport.addChangeListener(viewportListener);
|
2021-06-26 01:13:46 +00:00
|
|
|
updateUpdaterTextArea.addCaretListener(caretListener);
|
|
|
|
|
|
|
|
final MethodParser methods = viewer.methods.get(paneIndex);
|
|
|
|
for (int i = 0; i < updateUpdaterTextArea.getLineCount(); i++) {
|
|
|
|
String lineText = ClassViewer.getLineText(updateUpdaterTextArea, i);
|
2019-04-17 06:45:15 +00:00
|
|
|
Matcher regexMatcher = MethodParser.regex.matcher(lineText);
|
2021-04-12 20:19:12 +00:00
|
|
|
if (regexMatcher.find()) {
|
2019-04-17 06:45:15 +00:00
|
|
|
String methodName = regexMatcher.group("name");
|
|
|
|
String methodParams = regexMatcher.group("params");
|
|
|
|
methods.addMethod(i, methodName, methodParams);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
if (BytecodeViewer.viewer.showClassMethods.isSelected()) {
|
2019-04-17 06:45:15 +00:00
|
|
|
if (!methods.isEmpty()) {
|
|
|
|
methodsList = new JComboBox<>();
|
|
|
|
for (Integer line : methods.getMethodsLines()) {
|
|
|
|
methodsList.addItem(line);
|
|
|
|
}
|
2021-06-26 01:13:46 +00:00
|
|
|
methodsList.setRenderer(new MethodsRenderer(this));
|
|
|
|
methodsList.addActionListener(e ->
|
|
|
|
{
|
2021-04-12 22:31:22 +00:00
|
|
|
int line = (int) Objects.requireNonNull(methodsList.getSelectedItem());
|
|
|
|
|
|
|
|
RSyntaxTextArea area = null;
|
2021-06-26 01:13:46 +00:00
|
|
|
switch (paneIndex)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
area = viewer.resourceViewPanel1.updateThread.updateUpdaterTextArea;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
area = viewer.resourceViewPanel2.updateThread.updateUpdaterTextArea;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
area = viewer.resourceViewPanel3.updateThread.updateUpdaterTextArea;
|
|
|
|
break;
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
2021-04-12 22:31:22 +00:00
|
|
|
|
|
|
|
if (area != null)
|
|
|
|
ClassViewer.selectMethod(area, line);
|
2019-04-17 06:45:15 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout());
|
2021-06-26 01:13:46 +00:00
|
|
|
panel.add(updateUpdaterTextArea.getScrollPane().getColumnHeader().getComponent(0), BorderLayout.NORTH);
|
2019-04-17 06:45:15 +00:00
|
|
|
panel.add(methodsList, BorderLayout.SOUTH);
|
2021-06-26 01:13:46 +00:00
|
|
|
methodsList.setBackground(BLANK_COLOR);
|
|
|
|
updateUpdaterTextArea.getScrollPane().getColumnHeader().removeAll();
|
|
|
|
updateUpdaterTextArea.getScrollPane().getColumnHeader().add(panel);
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
|
|
|
}
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2018-01-31 15:03:53 +00:00
|
|
|
}
|