Merge pull request #41 from jindrapetrik/debuggerimprovements

Debuggerimprovements
This commit is contained in:
Jindra Petřík
2016-09-14 22:57:20 +02:00
committed by GitHub
4 changed files with 386 additions and 135 deletions

View File

@@ -26,20 +26,30 @@ import de.hameister.treetable.MyTreeTable;
import de.hameister.treetable.MyTreeTableModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.table.DefaultTableModel;
@@ -105,6 +115,9 @@ public class DebugPanel extends JPanel {
View.expandTreeNodes(tt.getTree(), expanded);
for (int i = 0; i < selRows.length; i++) {
selRows[i] = tt.getTree().getRowForPath(selPaths[i]);
if (selRows[i] == -1) {
continue;
}
if (i == 0) {
tt.setRowSelectionInterval(selRows[i], selRows[i]);
} else {
@@ -112,6 +125,14 @@ public class DebugPanel extends JPanel {
}
}
int ROW_HEIGHT = new JLabel("A").getPreferredSize().height;
JTree tree = tt.getTree();
tree.setRowHeight(ROW_HEIGHT);
for (int i = 0; i < tt.getRowCount(); i++) {
tt.setRowHeight(i, ROW_HEIGHT);
}
}
public DebugPanel() {
@@ -119,74 +140,81 @@ public class DebugPanel extends JPanel {
debugRegistersTable = new MyTreeTable(new ABCPanel.VariablesTableModel(debugRegistersTable, new ArrayList<>(), new ArrayList<>()), false);
debugLocalsTable = new MyTreeTable(new ABCPanel.VariablesTableModel(debugLocalsTable, new ArrayList<>(), new ArrayList<>()), false);
//Add watch feature, commented out. I tried it, but without success. I can't add watch in Flash Pro or FDB either. :-(
/*
//locales
debug.watch.add = Add watch to %name%
debug.watch.add.read = Read
debug.watch.add.write = Write
debug.watch.add.readwrite = Read+Write
MouseAdapter watchHandler = new MouseAdapter() {
error.debug.watch.add = Cannot add watch to this variable.
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
dopop(e);
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
dopop(e);
}
}
MouseAdapter watchHandler = new MouseAdapter() {
private void dopop(MouseEvent e) {
if (debugLocalsTable.getSelectedRow() == -1) {
return;
}
Object node = debugLocalsTable.getTree().getPathForRow(debugLocalsTable.getSelectedRow()).getLastPathComponent();
Variable v;
ABCPanel.VariableNode vn;
if (node instanceof ABCPanel.VariableNode) {
vn = ((ABCPanel.VariableNode) node);
v = vn.var;
} else {
return;
}
@Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
dopop(e);
}
}
JPopupMenu pm = new JPopupMenu();
//TODO!!
/*if (v.typeName != null && v.typeName.startsWith("flash.utils::ByteArray")) {
JMenu exportMenu = new JMenu("Export %name%".replace("%name%", v.name));
JMenuItem exportByteArray = new JMenuItem("Export bytearray");
exportByteArray.addActionListener((ActionEvent e1) -> {
Main.dumpBytes(v);
});
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
dopop(e);
}
}
exportMenu.add(exportByteArray);
pm.add(exportMenu);
}*/
long watchParentId = vn.parentObjectId;
private void dopop(MouseEvent e) {
if (debugLocalsTable.getSelectedRow() == -1) {
return;
}
Variable v = ((ABCPanel.VariablesTableModel) debugLocalsTable.getModel()).getVars().get(debugLocalsTable.getSelectedRow());
final long v_id = ((ABCPanel.VariablesTableModel) debugLocalsTable.getModel()).getVarIds().get(debugLocalsTable.getSelectedRow());
JMenu addWatchMenu = new JMenu(AppStrings.translate("debug.watch.add").replace("%name%", v.name));
JMenuItem watchReadMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.read"));
watchReadMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(v, watchParentId, true, false)) {
View.showMessageDialog(DebugPanel.this, AppStrings.translate("error.debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
});
JMenuItem watchWriteMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.write"));
watchWriteMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(v, watchParentId, false, true)) {
View.showMessageDialog(DebugPanel.this, AppStrings.translate("error.debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
});
JMenuItem watchReadWriteMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.readwrite"));
watchReadWriteMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(v, watchParentId, true, true)) {
View.showMessageDialog(DebugPanel.this, AppStrings.translate("error.debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
});
JPopupMenu pm = new JPopupMenu();
JMenu addWatchMenu = new JMenu(AppStrings.translate("debug.watch.add").replace("%name%", v.name));
JMenuItem watchReadMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.read"));
watchReadMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(v, v_id, true, false)) {
View.showMessageDialog(DebugPanel.this, AppStrings.translate("debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
});
JMenuItem watchWriteMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.write"));
watchWriteMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(v, v_id, false, true)) {
View.showMessageDialog(DebugPanel.this, AppStrings.translate("debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
});
JMenuItem watchReadWriteMenuItem = new JMenuItem(AppStrings.translate("debug.watch.add.readwrite"));
watchReadWriteMenuItem.addActionListener((ActionEvent e1) -> {
if (!Main.addWatch(v, v_id, true, true)) {
View.showMessageDialog(DebugPanel.this, AppStrings.translate("debug.watch.add"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
});
addWatchMenu.add(watchReadMenuItem);
addWatchMenu.add(watchWriteMenuItem);
addWatchMenu.add(watchReadWriteMenuItem);
pm.add(addWatchMenu);
pm.show(e.getComponent(), e.getX(), e.getY());
}
};
addWatchMenu.add(watchReadMenuItem);
addWatchMenu.add(watchWriteMenuItem);
addWatchMenu.add(watchReadWriteMenuItem);
pm.add(addWatchMenu);
debugLocalsTable.addMouseListener(watchHandler);
pm.show(e.getComponent(), e.getX(), e.getY());
}
};
debugLocalsTable.addMouseListener(watchHandler);
debugScopeTable.addMouseListener(watchHandler);
*/
//debugScopeTable.addMouseListener(watchHandler);
debugScopeTable = new MyTreeTable(new ABCPanel.VariablesTableModel(debugScopeTable, new ArrayList<>(), new ArrayList<>()), false);
callStackTable = new JTable();
@@ -281,6 +309,33 @@ public class DebugPanel extends JPanel {
add(varTabs, BorderLayout.CENTER);
}
/* private void getVariableList() {
// make sure the player has stopped and send our message awaiting a response
Main.getDebugHandler().getVariable(VariableConstants.GLOBAL_ID, TOOL_TIP_TEXT_KEY, loading)
requestFrame(0, isolateId); // our 0th frame gets our local context
// now let's request all of the special variables too
getValueWorker(VariableConstants.GLOBAL_ID, isolateId);
getValueWorker(VariableConstants.THIS_ID, isolateId);
getValueWorker(VariableConstants.ROOT_ID, isolateId);
// request as many levels as we can get
int i = 0;
Value v = null;
do {
v = getValueWorker(Value.LEVEL_ID - i, isolateId);
} while (i++ < 128 && v != null);
// now that we've primed the DManager we can request the base variable whose
// children are the variables that are available
v = m_manager.getValue(Value.BASE_ID, isolateId);
if (v == null) {
throw new VersionException();
}
return v.getMembers(this);
}*/
public void refresh() {
View.execInEventDispatch(new Runnable() {

View File

@@ -19,6 +19,8 @@ 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.VariableType;
import com.jpexs.debugger.flash.messages.in.InCallFunction;
import com.jpexs.decompiler.flash.ApplicationInfo;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.SWF;
@@ -206,6 +208,29 @@ public class Main {
return runProcess != null && !runProcessDebug;
}
/**
* FIXME!
*
* @param v
*/
public static synchronized void dumpBytes(Variable v) {
InCallFunction icf;
try {
long objectId = 0l;
if ((v.vType == VariableType.OBJECT || v.vType == VariableType.MOVIECLIP)) {
objectId = (Long) v.value;
}
Object oldPos = getDebugHandler().getVariable(objectId, "position", true).parent.value;
getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, 0);
icf = getDebugHandler().callFunction(false, "readUTF", v, new ArrayList<>());
System.out.println("Result=" + icf.variables.get(0).value);
getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, oldPos);
} catch (DebuggerHandler.ActionScriptException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static synchronized boolean addWatch(Variable v, long v_id, boolean watchRead, boolean watchWrite) {
DebuggerCommands.Watch w = getDebugHandler().addWatch(v, v_id, watchRead, watchWrite);
return w != null;

View File

@@ -309,25 +309,23 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
public List<VariableNode> path = new ArrayList<>();
public Long parentId;
public Variable var;
public Variable varInsideGetter;
public Long parentObjectId;
public int level;
public Variable thisVar;
public Variable trait;
public long traitId;
public Variable thisTrait;
public long thisTraitId;
private List<Variable> childs;
private List<Variable> childTraits;
private List<VariableNode> childs;
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + Objects.hashCode(this.parentId);
hash = 53 * hash + (this.thisVar == null ? 0 : Objects.hashCode(this.thisVar.name));
hash = 53 * hash + Objects.hashCode(this.parentObjectId);
hash = 53 * hash + (this.var == null ? 0 : Objects.hashCode(this.var.name));
return hash;
}
@@ -343,19 +341,19 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
return false;
}
final VariableNode other = (VariableNode) obj;
if (!Objects.equals(this.parentId, other.parentId)) {
if (!Objects.equals(this.parentObjectId, other.parentObjectId)) {
return false;
}
if (this.thisVar == null && other.thisVar == null) {
if (this.var == null && other.var == null) {
return true;
}
if (this.thisVar == null) {
if (this.var == null) {
return false;
}
if (other.thisVar == null) {
if (other.var == null) {
return false;
}
return Objects.equals(this.thisVar.name, other.thisVar.name);
return Objects.equals(this.var.name, other.var.name);
}
public boolean loaded = false;
@@ -369,35 +367,41 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
if (level == 0) {
return "root"; //TODO: localize?
}
return thisVar.name;
return var.name;
}
private void refresh() {
if (path.size() > 1) {
path.get(path.size() - 2).reloadChildren();
} else {
//Main.getDebugHandler().refreshFrame();
//InFrame fr = Main.getDebugHandler().getFrame();
}
}
private void reloadChildren() {
childs = new ArrayList<>();
childTraits = new ArrayList<>();
InGetVariable igv = Main.getDebugHandler().getVariable(parentId, thisVar.name, true);
if ("".equals(var.name)) {
return;
}
InGetVariable igv;
if (thisVar.vType != VariableType.FUNCTION || ((thisVar.flags & VariableFlags.HAS_GETTER) > 0)) {
if (parentId != 0) {
thisVar = igv.parent;
}
Long objectId = varToObjectId(varInsideGetter);
if (parentObjectId == 0 && objectId != 0) {
igv = Main.getDebugHandler().getVariable(objectId, "", true);
} else {
igv = Main.getDebugHandler().getVariable(parentObjectId, var.name, true);
}
//current var is getter function - set it to value really got
//if ((var.flags & VariableFlags.HAS_GETTER) > 0)
{
varInsideGetter = igv.parent;
}
Variable curTrait = null;
for (int i = 0; i < igv.childs.size(); i++) {
if (!isTraits(igv.childs.get(i))) {
childs.add(igv.childs.get(i));
childTraits.add(curTrait);
Long parentObjectId = varToObjectId(var);
childs.add(new VariableNode(path, level + 1, igv.childs.get(i), parentObjectId, curTrait));//igv.parentId
} else {
curTrait = igv.childs.get(i);
}
@@ -413,14 +417,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
public VariableNode getChildAt(int index) {
ensureLoaded();
Long parId = 0L;
if (thisVar != null && (thisVar.vType == VariableType.OBJECT || thisVar.vType == VariableType.MOVIECLIP)) {
parId = (Long) thisVar.value;
}
VariableNode vn = new VariableNode(level + 1, childs.get(index), parId, childTraits.get(index));
vn.path.addAll(path);
vn.path.add(vn);
return vn;
return childs.get(index);
}
public int getChildCount() {
@@ -428,30 +425,43 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
return childs.size();
}
public VariableNode(int level, Variable thisVar, Long parentId, Variable thisTrait) {
this.parentId = parentId;
this.thisVar = thisVar;
public VariableNode(List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait) {
this.var = var;
this.parentObjectId = parentObjectId;
this.level = level;
this.thisTrait = thisTrait;
this.trait = trait;
this.path.addAll(parentPath);
this.path.add(this);
loaded = false;
}
public VariableNode(int level, Variable thisVar, Long parentId, Variable thisTrait, Long thisTraitId, List<Variable> vars, List<Variable> varTraits) {
this.parentId = parentId;
this.thisVar = thisVar;
public VariableNode(List<VariableNode> parentPath, int level, Variable var, Long parentObjectId, Variable trait, List<VariableNode> subvars) {
this.var = var;
this.parentObjectId = parentObjectId;
this.level = level;
this.childs = vars;
this.trait = trait;
this.thisTrait = thisTrait;
this.childTraits = varTraits;
this.childs = subvars;
this.path.addAll(parentPath);
this.path.add(this);
for (VariableNode vn : subvars) {
vn.path.clear();
vn.path.addAll(this.path);
vn.path.add(vn);
}
loaded = true;
}
}
public static Long varToObjectId(Variable var) {
if (var != null && (var.vType == VariableType.OBJECT)) //|| var.vType == VariableType.MOVIECLIP)) {
{
return (Long) var.value;
} else {
return 0L;
}
}
public static class VariablesTableModel implements MyTreeTableModel {
List<TableModelListener> tableListeners = new ArrayList<>();
@@ -474,27 +484,49 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
public VariablesTableModel(MyTreeTable ttable, List<Variable> vars, List<Long> parentIds) {
this.ttable = ttable;
List<Variable> varTraits = new ArrayList<>();
List<VariableNode> childs = new ArrayList<>();
for (int i = 0; i < vars.size(); i++) {
varTraits.add(null);
childs.add(new VariableNode(new ArrayList<>(), 1, vars.get(i), 0L/*parentIds.get(i)*/, null));
}
root = new VariableNode(0, null, 0L, null, 0L, vars, varTraits);
root = new VariableNode(new ArrayList<>(), 0, null, 0L, null, childs);
}
@Override
public int getColumnCount() {
return 3;
return 6;
}
public Variable getVarAt(Object node) {
if (node == root) {
return null;
}
return ((VariableNode) node).var;
}
private static final int COLUMN_NAME = 0;
private static final int COLUMN_TRAIT = 1;
private static final int COLUMN_SCOPE = 2;
private static final int COLUMN_FLAGS = 3;
private static final int COLUMN_TYPE = 4;
private static final int COLUMN_VALUE = 5;
@Override
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case 0:
case COLUMN_NAME:
return AppStrings.translate("variables.column.name");
case 1:
case COLUMN_SCOPE:
return AppStrings.translate("variables.column.scope");
case COLUMN_FLAGS:
return AppStrings.translate("variables.column.flags");
case COLUMN_TYPE:
return AppStrings.translate("variables.column.type");
case 2:
case COLUMN_VALUE:
return AppStrings.translate("variables.column.value");
case COLUMN_TRAIT:
return AppStrings.translate("variables.column.trait");
default:
return null;
}
@@ -502,12 +534,118 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
if (columnIndex == COLUMN_NAME) {
return MyTreeTableModel.class;
}
return String.class;
}
private String flagsToScopeString(int flags) {
int scope = flags & VariableFlags.SCOPE_MASK;
switch (scope) {
case VariableFlags.PRIVATE_SCOPE:
return "private";
case VariableFlags.PROTECTED_SCOPE:
return "protected";
case VariableFlags.PUBLIC_SCOPE:
return "public";
case VariableFlags.NAMESPACE_SCOPE:
return "namespace";
case VariableFlags.INTERNAL_SCOPE:
return "internal";
default:
return "?";
}
}
/*
1 DONT_ENUMERATE
2 ?
4 READ_ONLY
8 ?
16 ?
32 IS_LOCAL
64
128
256
512
1024
2048
4096
8192
16384
32768
65536 IS_ARGUMENT
131072 IS_DYNAMIC
262144 IS_EXCEPTION
524288 HAS_GETTER
1048576 HAS_SETTER
2097152 IS_STATIC
4194304 IS_CONST
8388608,16777216,33554432 SCOPE
67108864 IS_CLASS
*/
private String flagsToString(int flags) {
Integer unknownFlags[] = new Integer[]{
2,
8,
16,
64,
128,
256,
512,
1024,
2048,
4096,
8192,
16384,
32768
};
List<String> flagsStr = new ArrayList<>();
if ((flags & VariableFlags.DONT_ENUMERATE) > 0) {
flagsStr.add("dontEnumerate");
}
for (Integer f : unknownFlags) {
if ((flags & f) > 0) {
flagsStr.add("unk" + f);
}
}
if ((flags & VariableFlags.HAS_GETTER) > 0) {
flagsStr.add("get");
}
if ((flags & VariableFlags.HAS_SETTER) > 0) {
flagsStr.add("set");
}
if ((flags & VariableFlags.READ_ONLY) > 0) {
flagsStr.add("readonly");
}
if ((flags & VariableFlags.IS_CONST) > 0) {
flagsStr.add("const");
}
if ((flags & VariableFlags.IS_DYNAMIC) > 0) {
flagsStr.add("dynamic");
}
if ((flags & VariableFlags.IS_CLASS) > 0) {
flagsStr.add("class");
}
if ((flags & VariableFlags.IS_ARGUMENT) > 0) {
flagsStr.add("argument");
}
if ((flags & VariableFlags.IS_EXCEPTION) > 0) {
flagsStr.add("exception");
}
if ((flags & VariableFlags.IS_LOCAL) > 0) {
flagsStr.add("local");
}
if ((flags & VariableFlags.IS_STATIC) > 0) {
flagsStr.add("static");
}
return String.join(", ", flagsStr);
}
@Override
public Object getValueAt(Object node, int columnIndex) {
if (node == root) {
@@ -516,39 +654,59 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
}
return "";
}
Variable v = ((VariableNode) node).thisVar;
Variable var = ((VariableNode) node).var;
Variable var_getter = ((VariableNode) node).varInsideGetter;
Variable trait = ((VariableNode) node).trait;
boolean readOnly = (var.flags & VariableFlags.READ_ONLY) > 0;
boolean hasGetter = (var.flags & VariableFlags.HAS_GETTER) > 0;
boolean hasSetter = (var.flags & VariableFlags.HAS_SETTER) > 0;
boolean onlySetter = hasSetter && !hasGetter;
//String flagStr = flagsToString(var.flags);
Variable val = var;
if (var_getter != null) {
val = var_getter;
}
switch (columnIndex) {
case 0:
return v.name;
case 1:
String typeStr = v.getTypeAsStr();
case COLUMN_NAME:
return var.name;
case COLUMN_SCOPE:
return flagsToScopeString(var.flags);
case COLUMN_FLAGS:
return flagsToString(var.flags);
case COLUMN_TYPE:
String typeStr = val.getTypeAsStr();
if ("Object".equals(typeStr)) {
typeStr = v.className;
typeStr = val.className;
}
if ("Object".equals(typeStr)) {
typeStr = v.typeName;
typeStr = val.typeName;
}
return typeStr;
case 2:
switch (v.vType) {
case COLUMN_VALUE:
switch (val.vType) {
case VariableType.OBJECT:
case VariableType.MOVIECLIP:
case VariableType.FUNCTION:
return v.getTypeAsStr() + "(" + v.value + ")";
return var.getTypeAsStr() + "(" + val.value + ")";
case VariableType.STRING:
return "\"" + Helper.escapeActionScriptString("" + v.value) + "\"";
return "\"" + Helper.escapeActionScriptString("" + val.value) + "\"";
default:
return EcmaScript.toString(v.value);
return EcmaScript.toString(val.value);
}
case COLUMN_TRAIT:
if (trait != null) {
return trait.name;
}
return "";
}
return null;
}
@Override
public boolean isCellEditable(Object node, int column) {
return column == 0 || (column == 2 && node != root && ((VariableNode) node).thisVar.isPrimitive);
return column == COLUMN_NAME || (column == COLUMN_VALUE && node != root && ((VariableNode) node).var.isPrimitive);
}
@Override
@@ -584,7 +742,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
default:
return;
}
Main.getDebugHandler().setVariable(((VariableNode) node).parentId, ((VariableNode) node).thisVar.name, valType, symb.value);
Main.getDebugHandler().setVariable(((VariableNode) node).parentObjectId, ((VariableNode) node).var.name, valType, symb.value);
//((VariableNode) node).refresh();
Object[] path = new Object[((VariableNode) node).path.size()];
for (int i = 0; i < path.length; i++) {
@@ -1238,8 +1396,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
View.showMessageDialog(this, sb.toString(), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
}
decompiledTextArea.requestFocus();
} catch (Throwable ex) {
Logger.getLogger(ABCPanel.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(ABCPanel.class
.getName()).log(Level.SEVERE, null, ex);
}
}

View File

@@ -758,4 +758,15 @@ abc.detail.specialmethod.instanceinitializer = Instance initializer
abc.detail.innerfunction = Inner function
button.edit.script.decompiled = Edit ActionScript
button.edit.script.disassembled = Edit P-code
button.edit.script.disassembled = Edit P-code
debug.watch.add = Add watch to %name%
debug.watch.add.read = Read
debug.watch.add.write = Write
debug.watch.add.readwrite = Read+Write-
error.debug.watch.add = Cannot add watch to this variable.
variables.column.scope = Scope
variables.column.flags = Flags
variables.column.trait = Trait