Added ActionScript Debugger - Call stack frames switching - view variables around call stack

Added ActionScript Debugger - Highlight lines of callstack
Changed Basic tag info panel always visible even when nothing to display (to avoid flickering)
This commit is contained in:
Jindra Petřík
2023-11-05 21:11:10 +01:00
parent 13cfed7be8
commit 982b44a0e6
11 changed files with 460 additions and 143 deletions
@@ -61,18 +61,16 @@ public class DebugPanel extends JPanel {
private MyTreeTable debugLocalsTable; //JTable debugLocalsTable;
private MyTreeTable debugScopeTable;
private JTable callStackTable;
private JTable stackTable;
private MyTreeTable debugScopeTable;
private JTable constantPoolTable;
private JTabbedPane varTabs;
private BreakListener listener;
private BreakListener breakListener;
private DebuggerHandler.FrameChangeListener frameChangeListener;
private JTextArea traceLogTextarea;
private int logLength = 0;
@@ -215,8 +213,6 @@ public class DebugPanel extends JPanel {
//debugScopeTable.addMouseListener(watchHandler);
debugScopeTable = new MyTreeTable(new ABCPanel.VariablesTableModel(debugScopeTable, new ArrayList<>(), new ArrayList<>()), false);
callStackTable = new JTable();
stackTable = new JTable();
constantPoolTable = new JTable();
traceLogTextarea = new JTextArea();
traceLogTextarea.setEditable(false);
@@ -258,30 +254,33 @@ public class DebugPanel extends JPanel {
refresh();
}
});
Main.getDebugHandler().addFrameChangeListener(frameChangeListener = new DebuggerHandler.FrameChangeListener() {
@Override
public void frameChanged() {
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
refresh();
}
});
}
});
Main.getDebugHandler().addBreakListener(listener = new DebuggerHandler.BreakListener() {
Main.getDebugHandler().addBreakListener(breakListener = new DebuggerHandler.BreakListener() {
@Override
public void doContinue() {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh();
}
});
}
@Override
public void breakAt(String scriptName, int line, int classIndex, int traitIndex, int methodIndex) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh();
}
});
public void breakAt(String scriptName, int line, int classIndex, int traitIndex, int methodIndex) {
}
});
@@ -406,52 +405,6 @@ public class DebugPanel extends JPanel {
debugLocalsTable.setTreeModel(new ABCPanel.VariablesTableModel(debugLocalsTable, new ArrayList<>(), new ArrayList<>()));
debugScopeTable.setTreeModel(new ABCPanel.VariablesTableModel(debugScopeTable, new ArrayList<>(), new ArrayList<>()));
}
InBreakAtExt info = Main.getDebugHandler().getBreakInfo();
if (info != null) {
//InBreakReason reason = Main.getDebugHandler().getBreakReason();
List<String> callStackFiles = new ArrayList<>();
List<Integer> callStackLines = new ArrayList<>();
callStackFiles.add(Main.getDebugHandler().moduleToString(info.file));
callStackLines.add(info.line);
for (int i = 0; i < info.files.size(); i++) {
callStackFiles.add(Main.getDebugHandler().moduleToString(info.files.get(i)));
callStackLines.add(info.lines.get(i));
}
Object[][] data = new Object[callStackFiles.size()][2];
for (int i = 0; i < callStackFiles.size(); i++) {
data[i][0] = callStackFiles.get(i);
data[i][1] = callStackLines.get(i);
}
DefaultTableModel tm = new DefaultTableModel(data, new Object[]{
AppStrings.translate("callStack.header.file"),
AppStrings.translate("callStack.header.line")
}) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
callStackTable.setModel(tm);
Object[][] data2 = new Object[info.stacks.size()][1];
for (int i = 0; i < info.stacks.size(); i++) {
data2[i][0] = info.stacks.get(i);
}
stackTable.setModel(new DefaultTableModel(data2, new Object[]{AppStrings.translate("stack.header.item")}) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
});
} else {
callStackTable.setModel(new DefaultTableModel());
stackTable.setModel(new DefaultTableModel());
}
InConstantPool cpool = Main.getDebugHandler().getConstantPool();
if (cpool != null) {
Object[][] data2 = new Object[cpool.vars.size()][2];
@@ -469,6 +422,8 @@ public class DebugPanel extends JPanel {
}
});
} else {
constantPoolTable.setModel(new DefaultTableModel());
}
varTabs.removeAll();
@@ -503,21 +458,7 @@ public class DebugPanel extends JPanel {
pa.add(new FasterScrollPane(constantPoolTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("constantpool.header"), pa);
}
if (callStackTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.CALLSTACK);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(callStackTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("callStack.header"), pa);
}
if (stackTable.getRowCount() > 0) {
tabTypes.add(SelectedTab.STACK);
pa = new JPanel(new BorderLayout());
pa.add(new FasterScrollPane(stackTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("stack.header"), pa);
}
if (logLength > 0) {
tabTypes.add(SelectedTab.LOG);
@@ -560,6 +501,7 @@ public class DebugPanel extends JPanel {
}
public void dispose() {
Main.getDebugHandler().removeBreakListener(listener);
Main.getDebugHandler().removeBreakListener(breakListener);
Main.getDebugHandler().removeFrameChangeListener(frameChangeListener);
}
}
@@ -0,0 +1,166 @@
/*
* Copyright (C) 2023 JPEXS
*
* 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/>.
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
*
* @author JPEXS
*/
public class DebugStackPanel extends JPanel {
private JTable stackTable;
private boolean active = false;
private int depth = 0;
public DebugStackPanel() {
stackTable = new JTable();
Main.getDebugHandler().addFrameChangeListener(new DebuggerHandler.FrameChangeListener() {
@Override
public void frameChanged() {
depth = Main.getDebugHandler().getDepth();
refresh();
}
});
Main.getDebugHandler().addBreakListener(new DebuggerHandler.BreakListener() {
@Override
public void breakAt(String scriptName, int line, int classIndex, int traitIndex, int methodIndex) {
}
@Override
public void doContinue() {
clear();
}
});
Main.getDebugHandler().addConnectionListener(new DebuggerHandler.ConnectionListener() {
@Override
public void connected() {
}
@Override
public void disconnected() {
clear();
}
});
//JLabel titleLabel = new JLabel(AppStrings.translate("callStack.header"), JLabel.CENTER);
setLayout(new BorderLayout());
//add(titleLabel, BorderLayout.NORTH);
add(new FasterScrollPane(stackTable), BorderLayout.CENTER);
stackTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
int row = stackTable.rowAtPoint(e.getPoint());
if (row >= 0) {
String scriptName = (String) stackTable.getModel().getValueAt(row, 0);
int line = (int)(Integer) stackTable.getModel().getValueAt(row, 1);
Main.getMainFrame().getPanel().gotoScriptLine(Main.getMainFrame().getPanel().getCurrentSwf(),
scriptName, line, -1, -1, -1);
Main.getDebugHandler().setDepth(row);
}
}
}
});
}
public void clear() {
stackTable.setModel(new DefaultTableModel());
active = false;
}
public boolean isActive() {
return active;
}
public void refresh() {
InBreakAtExt info = Main.getDebugHandler().getBreakInfo();
if (info == null) {
clear();
return;
}
active = true;
Object[][] data = new Object[info.files.size()][3];
for (int i = 0; i < info.files.size(); i++) {
data[i][0] = Main.getDebugHandler().moduleToString(info.files.get(i));
data[i][1] = info.lines.get(i);
data[i][2] = info.stacks.get(i);
}
DefaultTableModel tm = new DefaultTableModel(data, new Object[]{
AppStrings.translate("callStack.header.file"),
AppStrings.translate("callStack.header.line"),
AppStrings.translate("stack.header.item")
}) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
stackTable.setModel(tm);
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
TableCellRenderer renderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (row == depth) {
label.setFont(label.getFont().deriveFont(Font.BOLD));
}
return label;
}
};
stackTable.getColumnModel().getColumn(0).setCellRenderer(renderer);
stackTable.getColumnModel().getColumn(1).setCellRenderer(renderer);
stackTable.getColumnModel().getColumn(2).setCellRenderer(renderer);
repaint();
}
});
}
public int getDepth() {
return depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
}
@@ -103,6 +103,10 @@ public class DebuggerHandler implements DebugConnectionListener {
private int breakIp = -1;
private String breakScriptName = null;
private List<String> stackScriptNames = new ArrayList<>();
private List<Integer> stackLines = new ArrayList<>();
public static class ActionScriptException extends Exception {
@@ -129,12 +133,30 @@ public class DebuggerHandler implements DebugConnectionListener {
return breakIp;
}
public int getDepth() {
return depth;
}
public String getBreakScriptName() {
if (!isPaused()) {
return "-";
}
return breakScriptName;
}
public synchronized List<String> getStackScripts() {
if (!isPaused()) {
return new ArrayList<>();
}
return stackScriptNames;
}
public synchronized List<Integer> getStackLines() {
if (!isPaused()) {
return new ArrayList<>();
}
return stackLines;
}
public InGetVariable getVariable(long parentId, String varName, boolean children) {
try {
@@ -324,6 +346,8 @@ public class DebuggerHandler implements DebugConnectionListener {
}
private InFrame frame;
private int depth;
private InConstantPool pool;
@@ -334,9 +358,16 @@ public class DebuggerHandler implements DebugConnectionListener {
private final List<BreakListener> breakListeners = new CopyOnWriteArrayList<>();
private final List<TraceListener> traceListeners = new ArrayList<>();
private final List<FrameChangeListener> frameChangeListeners = new ArrayList<>();
private final List<ConnectionListener> clisteners = new ArrayList<>();
public void setDepth(int depth) {
this.depth = depth;
refreshFrame();
}
public String moduleToString(int file) {
if (!modulePaths.containsKey(file)) {
return "unknown";
@@ -369,6 +400,11 @@ public class DebuggerHandler implements DebugConnectionListener {
public void trace(String... val);
}
public static interface FrameChangeListener {
public void frameChanged();
}
public static interface BreakListener {
@@ -380,6 +416,14 @@ public class DebuggerHandler implements DebugConnectionListener {
public void addBreakListener(BreakListener l) {
breakListeners.add(l);
}
public void addFrameChangeListener(FrameChangeListener l) {
frameChangeListeners.add(l);
}
public void removeFrameChangeListener(FrameChangeListener l) {
frameChangeListeners.remove(l);
}
public void addTraceListener(TraceListener l) {
traceListeners.add(l);
@@ -406,11 +450,14 @@ public class DebuggerHandler implements DebugConnectionListener {
return;
}
try {
frame = commands.getFrame(0);
frame = commands.getFrame(depth);
pool = commands.getConstantPool(0);
} catch (IOException ex) {
//ignore
}
for (FrameChangeListener l : frameChangeListeners) {
l.frameChanged();
}
}
public synchronized InFrame getFrame() {
@@ -438,8 +485,8 @@ public class DebuggerHandler implements DebugConnectionListener {
public List<InSwfInfo.SwfInfo> getSwfs() {
return swfs;
}
}
public void disconnect() {
frame = null;
pool = null;
@@ -586,6 +633,7 @@ public class DebuggerHandler implements DebugConnectionListener {
name = DottedChain.parseWithSuffix(pkg).addWithSuffix(clsNameWithSuffix).toString();
}
}
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "Script added - index {0} name: {1}", new Object[]{file, name});
modulePaths.put(file, name);
scriptToModule.put(name, file);
con.dropMessage(sc);
@@ -714,6 +762,16 @@ public class DebuggerHandler implements DebugConnectionListener {
synchronized (DebuggerHandler.this) {
breakScriptName = newBreakScriptName;
breakIp = message.line;
if (breakInfo != null) {
List<String> files = new ArrayList<>();
for (int i = 0; i < breakInfo.files.size(); i++) {
files.add(Main.getDebugHandler().moduleToString(breakInfo.files.get(i)));
}
stackScriptNames = files;
List<Integer> lines = new ArrayList<>(breakInfo.lines);
stackLines = lines;
}
}
if (reasonInt == InBreakReason.REASON_SCRIPT_LOADED) {
@@ -725,9 +783,8 @@ public class DebuggerHandler implements DebugConnectionListener {
} else {
Main.startWork(AppStrings.translate("work.breakat") + newBreakScriptName + ":" + message.line + " " + AppStrings.translate("debug.break.reason." + reason), null);
}
frame = commands.getFrame(0);
pool = commands.getConstantPool(0);
depth = 0;
refreshFrame();
for (BreakListener l : breakListeners) {
l.breakAt(newBreakScriptName, message.line,
moduleToClassIndex.containsKey(message.file) ? moduleToClassIndex.get(message.file) : -1,
@@ -746,13 +803,13 @@ public class DebuggerHandler implements DebugConnectionListener {
synchronized (this) {
connected = true;
}
if (!isAS3) {
/*if (!isAS3) {
try {
commands.getConnection().writeMessage(new OutRewind(commands.getConnection()));
} catch (IOException ex) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}*/
for (ConnectionListener l : clisteners) {
l.connected();
+10 -1
View File
@@ -22,6 +22,7 @@ import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import com.jpexs.debugger.flash.Debugger;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.DebuggerConnection;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.VariableType;
import com.jpexs.debugger.flash.messages.in.InCallFunction;
@@ -682,6 +683,14 @@ public class Main {
public static synchronized String getIpClass() {
return getDebugHandler().getBreakScriptName();
}
public static synchronized List<Integer> getStackLines() {
return getDebugHandler().getStackLines();
}
public static synchronized List<String> getStackClasses() {
return getDebugHandler().getStackScripts();
}
public static synchronized boolean isBreakPointValid(String scriptName, int line) {
return !getDebugHandler().isBreakpointInvalid(scriptName, line);
@@ -3201,6 +3210,6 @@ public class Main {
} catch (Exception ex) {
throw new RuntimeException("Problems with creating the log files");
}
}
}
}
+148 -49
View File
@@ -366,11 +366,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
private static final String CARDHEADER = "Header card";
private static final String DETAILCARDAS3NAVIGATOR = "Traits list";
private static final int DETAILCARDAS3NAVIGATOR = 1;
private static final String DETAILCARDTAGINFO = "Tag information";
private static final int DETAILCARDTAGINFO = 0;
private static final String DETAILCARDEMPTYPANEL = "Empty card";
private static final int DETAILCARDEMPTYPANEL = -1;
private static final int DETAILCARDDEBUGSTACKFRAME = 2;
private static final String SPLIT_PANE1 = "SPLITPANE1";
@@ -390,7 +392,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
private final JPersistentSplitPane splitPane2;
private JPanel detailPanel;
private JTabbedPane detailPanel;
private QuickTreeFindPanel quickTreeFindPanel;
@@ -411,6 +413,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
private final PreviewPanel dumpPreviewPanel;
private final TagInfoPanel tagInfoPanel;
private final DebugStackPanel debugStackPanel;
private TreePanelMode treePanelMode;
@@ -1024,7 +1028,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
public String translate(String key) {
return mainFrame.translate(key);
}
public MainPanel(MainFrame mainFrame, MainFrameMenu mainMenu, FlashPlayerPanel flashPanel, FlashPlayerPanel previewFlashPanel) {
super();
@@ -1038,18 +1042,56 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
setLayout(new BorderLayout());
openables = new ObservableList<>();
detailPanel = new JPanel();
detailPanel.setLayout(new CardLayout());
detailPanel = new JTabbedPane();
//detailPanel.setLayout(new CardLayout());
JPanel whitePanel = new JPanel();
/*JPanel whitePanel = new JPanel();
if (View.isOceanic()) {
whitePanel.setBackground(Color.white);
}
detailPanel.add(whitePanel, DETAILCARDEMPTYPANEL);
*/
tagInfoPanel = new TagInfoPanel(this);
detailPanel.add(tagInfoPanel, DETAILCARDTAGINFO);
debugStackPanel = new DebugStackPanel();
Main.getDebugHandler().addBreakListener(new DebuggerHandler.BreakListener() {
@Override
public void breakAt(String scriptName, int line, int classIndex, int traitIndex, int methodIndex) {
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
showDetail(DETAILCARDDEBUGSTACKFRAME);
}
});
}
@Override
public void doContinue() {
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
showDetail(DETAILCARDEMPTYPANEL);
}
});
}
});
Main.getDebugHandler().addConnectionListener(new DebuggerHandler.ConnectionListener(){
@Override
public void connected() {
}
@Override
public void disconnected() {
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
reload(true);
}
});
}
});
UIManager.getDefaults().put("TreeUI", BasicTreeUI.class.getName());
tagTree = new TagTree(null, this);
tagTree.addTreeSelectionListener(this);
@@ -1412,8 +1454,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
public ABCPanel getABCPanel() {
if (abcPanel == null) {
abcPanel = new ABCPanel(this);
displayPanel.add(abcPanel, CARDACTIONSCRIPT3PANEL);
detailPanel.add(abcPanel.navigatorPanel, DETAILCARDAS3NAVIGATOR);
displayPanel.add(abcPanel, CARDACTIONSCRIPT3PANEL);
}
return abcPanel;
@@ -2486,32 +2527,57 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
public void gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex) {
View.checkAccess();
gotoScriptName(swf, scriptName);
if (abcPanel != null) {
if (Main.isDebugPCode()) {
if (classIndex != -1) {
boolean classChanged = false;
if (abcPanel.decompiledTextArea.getClassIndex() != classIndex) {
abcPanel.decompiledTextArea.setClassIndex(classIndex);
classChanged = true;
}
if (traitIndex != -10 && (classChanged || abcPanel.decompiledTextArea.lastTraitIndex != traitIndex)) {
abcPanel.decompiledTextArea.gotoTrait(traitIndex);
}
}
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.gotoInstrLine(line);
} else {
abcPanel.decompiledTextArea.gotoLine(line);
}
} else if (actionPanel != null) {
if (Main.isDebugPCode()) {
actionPanel.editor.gotoLine(line);
} else {
actionPanel.decompiledEditor.gotoLine(line);
}
if (abcPanel != null && swf.isAS3()) {
abcPanel.decompiledTextArea.addScriptListener(new Runnable() {
@Override
public void run() {
abcPanel.decompiledTextArea.removeScriptListener(this);
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
if (Main.isDebugPCode()) {
if (classIndex != -1) {
boolean classChanged = false;
if (abcPanel.decompiledTextArea.getClassIndex() != classIndex) {
abcPanel.decompiledTextArea.setClassIndex(classIndex);
classChanged = true;
}
if (traitIndex != -10 && (classChanged || abcPanel.decompiledTextArea.lastTraitIndex != traitIndex)) {
abcPanel.decompiledTextArea.gotoTrait(traitIndex);
}
}
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.gotoInstrLine(line);
} else {
abcPanel.decompiledTextArea.gotoLine(line);
}
scrollPosStorage.saveScrollPos(oldItem);
refreshBreakPoints();
}
});
}
});
} else if (actionPanel != null && !swf.isAS3()) {
actionPanel.addScriptListener(new Runnable() {
@Override
public void run() {
actionPanel.removeScriptListener(this);
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
if (Main.isDebugPCode()) {
actionPanel.editor.gotoLine(line);
} else {
actionPanel.decompiledEditor.gotoLine(line);
}
scrollPosStorage.saveScrollPos(oldItem);
refreshBreakPoints();
}
});
}
});
}
refreshBreakPoints();
gotoScriptName(swf, scriptName);
}
public void refreshBreakPoints() {
@@ -2561,11 +2627,16 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
String rawScriptName = scriptName;
if (rawScriptName.startsWith("#PCODE ")) {
rawScriptName = rawScriptName.substring("#PCODE ".length());
}
}
Map<String, ASMSource> asms = swf.getASMs(true);
if (actionPanel != null && asms.containsKey(rawScriptName)) {
actionPanel.setSource(asms.get(rawScriptName), true);
if (asms.containsKey(rawScriptName)) {
oldItem = null;
getCurrentTree().setSelectionPath(null);
setTagTreeSelectedNode(getCurrentTree(), asms.get(rawScriptName));
}
/*if (actionPanel != null && asms.containsKey(rawScriptName)) {
actionPanel.setSource(asms.get(rawScriptName), true);
}*/
}
}
@@ -4698,16 +4769,40 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
return null;
}
}
private void showDetail(String card) {
CardLayout cl = (CardLayout) (detailPanel.getLayout());
cl.show(detailPanel, card);
if (card.equals(DETAILCARDEMPTYPANEL)) {
if (detailPanel.isVisible()) {
detailPanel.setVisible(false);
private void showDetail(int card) {
if (debugStackPanel.isActive() && card != DETAILCARDDEBUGSTACKFRAME) {
return;
}
detailPanel.removeAll();
int pos = 0;
if (card == DETAILCARDTAGINFO) {
detailPanel.addTab(AppStrings.translate("taginfo.header"), tagInfoPanel);
if (card == DETAILCARDTAGINFO) {
detailPanel.setSelectedIndex(pos);
}
} else if (!detailPanel.isVisible()) {
pos++;
}
if (card == DETAILCARDAS3NAVIGATOR || card == DETAILCARDDEBUGSTACKFRAME) {
if (abcPanel != null && getCurrentSwf() != null && getCurrentSwf().isAS3()) {
detailPanel.addTab(AppStrings.translate("traits"), abcPanel.navigatorPanel);
if (card == DETAILCARDAS3NAVIGATOR) {
detailPanel.setSelectedIndex(pos);
}
pos++;
}
}
if (debugStackPanel.isActive()) {
detailPanel.addTab(AppStrings.translate("callStack.header"), debugStackPanel);
if (card == DETAILCARDDEBUGSTACKFRAME) {
detailPanel.setSelectedIndex(pos);
}
pos++;
}
if (currentView != VIEW_DUMP) {
detailPanel.setVisible(true);
}
}
@@ -4971,9 +5066,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
showTreePanelCard(DUMP_VIEW);
treePanelMode = TreePanelMode.DUMP_TREE;
showDetail(DETAILCARDEMPTYPANEL);
//showDetail(DETAILCARDEMPTYPANEL);
showDetail(DETAILCARDEMPTYPANEL);
reload(true);
updateUiWithCurrentOpenable();
detailPanel.setVisible(false);
return true;
case VIEW_RESOURCES:
pinsPanel.setVisible(true);
@@ -4993,6 +5090,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
});
detailPanel.setVisible(true);
refreshPins();
reload(true);
updateUiWithCurrentOpenable();
@@ -5029,6 +5127,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
showTreePanelCard(TAGLIST_VIEW);
treePanelMode = TreePanelMode.TAGLIST_TREE;
detailPanel.setVisible(true);
refreshPins();
reload(true);
updateUiWithCurrentOpenable();
@@ -54,8 +54,8 @@ public class TagInfoPanel extends JPanel {
public TagInfoPanel(MainPanel mainPanel) {
this.mainPanel = mainPanel;
setLayout(new BorderLayout());
JLabel topLabel = new JLabel(AppStrings.translate("taginfo.header"), JLabel.CENTER);
add(topLabel, BorderLayout.NORTH);
//JLabel topLabel = new JLabel(AppStrings.translate("taginfo.header"), JLabel.CENTER);
//add(topLabel, BorderLayout.NORTH);
add(new FasterScrollPane(editorPane), BorderLayout.CENTER);
editorPane.setContentType("text/html");
@@ -1116,8 +1116,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
final JToggleButton sortButton = new JToggleButton(View.getIcon("sort16"));
sortButton.setMargin(new Insets(3, 3, 3, 3));
navIconsPanel.add(sortButton);
JLabel navigatorLabel = new JLabel(AppStrings.translate("traits"), JLabel.CENTER);
navigatorPanel.add(navigatorLabel, BorderLayout.NORTH);
//JLabel navigatorLabel = new JLabel(AppStrings.translate("traits"), JLabel.CENTER);
//navigatorPanel.add(navigatorLabel, BorderLayout.NORTH);
navigatorPanel.add(navIconsPanel, BorderLayout.SOUTH);
navigatorPanel.add(new FasterScrollPane(navigator), BorderLayout.CENTER);
sortButton.addActionListener(new ActionListener() {
@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.gui.action;
import com.jpexs.debugger.flash.DebuggerConnection;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.ValueTooLargeException;
@@ -86,7 +87,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.Box;
@@ -22,6 +22,7 @@ import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.List;
import java.util.Set;
import javax.swing.UIManager;
import jsyntaxpane.components.BreakPointListener;
@@ -39,6 +40,8 @@ public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakP
private static final Color BG_RULER_COLOR = new Color(0xe9, 0xe8, 0xe2);
private static Color BG_BREAKPOINT_COLOR = new Color(0xfc, 0x9d, 0x9f);
private static final Color BG_STACK_COLOR = new Color(0xe7, 0xe1, 0xef);
private static final Color FG_BREAKPOINT_COLOR = null;
@@ -47,6 +50,10 @@ public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakP
private static final Color BG_IP_COLOR = new Color(0xbd, 0xe6, 0xaa);
private static final Color FG_IP_COLOR = null;
private static final Color FG_STACK_COLOR = null;
private static final int PRIORITY_STACK = 30;
private static final int PRIORITY_IP = 0;
@@ -61,6 +68,8 @@ public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakP
public static final LineMarker IP_MARKER = new LineMarker(FG_IP_COLOR, BG_IP_COLOR, PRIORITY_IP);
public static final LineMarker INVALID_BREAKPOINT_MARKER = new LineMarker(FG_INVALID_BREAKPOINT_COLOR, BG_INVALID_BREAKPOINT_COLOR, PRIORITY_INVALID_BREAKPOINT);
public static final LineMarker STACK_MARKER = new LineMarker(FG_STACK_COLOR, BG_STACK_COLOR, PRIORITY_STACK);
protected String scriptName = null;
@@ -122,6 +131,15 @@ public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakP
if (ip > 0 && ipPath != null && ipPath.equals(scriptName)) {
addColorMarker(ip + firstLineOffset(), IP_MARKER);
}
List<Integer> stackLines = Main.getStackLines();
List<String> stackClasses = Main.getStackClasses();
for (int i = 1; i < stackClasses.size(); i++) {
String cls = stackClasses.get(i);
int line = stackLines.get(i);
if (cls.equals(scriptName)) {
addColorMarker(line + firstLineOffset(), STACK_MARKER);
}
}
}
@Override
@@ -161,6 +179,13 @@ public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakP
((Graphics2D) g).setStroke(new BasicStroke(0.5f));
boolean drawText = true;
if (hasColorMarker(line, STACK_MARKER)) {
g.setColor(BG_STACK_COLOR);
g.fillPolygon(new int[]{x + 5, x + 15, x + 15}, new int[]{textY, textY, textY - 10}, 3);
g.setColor(Color.black);
g.drawPolygon(new int[]{x + 5, x + 15, x + 15}, new int[]{textY, textY, textY - 10}, 3);
drawText = false;
}
if (hasColorMarker(line, INVALID_BREAKPOINT_MARKER)) {
g.setColor(BG_INVALID_BREAKPOINT_COLOR);
g.fillOval(x + 5, textY - 10, 10, 10);
@@ -218,6 +218,17 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
int pos = ActionUtils.getDocumentPosition(this, line, 0);
if (pos != -1) {
setCaretPosition(pos);
com.jpexs.decompiler.flash.gui.View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
try {
Rectangle r = modelToView(pos);
scrollRectToVisible(r);
} catch (BadLocationException ex) {
//ignore
}
}
});
}
}