Switching sessions via combo box.

This commit is contained in:
Jindra Petřík
2026-02-15 17:42:21 +01:00
parent 3a44891b26
commit f198f86067
9 changed files with 172 additions and 34 deletions
@@ -18,12 +18,22 @@ package com.jpexs.decompiler.flash.gui;
import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
@@ -37,6 +47,8 @@ import javax.swing.table.TableCellRenderer;
*/
public class DebugStackPanel extends JPanel {
private JComboBox<SessionItem> sessionComboBox = new JComboBox<>();
private JTable stackTable;
private boolean active = false;
@@ -89,6 +101,7 @@ public class DebugStackPanel extends JPanel {
setLayout(new BorderLayout());
//add(titleLabel, BorderLayout.NORTH);
add(new FasterScrollPane(stackTable), BorderLayout.CENTER);
add(sessionComboBox, BorderLayout.NORTH);
stackTable.addMouseListener(new MouseAdapter() {
@Override
@@ -96,12 +109,57 @@ public class DebugStackPanel extends JPanel {
if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
int row = stackTable.rowAtPoint(e.getPoint());
if (row >= 0) {
gotoRow(row);
}
}
}
});
sessionComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SessionItem selection = (SessionItem) sessionComboBox.getSelectedItem();
if (selection != null) {
DebuggerSession session = Main.getDebugHandler().getSessionById(selection.id);
if (session != null && session != Main.getCurrentDebugSession()) {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh(session);
}
});
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
gotoRow(0);
}
});
}
}
}
});
}
private void gotoRow(int row) {
String swfHash = swfHashes[row];
String scriptName = (String) stackTable.getModel().getValueAt(row, 1);
int line = (int) (Integer) stackTable.getModel().getValueAt(row, 2);
SWF swf = swfHash == null ? Main.getRunningSWF() : Main.findOpenedSwfByHash(swfHash);
Main.getMainFrame().getPanel().gotoScriptLine(swf,
boolean scriptFound = Main.getMainFrame().getPanel().gotoScriptLine(swf,
scriptName, line, classIndices[row], traitIndices[row], methodIndices[row], Main.isDebugPCode());
if (!scriptFound) {
if (Main.getMainFrame().getPanel().getCurrentView() == MainPanel.VIEW_RESOURCES) {
TreeItem scriptNode = Main.getMainFrame().getPanel().tagTree.getFullModel().getScriptsNode(swf);
if (scriptNode != null) {
scriptFound = true;
Main.getMainFrame().getPanel().setTagTreeSelectedNode(Main.getMainFrame().getPanel().getCurrentTree(), scriptNode);
}
}
if (!scriptFound) {
Main.getMainFrame().getPanel().setTagTreeSelectedNode(Main.getMainFrame().getPanel().getCurrentTree(), swf);
}
}
DebuggerSession session = null;
if (currentSessionRef != null) {
session = currentSessionRef.get();
@@ -110,9 +168,18 @@ public class DebugStackPanel extends JPanel {
session.setDepth(row);
}
}
private class SessionItem {
private int id;
public SessionItem(int id) {
this.id = id;
}
@Override
public String toString() {
return AppStrings.translate("debug.session").replace("%id%", "" + id);
}
});
}
public void clear() {
@@ -124,7 +191,33 @@ public class DebugStackPanel extends JPanel {
return active;
}
public void refresh(DebuggerSession session) {
Map<Integer, DebuggerSession> allSessions = Main.getDebugHandler().getActiveSessions();
DefaultComboBoxModel<SessionItem> model = new DefaultComboBoxModel<>();
int itemIndex = -1;
int j = 0;
for (int id : allSessions.keySet()) {
DebuggerSession s = allSessions.get(id);
if (s == session) {
itemIndex = j;
}
model.addElement(new SessionItem(id));
j++;
}
sessionComboBox.setModel(model);
if (itemIndex > -1) {
final int fItemIndex = itemIndex;
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
sessionComboBox.setSelectedIndex(fItemIndex);
}
});
}
if (session == null) {
clear();
return;
@@ -147,6 +240,10 @@ public class DebugStackPanel extends JPanel {
if (moduleName.contains(":")) {
swfHash = moduleName.substring(0, moduleName.indexOf(":"));
moduleName = moduleName.substring(moduleName.indexOf(":") + 1);
} else {
List<SWF> debuggedSwfs = new ArrayList<>(session.getDebuggedSwfs().values());
SWF lastSwf = debuggedSwfs.get(debuggedSwfs.size() - 1);
swfHash = Main.getSwfHash(lastSwf);
}
newSwfHashes[i] = swfHash;
data[i][0] = swfHash == null ? "unknown" : Main.findOpenedSwfByHash(swfHash).toString();
@@ -158,7 +255,6 @@ public class DebugStackPanel extends JPanel {
Integer newMethodIndex = session.moduleToMethodIndex(f);
newMethodIndices[i] = newMethodIndex == null ? -1 : newMethodIndex;
Integer newTraitIndex = session.moduleToTraitIndex(f);
;
newTraitIndices[i] = newTraitIndex == null ? -1 : newTraitIndex;
}
@@ -316,4 +316,25 @@ public class DebuggerHandler implements DebugConnectionListener {
}
return null;
}
public Map<Integer, DebuggerSession> getActiveSessions() {
Map<Integer, DebuggerSession> ret = new LinkedHashMap<>();
List<DebuggerSession> currentSessions = new ArrayList<>(sessions);
for (DebuggerSession session : currentSessions) {
if (session.isConnected()) {
ret.put(session.getId(), session);
}
}
return ret;
}
public DebuggerSession getSessionById(int id) {
List<DebuggerSession> currentSessions = new ArrayList<>(sessions);
for (DebuggerSession session : currentSessions) {
if (session.isConnected() && session.getId() == id) {
return session;
}
}
return null;
}
}
@@ -153,7 +153,14 @@ public class DebuggerSession {
paused = false;
}
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
Main.getMainFrame().getPanel().updateMenu();
}
});
//enlog(DebuggerConnection.class);
//enlog(DebuggerCommands.class);
@@ -635,6 +642,12 @@ public class DebuggerSession {
}
}
public int getId() {
return id;
}
public boolean containsSwf(SWF swf) {
return debuggedSwfs.containsValue(swf);
}
+1 -1
View File
@@ -3161,7 +3161,7 @@ public class Main {
if (Main.getDebugHandler().getNumberOfPausedSessions() > 1
&& Main.getCurrentDebugSession() != session) {
Logger.getLogger(Main.class.getName()).log(Level.INFO, "Another SWF ({0}) has reached breakpoint meanwhile", swf.toString());
Logger.getLogger(Main.class.getName()).log(Level.INFO, "Another SWF ({0}) has reached breakpoint meanwhile", swf == null ? "unknown" : swf.toString());
mainFrame.getPanel().refreshBreakPoints();
return;
}
@@ -2718,7 +2718,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
}
public void gotoScriptMethod(SWF swf, String scriptName, int methodIndex) {
public boolean gotoScriptMethod(SWF swf, String scriptName, int methodIndex) {
abcPanel.decompiledTextArea.addScriptListener(new Runnable() {
@Override
public void run() {
@@ -2728,10 +2728,10 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
}
});
gotoScriptName(swf, scriptName);
return gotoScriptName(swf, scriptName);
}
public void gotoScriptTrait(SWF swf, String scriptName, int classIndex, int traitIndex) {
public boolean gotoScriptTrait(SWF swf, String scriptName, int classIndex, int traitIndex) {
abcPanel.decompiledTextArea.addScriptListener(new Runnable() {
@Override
public void run() {
@@ -2746,7 +2746,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
}
});
gotoScriptName(swf, scriptName);
return gotoScriptName(swf, scriptName);
}
public void findOrLoadOpenableListByFilePath(String filePath, OpenableListLoaded executeAfterOpen, boolean loadSession) {
@@ -2768,7 +2768,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}, loadSession);
}
public void gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex, boolean pcode) {
public boolean gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex, boolean pcode) {
View.checkAccess();
if (abcPanel != null && swf.isAS3()) {
@@ -2822,7 +2822,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
});
}
gotoScriptName(swf, scriptName);
return gotoScriptName(swf, scriptName);
}
public void refreshBreakPoints() {
@@ -2850,11 +2850,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
});
}*/
public void gotoScriptName(SWF mainSwf, String scriptNameWithSwfHash) {
public boolean gotoScriptName(SWF mainSwf, String scriptNameWithSwfHash) {
View.checkAccess();
if (mainSwf == null) {
return;
return false;
}
if (mainSwf.isAS3()) {
String rawScriptName = scriptNameWithSwfHash;
@@ -2867,7 +2867,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
//if (!abcList.isEmpty()) {
ABCPanel abcPanel = getABCPanel();
abcPanel.hilightScript(mainSwf, rawScriptName);
return abcPanel.hilightScript(mainSwf, rawScriptName);
//}
} else {
String rawScriptName = scriptNameWithSwfHash;
@@ -2879,11 +2879,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
oldItem = null;
getCurrentTree().setSelectionPath(null);
setTagTreeSelectedNode(getCurrentTree(), asms.get(rawScriptName));
return true;
}
/*if (actionPanel != null && asms.containsKey(rawScriptName)) {
actionPanel.setSource(asms.get(rawScriptName), true);
}*/
}
return false;
}
public void gotoDocumentClass(SWF swf) {
@@ -1775,7 +1775,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
* @param name Full name of the script. It must be printable - deobfuscated,
* not raw!
*/
public void hilightScript(Openable openable, String name) {
public boolean hilightScript(Openable openable, String name) {
TreeItem scriptNode = null;
if (openable instanceof SWF) {
@@ -1799,10 +1799,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
if (swf.getFile() == null && "__playerglobal".equals(swf.getFileTitle())) {
mainPanel.findOrLoadOpenableListByFilePath(Configuration.getPlayerSWC().getAbsolutePath(), afterOpen, false);
return;
return true;
} else if (swf.getFile() == null && "__airglobal".equals(swf.getFileTitle())) {
mainPanel.findOrLoadOpenableListByFilePath(Configuration.getAirSWC().getAbsolutePath(), afterOpen, false);
return;
return true;
}
if (mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES) {
@@ -1829,11 +1829,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
if (scriptNode != null) {
hilightScript(openable, name, scriptNode);
return hilightScript(openable, name, scriptNode);
}
return false;
}
public void hilightScript(Openable openable, String name, TreeItem scriptNode) {
public boolean hilightScript(Openable openable, String name, TreeItem scriptNode) {
View.checkAccess();
Object item;
@@ -1907,10 +1908,11 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
}
if (!found) {
return;
return false;
}
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), (TreeItem) item);
mainPanel.reload(true);
return true;
}
public void hilightScript(ScriptPack pack) {
@@ -1159,6 +1159,8 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
editor.addTextChangedListener(this::editorTextChanged);
decompiledEditor.addTextChangedListener(this::decompiledEditorTextChanged);
debugPanel.refresh(Main.getCurrentDebugSession());
decompiledEditor.refreshMarkers();
editor.refreshMarkers();
}
private void deobfuscateButtonActionPerformed(ActionEvent evt) {
@@ -1114,3 +1114,4 @@ contextmenu.prepareDebug.injectDebug = Prepare file for debugging (+ inject debu
contextmenu.prepareDebug.generateSwd = Prepare file for debugging (+ generate SWD)
prepareDebug.title = Hit Save to overwrite current file or select another file.
work.halted.with = Debugging of %file% started, execution halted. Add breakpoints and click Continue (F5) to resume running.
debug.session = Session %id%
@@ -1113,3 +1113,4 @@ contextmenu.prepareDebug.injectDebug = P\u0159ipravit soubor pro lad\u011bn\u00e
contextmenu.prepareDebug.generateSwd = P\u0159ipravit soubor pro lad\u011bn\u00ed (+ vytvo\u0159it SWD)
prepareDebug.title = Stiskni Ulo\u017eit pro p\u0159eps\u00e1n\u00ed nyn\u011bj\u0161\u00edhio souboru nebo vyber soubor jin\u00fd.
work.halted.with = Lad\u011bn\u00ed %file% za\u010dalo, b\u011bh je nyn\u00ed pozastaven. P\u0159idejte breakpointy a klikn\u011bte na Pokra\u010dovat (F5) pro obnoven\u00ed b\u011bhu.
debug.session = Sezen\u00ed %id%