Added: #2644 Debugger - Button to sort variables alphabetically

This commit is contained in:
Jindra Petřík
2026-02-27 22:10:49 +01:00
parent 3f1b6682f5
commit d3eb321ddc
12 changed files with 127 additions and 26 deletions

View File

@@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
### Added
- Debugger - Button to disconnect current session (stay listening)
- [#2644] Debugger - Button to sort variables alphabetically
### Fixed
- [#2643] APNG export - images containing multiple IDAT chunks
@@ -4174,6 +4175,7 @@ Major version of SWF to XML export changed to 2.
[alpha 9]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha8...alpha9
[alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8
[alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7
[#2644]: https://www.free-decompiler.com/flash/issues/2644
[#2643]: https://www.free-decompiler.com/flash/issues/2643
[#2645]: https://www.free-decompiler.com/flash/issues/2645
[#2639]: https://www.free-decompiler.com/flash/issues/2639

View File

@@ -1201,6 +1201,11 @@ public final class Configuration {
@ConfigurationCategory("script")
public static ConfigurationItem<Boolean> as3QNameObfuscatedPropsInSquareBrackets = null;
@ConfigurationDefaultBoolean(false)
@ConfigurationCategory("ui")
public static ConfigurationItem<Boolean> sortDebugVariablesAlphabetically = null;
private static Map<String, String> configurationDescriptions = new LinkedHashMap<>();
private static Map<String, String> configurationTitles = new LinkedHashMap<>();

View File

@@ -16,7 +16,6 @@
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.debugger.flash.Debugger;
import com.jpexs.debugger.flash.DebuggerCommands;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.messages.in.InConstantPool;
@@ -24,6 +23,7 @@ import com.jpexs.debugger.flash.messages.in.InFrame;
import com.jpexs.debugger.flash.messages.in.InGetVariable;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.configuration.ConfigurationItemChangeListener;
import com.jpexs.decompiler.flash.gui.DebuggerHandler.BreakListener;
import com.jpexs.decompiler.flash.gui.abc.ABCPanel;
import com.jpexs.helpers.Helper;
@@ -57,6 +57,7 @@ import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.JTree;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@@ -97,6 +98,8 @@ public class DebugPanel extends JPanel {
public ABCPanel.VariablesTableModel localsTable;
private WeakReference<DebuggerSession> currentSessionRef = null;
private JToggleButton sortToggleButton;
private boolean as3;
@@ -169,9 +172,12 @@ public class DebugPanel extends JPanel {
public DebugPanel(boolean as3) {
super(new BorderLayout());
this.as3 = as3;
debugRegistersTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugRegistersTable, new ArrayList<>(), new ArrayList<>()), false);
debugLocalsTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugLocalsTable, new ArrayList<>(), new ArrayList<>()), false);
debugWatchesTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugWatchesTable, new ArrayList<>(), new ArrayList<>()), false);
sortToggleButton = new JToggleButton(View.getIcon("sort16"));
debugRegistersTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugRegistersTable, new ArrayList<>(), new ArrayList<>(), false), false);
debugLocalsTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugLocalsTable, new ArrayList<>(), new ArrayList<>(), false), false);
debugWatchesTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugWatchesTable, new ArrayList<>(), new ArrayList<>(), false), false);
MouseAdapter watchHandler = new MouseAdapter() {
@@ -409,7 +415,7 @@ public class DebugPanel extends JPanel {
debugWatchesTable.addMouseListener(watchHandler);
//debugScopeTable.addMouseListener(watchHandler);
debugScopeTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugScopeTable, new ArrayList<>(), new ArrayList<>()), false);
debugScopeTable = new MyTreeTable(new ABCPanel.VariablesTableModel(null, as3, debugScopeTable, new ArrayList<>(), new ArrayList<>(), false), false);
constantPoolTable = new JTable(new DefaultTableModel(new Object[2][0], new Object[]{
AppStrings.translate("constantpool.header.id"),
@@ -497,6 +503,30 @@ public class DebugPanel extends JPanel {
//reacts to frameChanged instead
}
});
sortToggleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
refresh();
}
});
sortToggleButton.setToolTipText(AppStrings.translate("sort.alphabetically"));
sortToggleButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Configuration.sortDebugVariablesAlphabetically.set(sortToggleButton.isSelected());
}
});
Configuration.sortDebugVariablesAlphabetically.addListener(new ConfigurationItemChangeListener<Boolean>() {
@Override
public void configurationItemChanged(Boolean newValue) {
sortToggleButton.setSelected(newValue);
refresh();
}
});
JPanel bottomButtonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
bottomButtonsPanel.add(sortToggleButton);
varTabs = new JTabbedPane();
varTabs.addChangeListener(new ChangeListener() {
@@ -511,6 +541,11 @@ public class DebugPanel extends JPanel {
int si = varTabs.getSelectedIndex();
if (si > -1 && si < tabTypes.size()) {
selectedTab = tabTypes.get(si);
bottomButtonsPanel.setVisible(
selectedTab == SelectedTab.LOCALS
|| selectedTab == SelectedTab.WATCHES
);
}
}
}
@@ -519,6 +554,10 @@ public class DebugPanel extends JPanel {
add(new HeaderLabel(AppStrings.translate("debugpanel.header")), BorderLayout.NORTH);
add(varTabs, BorderLayout.CENTER);
add(bottomButtonsPanel, BorderLayout.SOUTH);
}
/* private void getVariableList() {
@@ -571,6 +610,8 @@ public class DebugPanel extends JPanel {
try {
setLoading(true);
boolean sort = sortToggleButton.isSelected();
int sessionId = -1;
if (session != null) {
@@ -583,10 +624,10 @@ public class DebugPanel extends JPanel {
localsTable = null;
InFrame f = session == null ? null : session.getFrame();
ABCPanel.VariablesTableModel registersTableModel = new ABCPanel.VariablesTableModel(session, as3, debugRegistersTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel localsTableModel = new ABCPanel.VariablesTableModel(session, as3, debugLocalsTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel scopeTableModel = new ABCPanel.VariablesTableModel(session, as3, debugScopeTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel watchesTableModel = new ABCPanel.VariablesTableModel(session, as3, debugWatchesTable, new ArrayList<>(), new ArrayList<>());
ABCPanel.VariablesTableModel registersTableModel = new ABCPanel.VariablesTableModel(session, as3, debugRegistersTable, new ArrayList<>(), new ArrayList<>(), sort);
ABCPanel.VariablesTableModel localsTableModel = new ABCPanel.VariablesTableModel(session, as3, debugLocalsTable, new ArrayList<>(), new ArrayList<>(), sort);
ABCPanel.VariablesTableModel scopeTableModel = new ABCPanel.VariablesTableModel(session, as3, debugScopeTable, new ArrayList<>(), new ArrayList<>(), sort);
ABCPanel.VariablesTableModel watchesTableModel = new ABCPanel.VariablesTableModel(session, as3, debugWatchesTable, new ArrayList<>(), new ArrayList<>(), sort);
ABCPanel.VariablesTableModel fRegistersTableModel;
ABCPanel.VariablesTableModel fLocalsTableModel;
ABCPanel.VariablesTableModel fScopeTableModel;
@@ -621,8 +662,8 @@ public class DebugPanel extends JPanel {
locals.addAll(f.arguments);
locals.addAll(f.variables);
localsTable = new ABCPanel.VariablesTableModel(session, as3, debugLocalsTable, locals, null);
localsTable = new ABCPanel.VariablesTableModel(session, as3, debugLocalsTable, locals, null, sort);
List<Variable> watchedVars = new ArrayList<>();
List<Long> watchedParentIds = new ArrayList<>();
@@ -663,10 +704,10 @@ public class DebugPanel extends JPanel {
}
};
registersTableModel = new ABCPanel.VariablesTableModel(session, as3, debugRegistersTable, f.registers, null);
registersTableModel = new ABCPanel.VariablesTableModel(session, as3, debugRegistersTable, f.registers, null, sort);
localsTableModel = localsTable;
scopeTableModel = new ABCPanel.VariablesTableModel(session, as3, debugScopeTable, f.scopeChain, null);
watchesTableModel = new ABCPanel.VariablesTableModel(session, as3, debugWatchesTable, watchedVars, watchedParentIds);
scopeTableModel = new ABCPanel.VariablesTableModel(session, as3, debugScopeTable, f.scopeChain, null, sort);
watchesTableModel = new ABCPanel.VariablesTableModel(session, as3, debugWatchesTable, watchedVars, watchedParentIds, sort);
localsTableModel.addTreeModelListener(refreshListener);
scopeTableModel.addTreeModelListener(refreshListener);

View File

@@ -123,6 +123,7 @@ import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -344,6 +345,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
sessionIdToLoadedVariableNode.get(sessionId).clear();
}
private boolean sort;
@Override
public int hashCode() {
@@ -403,8 +405,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
private void reloadChildren() {
childs = new ArrayList<>();
traits = new ArrayList<>();
List<VariableNode> newChilds = new ArrayList<>();
List<Variable> newTraits = new ArrayList<>();
if ("".equals(var.name)) {
return;
@@ -447,12 +449,24 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
if (!isTraits(igv.childs.get(i))) {
Long parentObjectId = varToObjectId(varInsideGetter);
childs.add(new VariableNode(currentSession, treeTable, as3, path, level + 1, igv.childs.get(i), parentObjectId, curTrait));
newChilds.add(new VariableNode(currentSession, treeTable, as3, path, level + 1, igv.childs.get(i), parentObjectId, curTrait, sort));
} else {
curTrait = igv.childs.get(i);
traits.add(curTrait);
newTraits.add(curTrait);
}
}
if (sort) {
newChilds.sort(new Comparator<VariableNode>() {
@Override
public int compare(VariableNode o1, VariableNode o2) {
return o1.var.name.compareTo(o2.var.name);
}
});
}
this.childs = newChilds;
this.traits = newTraits;
}
private void ensureLoaded() {
@@ -578,7 +592,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
return childs.size();
}
public VariableNode(DebuggerSession session, MyTreeTable treeTable, boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait) {
public VariableNode(DebuggerSession session, MyTreeTable treeTable, boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait, boolean sort) {
this.var = var;
this.varInsideGetter = var;
this.parentObjectId = parentObjectId;
@@ -590,9 +604,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
this.session = session;
this.treeTable = treeTable;
this.as3 = as3;
this.sort = sort;
}
public VariableNode(DebuggerSession session, MyTreeTable treeTable, boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait, List<VariableNode> subvars) {
public VariableNode(DebuggerSession session, MyTreeTable treeTable, boolean as3, List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait, List<VariableNode> subvars, boolean sort) {
this.var = var;
this.varInsideGetter = var;
this.parentObjectId = parentObjectId;
@@ -611,6 +626,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
this.session = session;
this.treeTable = treeTable;
this.as3 = as3;
this.sort = sort;
}
}
@@ -646,17 +662,31 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
private static final int STRUCTURE_CHANGED = 3;
private final MyTreeTable treeTable;
private final boolean sort;
public VariablesTableModel(DebuggerSession session, boolean as3, MyTreeTable treeTable, List<Variable> vars, List<Long> parentIds) {
public VariablesTableModel(DebuggerSession session, boolean as3, MyTreeTable treeTable, List<Variable> vars, List<Long> parentIds, boolean sort) {
this.treeTable = treeTable;
List<VariableNode> childs = new ArrayList<>();
for (int i = 0; i < vars.size(); i++) {
childs.add(new VariableNode(session, treeTable, as3, new ArrayList<>(), 1, vars.get(i), parentIds == null ? 0L : parentIds.get(i), null));
childs.add(new VariableNode(session, treeTable, as3, new ArrayList<>(), 1, vars.get(i), parentIds == null ? 0L : parentIds.get(i), null, sort));
}
root = new VariableNode(session, treeTable, as3, new ArrayList<>(), 0, null, 0L, null, childs);
if (sort) {
childs.sort(new Comparator<VariableNode>() {
@Override
public int compare(VariableNode o1, VariableNode o2) {
return o1.var.name.compareTo(o2.var.name);
}
});
}
root = new VariableNode(session, treeTable, as3, new ArrayList<>(), 0, null, 0L, null, childs, sort);
root.loaded = true;
this.sort = sort;
}
@Override
@@ -1646,6 +1676,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
navIconsPanel.setLayout(new BoxLayout(navIconsPanel, BoxLayout.X_AXIS));
final JToggleButton sortButton = new JToggleButton(View.getIcon("sort16"));
sortButton.setMargin(new Insets(3, 3, 3, 3));
sortButton.setToolTipText(AppStrings.translate("sort.alphabetically"));
navIconsPanel.add(sortButton);
//JLabel navigatorLabel = new JLabel(AppStrings.translate("traits"), JLabel.CENTER);
//navigatorPanel.add(navigatorLabel, BorderLayout.NORTH);

View File

@@ -669,3 +669,6 @@ config.description.showDebugListenInfo = Displays some info about how debug list
config.name.as3QNameObfuscatedPropsInSquareBrackets = Show AS3 obfuscated QName properties in brackets
config.description.as3QNameObfuscatedPropsInSquareBrackets = Displays AS3 obfuscated QName properties as strings in brackets.
#after 25.1.2
config.name.sortDebugVariablesAlphabetically = Sort variables in the debugger
config.description.sortDebugVariablesAlphabetically = Sorts variables in the debugger alphabetically.

View File

@@ -668,3 +668,7 @@ config.description.showDebugListenInfo = Zobraz\u00ed informace o tom jak naslou
config.name.as3QNameObfuscatedPropsInSquareBrackets = Zobrazit AS3 obfuskovan\u00e9 QName vlastnosti v hranat\u00fdch z\u00e1vork\u00e1ch
config.description.as3QNameObfuscatedPropsInSquareBrackets = Zobraz\u00ed AS3 obfuskovan\u00e9 QName vlastnosti v \u0159et\u011bzc\u00edch v hranat\u00fdch z\u00e1vork\u00e1ch.
#after 25.1.2
config.name.sortDebugVariablesAlphabetically = Se\u0159adit prom\u011bnn\u00e9 v debuggeru
config.description.sortDebugVariablesAlphabetically = Se\u0159ad\u00ed prom\u011bnn\u00e9 v debuggeru abecedn\u011b.

View File

@@ -597,3 +597,7 @@ config.description.showDebugListenInfo = Zeigt einige Informationen dar\u00fcber
config.name.as3QNameObfuscatedPropsInSquareBrackets = Obfuskierte AS3-QName-Eigenschaften in eckigen Klammern anzeigen
config.description.as3QNameObfuscatedPropsInSquareBrackets = Zeigt obfuskierte AS3-QName-Eigenschaften als Zeichenketten in eckigen Klammern an.
#after 25.1.2
config.name.sortDebugVariablesAlphabetically = Variablen im Debugger alphabetisch sortieren
config.description.sortDebugVariablesAlphabetically = Sortiert die Variablen im Debugger alphabetisch.

View File

@@ -668,3 +668,7 @@ config.description.showDebugListenInfo = Zobraz\u00ed niektor\u00e9 inform\u00e1
config.name.as3QNameObfuscatedPropsInSquareBrackets = Zobrazi\u0165 AS3 obfuskovan\u00e9 QName vlastnosti v z\u00e1tvork\u00e1ch
config.description.as3QNameObfuscatedPropsInSquareBrackets = Zobrazuje AS3 obfuskovan\u00e9 QName vlastnosti ako re\u0165azce v hranat\u00fdch z\u00e1tvork\u00e1ch.
#after 25.1.2
config.name.sortDebugVariablesAlphabetically = Zoradi\u0165 premenn\u00e9 v ladi\u010di abecedne
config.description.sortDebugVariablesAlphabetically = Zorad\u00ed premenn\u00e9 v ladi\u010di abecedne.

View File

@@ -1138,3 +1138,4 @@ variables.header.watches = Watches
menu.debugging.debug.stopListening = Stop listening
menu.debugging.debug.disconnectSession = Disconnect session
sort.alphabetically = Sort alphabetically

View File

@@ -1136,4 +1136,6 @@ variables.header.watches = Sledov\u00e1n\u00ed
#after 25.1.2
menu.debugging.debug.stopListening = Zastavit naslouch\u00e1n\u00ed
menu.debugging.debug.disconnectSession = Odpojit sezen\u00ed
menu.debugging.debug.disconnectSession = Odpojit sezen\u00ed
sort.alphabetically = Se\u0159adit abecedn\u011b

View File

@@ -997,4 +997,6 @@ variables.header.watches = \u00dcberwachungen
#after 25.1.2
menu.debugging.debug.stopListening = Listening beenden
menu.debugging.debug.disconnectSession = Sitzung trennen
menu.debugging.debug.disconnectSession = Sitzung trennen
sort.alphabetically = Alphabetisch sortieren

View File

@@ -1136,4 +1136,6 @@ variables.header.watches = Sledovania
#after 25.1.2
menu.debugging.debug.stopListening = Zastavi\u0165 po\u010d\u00favanie
menu.debugging.debug.disconnectSession = Odpoji\u0165 sedenie
menu.debugging.debug.disconnectSession = Odpoji\u0165 sedenie
sort.alphabetically = Zoradi\u0165 abecedne