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.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Component; import java.awt.Component;
import java.awt.Font; 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.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.lang.ref.WeakReference; 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.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTable; import javax.swing.JTable;
@@ -37,6 +47,8 @@ import javax.swing.table.TableCellRenderer;
*/ */
public class DebugStackPanel extends JPanel { public class DebugStackPanel extends JPanel {
private JComboBox<SessionItem> sessionComboBox = new JComboBox<>();
private JTable stackTable; private JTable stackTable;
private boolean active = false; private boolean active = false;
@@ -89,6 +101,7 @@ public class DebugStackPanel extends JPanel {
setLayout(new BorderLayout()); setLayout(new BorderLayout());
//add(titleLabel, BorderLayout.NORTH); //add(titleLabel, BorderLayout.NORTH);
add(new FasterScrollPane(stackTable), BorderLayout.CENTER); add(new FasterScrollPane(stackTable), BorderLayout.CENTER);
add(sessionComboBox, BorderLayout.NORTH);
stackTable.addMouseListener(new MouseAdapter() { stackTable.addMouseListener(new MouseAdapter() {
@Override @Override
@@ -96,23 +109,77 @@ public class DebugStackPanel extends JPanel {
if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) { if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e)) {
int row = stackTable.rowAtPoint(e.getPoint()); int row = stackTable.rowAtPoint(e.getPoint());
if (row >= 0) { if (row >= 0) {
String swfHash = swfHashes[row]; gotoRow(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,
scriptName, line, classIndices[row], traitIndices[row], methodIndices[row], Main.isDebugPCode());
DebuggerSession session = null;
if (currentSessionRef != null) {
session = currentSessionRef.get();
}
if (session != null) {
session.setDepth(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);
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();
}
if (session != null) {
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() { public void clear() {
@@ -123,8 +190,34 @@ public class DebugStackPanel extends JPanel {
public boolean isActive() { public boolean isActive() {
return active; return active;
} }
public void refresh(DebuggerSession session) { 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) { if (session == null) {
clear(); clear();
return; return;
@@ -147,7 +240,11 @@ public class DebugStackPanel extends JPanel {
if (moduleName.contains(":")) { if (moduleName.contains(":")) {
swfHash = moduleName.substring(0, moduleName.indexOf(":")); swfHash = moduleName.substring(0, moduleName.indexOf(":"));
moduleName = moduleName.substring(moduleName.indexOf(":") + 1); 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; newSwfHashes[i] = swfHash;
data[i][0] = swfHash == null ? "unknown" : Main.findOpenedSwfByHash(swfHash).toString(); data[i][0] = swfHash == null ? "unknown" : Main.findOpenedSwfByHash(swfHash).toString();
data[i][1] = moduleName; data[i][1] = moduleName;
@@ -157,8 +254,7 @@ public class DebugStackPanel extends JPanel {
newClassIndices[i] = newClassIndex == null ? -1 : newClassIndex; newClassIndices[i] = newClassIndex == null ? -1 : newClassIndex;
Integer newMethodIndex = session.moduleToMethodIndex(f); Integer newMethodIndex = session.moduleToMethodIndex(f);
newMethodIndices[i] = newMethodIndex == null ? -1 : newMethodIndex; newMethodIndices[i] = newMethodIndex == null ? -1 : newMethodIndex;
Integer newTraitIndex = session.moduleToTraitIndex(f); Integer newTraitIndex = session.moduleToTraitIndex(f);
;
newTraitIndices[i] = newTraitIndex == null ? -1 : newTraitIndex; newTraitIndices[i] = newTraitIndex == null ? -1 : newTraitIndex;
} }
@@ -316,4 +316,25 @@ public class DebuggerHandler implements DebugConnectionListener {
} }
return null; 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; paused = false;
} }
Main.getMainFrame().getPanel().updateMenu(); View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
Main.getMainFrame().getPanel().updateMenu();
}
});
//enlog(DebuggerConnection.class); //enlog(DebuggerConnection.class);
//enlog(DebuggerCommands.class); //enlog(DebuggerCommands.class);
@@ -635,6 +642,12 @@ public class DebuggerSession {
} }
} }
public int getId() {
return id;
}
public boolean containsSwf(SWF swf) { public boolean containsSwf(SWF swf) {
return debuggedSwfs.containsValue(swf); return debuggedSwfs.containsValue(swf);
} }
+1 -1
View File
@@ -3161,7 +3161,7 @@ public class Main {
if (Main.getDebugHandler().getNumberOfPausedSessions() > 1 if (Main.getDebugHandler().getNumberOfPausedSessions() > 1
&& Main.getCurrentDebugSession() != session) { && 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(); mainFrame.getPanel().refreshBreakPoints();
return; 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() { abcPanel.decompiledTextArea.addScriptListener(new Runnable() {
@Override @Override
public void run() { 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() { abcPanel.decompiledTextArea.addScriptListener(new Runnable() {
@Override @Override
public void run() { 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) { public void findOrLoadOpenableListByFilePath(String filePath, OpenableListLoaded executeAfterOpen, boolean loadSession) {
@@ -2768,7 +2768,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}, loadSession); }, 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(); View.checkAccess();
if (abcPanel != null && swf.isAS3()) { 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() { 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(); View.checkAccess();
if (mainSwf == null) { if (mainSwf == null) {
return; return false;
} }
if (mainSwf.isAS3()) { if (mainSwf.isAS3()) {
String rawScriptName = scriptNameWithSwfHash; String rawScriptName = scriptNameWithSwfHash;
@@ -2867,7 +2867,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
//if (!abcList.isEmpty()) { //if (!abcList.isEmpty()) {
ABCPanel abcPanel = getABCPanel(); ABCPanel abcPanel = getABCPanel();
abcPanel.hilightScript(mainSwf, rawScriptName); return abcPanel.hilightScript(mainSwf, rawScriptName);
//} //}
} else { } else {
String rawScriptName = scriptNameWithSwfHash; String rawScriptName = scriptNameWithSwfHash;
@@ -2879,11 +2879,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
oldItem = null; oldItem = null;
getCurrentTree().setSelectionPath(null); getCurrentTree().setSelectionPath(null);
setTagTreeSelectedNode(getCurrentTree(), asms.get(rawScriptName)); setTagTreeSelectedNode(getCurrentTree(), asms.get(rawScriptName));
return true;
} }
/*if (actionPanel != null && asms.containsKey(rawScriptName)) { /*if (actionPanel != null && asms.containsKey(rawScriptName)) {
actionPanel.setSource(asms.get(rawScriptName), true); actionPanel.setSource(asms.get(rawScriptName), true);
}*/ }*/
} }
return false;
} }
public void gotoDocumentClass(SWF swf) { public void gotoDocumentClass(SWF swf) {
@@ -1767,7 +1767,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
hilightScript(openable, name); hilightScript(openable, name);
} }
} }
/** /**
* Hilights specific script. * Hilights specific script.
* *
@@ -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, * @param name Full name of the script. It must be printable - deobfuscated,
* not raw! * not raw!
*/ */
public void hilightScript(Openable openable, String name) { public boolean hilightScript(Openable openable, String name) {
TreeItem scriptNode = null; TreeItem scriptNode = null;
if (openable instanceof SWF) { 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())) { if (swf.getFile() == null && "__playerglobal".equals(swf.getFileTitle())) {
mainPanel.findOrLoadOpenableListByFilePath(Configuration.getPlayerSWC().getAbsolutePath(), afterOpen, false); mainPanel.findOrLoadOpenableListByFilePath(Configuration.getPlayerSWC().getAbsolutePath(), afterOpen, false);
return; return true;
} else if (swf.getFile() == null && "__airglobal".equals(swf.getFileTitle())) { } else if (swf.getFile() == null && "__airglobal".equals(swf.getFileTitle())) {
mainPanel.findOrLoadOpenableListByFilePath(Configuration.getAirSWC().getAbsolutePath(), afterOpen, false); mainPanel.findOrLoadOpenableListByFilePath(Configuration.getAirSWC().getAbsolutePath(), afterOpen, false);
return; return true;
} }
if (mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES) { if (mainPanel.getCurrentView() == MainPanel.VIEW_RESOURCES) {
@@ -1829,11 +1829,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
} }
if (scriptNode != null) { 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(); View.checkAccess();
Object item; Object item;
@@ -1907,10 +1908,11 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
} }
} }
if (!found) { if (!found) {
return; return false;
} }
mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), (TreeItem) item); mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), (TreeItem) item);
mainPanel.reload(true); mainPanel.reload(true);
return true;
} }
public void hilightScript(ScriptPack pack) { public void hilightScript(ScriptPack pack) {
@@ -1159,6 +1159,8 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
editor.addTextChangedListener(this::editorTextChanged); editor.addTextChangedListener(this::editorTextChanged);
decompiledEditor.addTextChangedListener(this::decompiledEditorTextChanged); decompiledEditor.addTextChangedListener(this::decompiledEditorTextChanged);
debugPanel.refresh(Main.getCurrentDebugSession()); debugPanel.refresh(Main.getCurrentDebugSession());
decompiledEditor.refreshMarkers();
editor.refreshMarkers();
} }
private void deobfuscateButtonActionPerformed(ActionEvent evt) { 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) contextmenu.prepareDebug.generateSwd = Prepare file for debugging (+ generate SWD)
prepareDebug.title = Hit Save to overwrite current file or select another file. 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. 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) 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. 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. 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%