Debugger - display variables in the tree structure

Set variables while debugging
This commit is contained in:
Jindra Petřík
2015-12-15 09:48:51 +01:00
parent 2377eef49d
commit 33fdfcc0ac
28 changed files with 2704 additions and 63 deletions

5
.gitignore vendored
View File

@@ -65,4 +65,7 @@ hs_err_pid*.log
/libsrc/cmykjpeg/nbproject/private/
/libsrc/Plugins/nbproject/private/
/libsrc/Plugins/build/
/libsrc/Plugins/dist/
/libsrc/Plugins/dist/
/libsrc/treetable/nbproject/private/
/libsrc/treetable/build/
/libsrc/treetable/dist/

Binary file not shown.

BIN
lib/treetable.jar Normal file

Binary file not shown.

View File

@@ -191,7 +191,12 @@ is divided into following sections:
</not>
</and>
</condition>
<property name="javac.fork" value="${jdkBug6558476}"/>
<condition else="false" property="javac.fork">
<or>
<istrue value="${jdkBug6558476}"/>
<istrue value="${javac.external.vm}"/>
</or>
</condition>
<property name="jar.index" value="false"/>
<property name="jar.index.metainf" value="${jar.index}"/>
<property name="copylibs.rebase" value="true"/>
@@ -217,6 +222,7 @@ is divided into following sections:
<condition else="" property="testng.debug.mode" value="-mixed">
<istrue value="${junit+testng.available}"/>
</condition>
<property name="java.failonerror" value="true"/>
</target>
<target name="-post-init">
<!-- Empty placeholder for easier customization. -->
@@ -693,7 +699,7 @@ is divided into following sections:
<sequential>
<property environment="env"/>
<resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
<java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
<java classname="@{classname}" dir="${profiler.info.dir}" failonerror="${java.failonerror}" fork="true" jvm="${profiler.info.jvm}">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg value="${profiler.info.jvmargs.agent}"/>
<jvmarg line="${profiler.info.jvmargs}"/>
@@ -768,7 +774,7 @@ is divided into following sections:
<attribute default="${debug.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg line="${debug-args-line}"/>
<jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
@@ -795,7 +801,7 @@ is divided into following sections:
<attribute default="jvm" name="jvm"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
<redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>

View File

@@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=8064a381@1.75.2.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=73f9688e
nbproject/build-impl.xml.script.CRC32=de1179e8
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48
nbproject/build-impl.xml.script.CRC32=ce0b030d
nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48

View File

@@ -189,7 +189,12 @@ is divided into following sections:
</not>
</and>
</condition>
<property name="javac.fork" value="${jdkBug6558476}"/>
<condition else="false" property="javac.fork">
<or>
<istrue value="${jdkBug6558476}"/>
<istrue value="${javac.external.vm}"/>
</or>
</condition>
<property name="jar.index" value="false"/>
<property name="jar.index.metainf" value="${jar.index}"/>
<property name="copylibs.rebase" value="true"/>
@@ -215,6 +220,7 @@ is divided into following sections:
<condition else="" property="testng.debug.mode" value="-mixed">
<istrue value="${junit+testng.available}"/>
</condition>
<property name="java.failonerror" value="true"/>
</target>
<target name="-post-init">
<!-- Empty placeholder for easier customization. -->
@@ -680,7 +686,7 @@ is divided into following sections:
<sequential>
<property environment="env"/>
<resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
<java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
<java classname="@{classname}" dir="${profiler.info.dir}" failonerror="${java.failonerror}" fork="true" jvm="${profiler.info.jvm}">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg value="${profiler.info.jvmargs.agent}"/>
<jvmarg line="${profiler.info.jvmargs}"/>
@@ -755,7 +761,7 @@ is divided into following sections:
<attribute default="${debug.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg line="${debug-args-line}"/>
<jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
@@ -782,7 +788,7 @@ is divided into following sections:
<attribute default="jvm" name="jvm"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
<jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
<jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
<redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>

View File

@@ -4,5 +4,5 @@ nbbuild.xml.stylesheet.CRC32=8064a381@1.74.2.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=0a5363c8
nbproject/build-impl.xml.script.CRC32=13f57099
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.2.48
nbproject/build-impl.xml.script.CRC32=6f75ce45
nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="treetable" default="default" basedir=".">
<description>Builds, tests, and runs the project treetable.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="treetable-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
build.xml.data.CRC32=3ded4556
build.xml.script.CRC32=4673fb60
build.xml.stylesheet.CRC32=8064a381@1.75.2.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=3ded4556
nbproject/build-impl.xml.script.CRC32=646636b1
nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48

View File

@@ -0,0 +1,73 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processor.options=
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/treetable.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
javac.source=1.8
javac.target=1.8
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=de.hameister.treetable.TreeTableMain
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>treetable</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@@ -0,0 +1,91 @@
package de.hameister.treetable;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;
public abstract class MyAbstractTreeTableModel implements MyTreeTableModel {
protected Object root;
protected EventListenerList listenerList = new EventListenerList();
private static final int CHANGED = 0;
private static final int INSERTED = 1;
private static final int REMOVED = 2;
private static final int STRUCTURE_CHANGED = 3;
public MyAbstractTreeTableModel(Object root) {
this.root = root;
}
public Object getRoot() {
return root;
}
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
public void valueForPathChanged(TreePath path, Object newValue) {
}
/**
* Die Methode wird normalerweise nicht aufgerufen.
*/
public int getIndexOfChild(Object parent, Object child) {
return 0;
}
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
private void fireTreeNode(int changeType, Object source, Object[] path, int[] childIndices, Object[] children) {
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = new TreeModelEvent(source, path, childIndices, children);
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == TreeModelListener.class) {
switch (changeType) {
case CHANGED:
((TreeModelListener) listeners[i + 1]).treeNodesChanged(e);
break;
case INSERTED:
((TreeModelListener) listeners[i + 1]).treeNodesInserted(e);
break;
case REMOVED:
((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e);
break;
case STRUCTURE_CHANGED:
((TreeModelListener) listeners[i + 1]).treeStructureChanged(e);
break;
default:
break;
}
}
}
}
protected void fireTreeNodesChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(CHANGED, source, path, childIndices, children);
}
protected void fireTreeNodesInserted(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(INSERTED, source, path, childIndices, children);
}
protected void fireTreeNodesRemoved(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(REMOVED, source, path, childIndices, children);
}
protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(STRUCTURE_CHANGED, source, path, childIndices, children);
}
}

View File

@@ -0,0 +1,64 @@
package de.hameister.treetable;
import java.util.Date;
public class MyDataModel extends MyAbstractTreeTableModel {
// Spalten Name.
static protected String[] columnNames = {"Knotentext", "String", "Datum", "Integer"};
// Spalten Typen.
static protected Class<?>[] columnTypes = {MyTreeTableModel.class, String.class, Date.class, Integer.class};
public MyDataModel(MyDataNode rootNode) {
super(rootNode);
root = rootNode;
}
public Object getChild(Object parent, int index) {
return ((MyDataNode) parent).getChildren().get(index);
}
public int getChildCount(Object parent) {
return ((MyDataNode) parent).getChildren().size();
}
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public Class<?> getColumnClass(int column) {
return columnTypes[column];
}
public Object getValueAt(Object node, int column) {
switch (column) {
case 0:
return ((MyDataNode) node).getName();
case 1:
return ((MyDataNode) node).getCapital();
case 2:
return ((MyDataNode) node).getDeclared();
case 3:
return ((MyDataNode) node).getArea();
default:
break;
}
return null;
}
public boolean isCellEditable(Object node, int column) {
return true; // Important to activate TreeExpandListener
}
public void setValueAt(Object aValue, Object node, int column) {
}
}

View File

@@ -0,0 +1,56 @@
package de.hameister.treetable;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class MyDataNode {
private String name;
private String capital;
private Date declared;
private Integer area;
private List<MyDataNode> children;
public MyDataNode(String name, String capital, Date declared, Integer area, List<MyDataNode> children) {
this.name = name;
this.capital = capital;
this.declared = declared;
this.area = area;
this.children = children;
if (this.children == null) {
this.children = Collections.emptyList();
}
}
public String getName() {
return name;
}
public String getCapital() {
return capital;
}
public Date getDeclared() {
return declared;
}
public Integer getArea() {
return area;
}
public List<MyDataNode> getChildren() {
return children;
}
/**
* Knotentext vom JTree.
*/
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,51 @@
package de.hameister.treetable;
import java.awt.Dimension;
import javax.swing.JTable;
import javax.swing.plaf.basic.BasicTableUI;
public class MyTreeTable extends JTable {
private MyTreeTableCellRenderer tree;
private MyTreeTableModel treeTableModel;
public MyTreeTableCellRenderer getTree() {
return tree;
}
public MyTreeTableModel getTreeTableModel() {
return treeTableModel;
}
public void setTreeModel(MyTreeTableModel treeTableModel) {
// JTree erstellen.
this.treeTableModel = treeTableModel;
tree = new MyTreeTableCellRenderer(this, treeTableModel);
// Modell setzen.
super.setModel(new MyTreeTableModelAdapter(treeTableModel, tree));
// Gleichzeitiges Selektieren fuer Tree und Table.
MyTreeTableSelectionModel selectionModel = new MyTreeTableSelectionModel();
tree.setSelectionModel(selectionModel); //For the tree
setSelectionModel(selectionModel.getListSelectionModel()); //For the table
// Renderer fuer den Tree.
setDefaultRenderer(MyTreeTableModel.class, tree);
// Editor fuer die TreeTable
setDefaultEditor(MyTreeTableModel.class, new MyTreeTableCellEditor(tree, this));
// Kein Grid anzeigen.
setShowGrid(false);
// Keine Abstaende.
setIntercellSpacing(new Dimension(0, 0));
}
public MyTreeTable(MyTreeTableModel treeTableModel) {
super();
setUI(new BasicTableUI());
setTreeModel(treeTableModel);
}
}

View File

@@ -0,0 +1,44 @@
package de.hameister.treetable;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.table.TableCellEditor;
public class MyTreeTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private JTree tree;
private JTable table;
public MyTreeTableCellEditor(JTree tree, JTable table) {
this.tree = tree;
this.table = table;
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int r, int c) {
return tree;
}
public boolean isCellEditable(EventObject e) {
if (e instanceof MouseEvent) {
int colunm1 = 0;
MouseEvent me = (MouseEvent) e;
int doubleClick = 2;
MouseEvent newME = new MouseEvent(tree, me.getID(), me.getWhen(), me.getModifiers(), me.getX() - table.getCellRect(0, colunm1, true).x, me.getY(), doubleClick, me.isPopupTrigger());
tree.dispatchEvent(newME);
}
return false;
}
@Override
public Object getCellEditorValue() {
return null;
}
}

View File

@@ -0,0 +1,75 @@
package de.hameister.treetable;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.table.TableCellRenderer;
import javax.swing.tree.TreeModel;
public class MyTreeTableCellRenderer extends JTree implements TableCellRenderer {
/**
* Die letzte Zeile, die gerendert wurde.
*/
protected int visibleRow;
private MyTreeTable treeTable;
public MyTreeTableCellRenderer(MyTreeTable treeTable, TreeModel model) {
super(model);
setUI(new BasicTreeUI());
this.treeTable = treeTable;
// Setzen der Zeilenhoehe fuer die JTable
// Muss explizit aufgerufen werden, weil treeTable noch
// null ist, wenn super(model) setRowHeight aufruft!
setRowHeight(getRowHeight());
}
/**
* Tree und Table muessen die gleiche Hoehe haben.
*/
public void setRowHeight(int rowHeight) {
if (rowHeight > 0) {
super.setRowHeight(rowHeight);
if (treeTable != null && treeTable.getRowHeight() != rowHeight) {
treeTable.setRowHeight(getRowHeight());
}
}
}
/**
* Tree muss die gleiche Hoehe haben wie Table.
*/
public void setBounds(int x, int y, int w, int h) {
super.setBounds(x, 0, w, treeTable.getHeight());
}
/**
* Sorgt fuer die Einrueckung der Ordner.
*/
public void paint(Graphics g) {
g.translate(0, -visibleRow * getRowHeight());
super.paint(g);
}
/**
* Liefert den Renderer mit der passenden Hintergrundfarbe zurueck.
*/
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setBackground(table.getSelectionBackground());
} else {
setBackground(table.getBackground());
}
visibleRow = row;
return this;
}
}

View File

@@ -0,0 +1,58 @@
package de.hameister.treetable;
import javax.swing.tree.TreeModel;
public interface MyTreeTableModel extends TreeModel {
/**
* Returns the number of available columns.
*
* @return Number of Columns
*/
public int getColumnCount();
/**
* Returns the column name.
*
* @param column Column number
* @return Column name
*/
public String getColumnName(int column);
/**
* Returns the type (class) of a column.
*
* @param column Column number
* @return Class
*/
public Class<?> getColumnClass(int column);
/**
* Returns the value of a node in a column.
*
* @param node Node
* @param column Column number
* @return Value of the node in the column
*/
public Object getValueAt(Object node, int column);
/**
* Check if a cell of a node in one column is editable.
*
* @param node Node
* @param column Column number
* @return true/false
*/
public boolean isCellEditable(Object node, int column);
/**
* Sets a value for a node in one column.
*
* @param aValue New value
* @param node Node
* @param column Column number
*/
public void setValueAt(Object aValue, Object node, int column);
}

View File

@@ -0,0 +1,63 @@
package de.hameister.treetable;
import java.awt.Rectangle;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.tree.TreePath;
public class MyTreeTableModelAdapter extends AbstractTableModel {
JTree tree;
MyTreeTableModel treeTableModel;
public MyTreeTableModelAdapter(MyTreeTableModel treeTableModel, JTree tree) {
this.tree = tree;
this.treeTableModel = treeTableModel;
tree.addTreeExpansionListener(new TreeExpansionListener() {
public void treeExpanded(TreeExpansionEvent event) {
fireTableDataChanged();
}
public void treeCollapsed(TreeExpansionEvent event) {
fireTableDataChanged();
}
});
}
public int getColumnCount() {
return treeTableModel.getColumnCount();
}
public String getColumnName(int column) {
return treeTableModel.getColumnName(column);
}
public Class<?> getColumnClass(int column) {
return treeTableModel.getColumnClass(column);
}
public int getRowCount() {
return tree.getRowCount();
}
protected Object nodeForRow(int row) {
TreePath treePath = tree.getPathForRow(row);
return treePath.getLastPathComponent();
}
public Object getValueAt(int row, int column) {
return treeTableModel.getValueAt(nodeForRow(row), column);
}
public boolean isCellEditable(int row, int column) {
return treeTableModel.isCellEditable(nodeForRow(row), column);
}
public void setValueAt(Object value, int row, int column) {
treeTableModel.setValueAt(value, nodeForRow(row), column);
}
}

View File

@@ -0,0 +1,26 @@
package de.hameister.treetable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.tree.DefaultTreeSelectionModel;
public class MyTreeTableSelectionModel extends DefaultTreeSelectionModel {
public MyTreeTableSelectionModel() {
super();
getListSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
}
});
}
ListSelectionModel getListSelectionModel() {
return listSelectionModel;
}
}

View File

@@ -0,0 +1,84 @@
package de.hameister.treetable;
import java.awt.Container;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class TreeTableMain extends JFrame {
public TreeTableMain() {
super("Tree Table Demo");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(0, 1));
MyAbstractTreeTableModel treeTableModel = new MyDataModel(createDataStructure());
MyTreeTable myTreeTable = new MyTreeTable(treeTableModel);
Container cPane = getContentPane();
cPane.add(new JScrollPane(myTreeTable));
setSize(1000, 800);
setLocationRelativeTo(null);
}
private static MyDataNode createDataStructure() {
List<MyDataNode> children1 = new ArrayList<MyDataNode>();
children1.add(new MyDataNode("N12", "C12", new Date(), Integer.valueOf(50), null));
children1.add(new MyDataNode("N13", "C13", new Date(), Integer.valueOf(60), null));
children1.add(new MyDataNode("N14", "C14", new Date(), Integer.valueOf(70), null));
children1.add(new MyDataNode("N15", "C15", new Date(), Integer.valueOf(80), null));
List<MyDataNode> children2 = new ArrayList<MyDataNode>();
children2.add(new MyDataNode("N12", "C12", new Date(), Integer.valueOf(10), null));
children2.add(new MyDataNode("N13", "C13", new Date(), Integer.valueOf(20), children1));
children2.add(new MyDataNode("N14", "C14", new Date(), Integer.valueOf(30), null));
children2.add(new MyDataNode("N15", "C15", new Date(), Integer.valueOf(40), null));
List<MyDataNode> rootNodes = new ArrayList<MyDataNode>();
rootNodes.add(new MyDataNode("N1", "C1", new Date(), Integer.valueOf(10), children2));
rootNodes.add(new MyDataNode("N2", "C2", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N3", "C3", new Date(), Integer.valueOf(10), children2));
rootNodes.add(new MyDataNode("N4", "C4", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N5", "C5", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N6", "C6", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N7", "C7", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N8", "C8", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N9", "C9", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N10", "C10", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N11", "C11", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N12", "C7", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N13", "C8", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N14", "C9", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N15", "C10", new Date(), Integer.valueOf(10), children1));
rootNodes.add(new MyDataNode("N16", "C11", new Date(), Integer.valueOf(10), children1));
MyDataNode root = new MyDataNode("R1", "R1", new Date(), Integer.valueOf(10), rootNodes);
return root;
}
public static void main(final String[] args) {
Runnable gui = new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
new TreeTableMain().setVisible(true);
}
};
SwingUtilities.invokeLater(gui);
}
}

View File

@@ -308,7 +308,7 @@
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
<compilation-unit>
<package-root>src</package-root>
<classpath mode="compile">lib/LZMA.jar;lib/jna-3.5.1.jar;lib/jpproxy.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-6.2.jar;lib/jl1.0.1.jar;lib/nellymoser.jar;lib/gif.jar;lib/avi.jar;lib/ttf.jar;lib/jpacker.jar;lib/sfntly.jar;lib/gnujpdf.jar;libsrc/ffdec_lib/src;lib/tablelayout.jar;lib/jsyntaxpane-0.9.5.jar;lib/JavactiveX.jar;lib/flashdebugger.jar</classpath>
<classpath mode="compile">lib/LZMA.jar;lib/jna-3.5.1.jar;lib/jpproxy.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-6.2.jar;lib/jl1.0.1.jar;lib/nellymoser.jar;lib/gif.jar;lib/avi.jar;lib/ttf.jar;lib/jpacker.jar;lib/sfntly.jar;lib/gnujpdf.jar;libsrc/ffdec_lib/src;lib/tablelayout.jar;lib/jsyntaxpane-0.9.5.jar;lib/JavactiveX.jar;lib/flashdebugger.jar;lib/treetable.jar</classpath>
<built-to>build</built-to>
<built-to>javadoc</built-to>
<built-to>reports</built-to>

View File

@@ -21,6 +21,11 @@ import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.debugger.flash.messages.in.InFrame;
import com.jpexs.decompiler.flash.gui.DebuggerHandler.BreakListener;
import com.jpexs.decompiler.flash.gui.abc.ABCPanel;
import de.hameister.treetable.MyAbstractTreeTableModel;
import de.hameister.treetable.MyTreeTable;
import de.hameister.treetable.MyTreeTableModel;
import de.hameister.treetable.MyTreeTableModelAdapter;
import de.hameister.treetable.MyTreeTableSelectionModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
@@ -43,7 +48,15 @@ import javax.swing.JTable;
import javax.swing.JTextArea;
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.plaf.basic.BasicTableUI;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
/**
*
@@ -51,11 +64,11 @@ import javax.swing.table.DefaultTableModel;
*/
public class DebugPanel extends JPanel {
private JTable debugRegistersTable;
private MyTreeTable debugRegistersTable;
private JTable debugLocalsTable;
private MyTreeTable debugLocalsTable; //JTable debugLocalsTable;
private JTable debugScopeTable;
private MyTreeTable debugScopeTable;
private JTable callStackTable;
@@ -88,10 +101,34 @@ public class DebugPanel extends JPanel {
private SelectedTab selectedTab = null;
private void safeSetTreeModel(MyTreeTable tt, MyTreeTableModel tmodel) {
List<List<String>> expanded = View.getExpandedNodes(tt.getTree());
int selRows[] = tt.getSelectedRows();
TreePath selPaths[] = new TreePath[selRows.length];
for (int i = 0; i < selRows.length; i++) {
selPaths[i] = tt.getTree().getPathForRow(selRows[i]);
}
tt.setTreeModel(tmodel);
//tt.getTree().setRootVisible(false);
View.expandTreeNodes(tt.getTree(), expanded);
for (int i = 0; i < selRows.length; i++) {
selRows[i] = tt.getTree().getRowForPath(selPaths[i]);
if (i == 0) {
tt.setRowSelectionInterval(selRows[i], selRows[i]);
} else {
tt.addRowSelectionInterval(selRows[i], selRows[i]);
}
}
}
public DebugPanel() {
super(new BorderLayout());
debugRegistersTable = new JTable(new ABCPanel.VariablesTableModel(new ArrayList<>(), new ArrayList<>()));
debugLocalsTable = new JTable(new ABCPanel.VariablesTableModel(new ArrayList<>(), new ArrayList<>()));
debugRegistersTable = new MyTreeTable(new ABCPanel.VariablesTableModel(debugRegistersTable, new ArrayList<>(), new ArrayList<>()));
debugLocalsTable = new MyTreeTable(new ABCPanel.VariablesTableModel(debugLocalsTable, new ArrayList<>(), new ArrayList<>()));
//Add watch feature, commented out. I tried it, but without success. I can't add watch in Flash Pro or FDB either. :-(
/*
@@ -161,7 +198,7 @@ public class DebugPanel extends JPanel {
debugScopeTable.addMouseListener(watchHandler);
*/
debugScopeTable = new JTable(new ABCPanel.VariablesTableModel(new ArrayList<>(), new ArrayList<>()));
debugScopeTable = new MyTreeTable(new ABCPanel.VariablesTableModel(debugScopeTable, new ArrayList<>(), new ArrayList<>()));
callStackTable = new JTable();
stackTable = new JTable();
@@ -271,21 +308,56 @@ public class DebugPanel extends JPanel {
for (int i = 0; i < f.registers.size(); i++) {
regVarIds.add(0L);
}
debugRegistersTable.setModel(new ABCPanel.VariablesTableModel(f.registers, regVarIds));
safeSetTreeModel(debugRegistersTable, new ABCPanel.VariablesTableModel(debugRegistersTable, f.registers, regVarIds));
List<Variable> locals = new ArrayList<>();
locals.addAll(f.arguments);
locals.addAll(f.variables);
List<Long> localIds = new ArrayList<>();
localIds.addAll(f.argumentIds);
localIds.addAll(f.variableIds);
localIds.addAll(f.argumentFrameIds);
localIds.addAll(f.frameIds);
debugLocalsTable.setModel(new ABCPanel.VariablesTableModel(locals, localIds));
debugScopeTable.setModel(new ABCPanel.VariablesTableModel(f.scopeChain, f.scopeChainIds));
safeSetTreeModel(debugLocalsTable, new ABCPanel.VariablesTableModel(debugLocalsTable, locals, localIds));
safeSetTreeModel(debugScopeTable, new ABCPanel.VariablesTableModel(debugScopeTable, f.scopeChain, f.scopeChainFrameIds));
/*TableModelListener refreshListener = new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
Main.getDebugHandler().refreshFrame();
refresh();
}
};*/
TreeModelListener refreshListener = new TreeModelListener() {
@Override
public void treeNodesChanged(TreeModelEvent e) {
Main.getDebugHandler().refreshFrame();
refresh();
}
@Override
public void treeNodesInserted(TreeModelEvent e) {
Main.getDebugHandler().refreshFrame();
refresh();
}
@Override
public void treeNodesRemoved(TreeModelEvent e) {
Main.getDebugHandler().refreshFrame();
refresh();
}
@Override
public void treeStructureChanged(TreeModelEvent e) {
Main.getDebugHandler().refreshFrame();
refresh();
}
};
debugLocalsTable.getTreeTableModel().addTreeModelListener(refreshListener);
debugScopeTable.getTreeTableModel().addTreeModelListener(refreshListener);
} else {
debugRegistersTable.setModel(new DefaultTableModel());
debugLocalsTable.setModel(new DefaultTableModel());
debugScopeTable.setModel(new DefaultTableModel());
debugRegistersTable.setTreeModel(new ABCPanel.VariablesTableModel(debugRegistersTable, new ArrayList<>(), new ArrayList<>()));
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) {
@@ -325,13 +397,13 @@ public class DebugPanel extends JPanel {
varTabs.removeAll();
tabTypes.clear();
JPanel pa;
if (debugRegistersTable.getRowCount() > 0) {
if (debugRegistersTable.getRowCount() > 1 /*root*/) {
tabTypes.add(SelectedTab.REGISTERS);
pa = new JPanel(new BorderLayout());
pa.add(new JScrollPane(debugRegistersTable), BorderLayout.CENTER);
varTabs.addTab(AppStrings.translate("variables.header.registers"), pa);
}
if (debugLocalsTable.getRowCount() > 0) {
if (debugLocalsTable.getRowCount() > 1 /*root*/) {
tabTypes.add(SelectedTab.LOCALS);
pa = new JPanel(new BorderLayout());
@@ -339,7 +411,7 @@ public class DebugPanel extends JPanel {
varTabs.addTab(AppStrings.translate("variables.header.locals"), pa);
}
if (debugScopeTable.getRowCount() > 0) {
if (debugScopeTable.getRowCount() > 1 /*root*/) {
tabTypes.add(SelectedTab.SCOPECHAIN);
pa = new JPanel(new BorderLayout());

View File

@@ -22,6 +22,7 @@ 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.InAskBreakpoints;
import com.jpexs.debugger.flash.messages.in.InBreakAt;
import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
@@ -108,6 +109,40 @@ public class DebuggerHandler implements DebugConnectionListener {
return breakScriptName;
}
public InGetVariable getVariable(long parentId, String varName, boolean children) {
try {
return commands.getVariable(parentId, varName, true, children);
} catch (IOException ex) {
return null;
}
}
public void setVariable(long parentId, String varName, int valueType, Object value) {
try {
String svalue = "";
switch (valueType) {
case VariableType.STRING:
svalue = "" + value;
break;
case VariableType.NUMBER:
svalue = "" + value;
break;
case VariableType.BOOLEAN:
svalue = ((Boolean) value) ? "true" : "false";
break;
case VariableType.UNDEFINED:
svalue = "undefined";
break;
case VariableType.NULL:
svalue = "undefined";
break;
}
commands.setVariable(parentId, varName, valueType, svalue);
} catch (IOException ex) {
//ignore
}
}
public synchronized void removeBreakPoint(String scriptName, int line) {
if (isBreakpointInvalid(scriptName, line)) {
invalidBreakPointMap.get(scriptName).remove(line);
@@ -332,6 +367,17 @@ public class DebuggerHandler implements DebugConnectionListener {
clisteners.remove(l);
}
public synchronized void refreshFrame() {
if (!paused) {
return;
}
try {
frame = commands.getFrame(0);
} catch (IOException ex) {
//ignore
}
}
public synchronized InFrame getFrame() {
if (!paused) {
return null;

View File

@@ -519,6 +519,10 @@ public class Main {
loadFromMemoryFrame.setVisible(true);
}
public static void setVariable(long parentId, String varName, int valueType, Object value) {
getDebugHandler().setVariable(parentId, varName, valueType, value);
}
public static void setSubLimiter(boolean value) {
if (value) {
AVM2Code.toSourceLimit = Configuration.sublimiter.get();
@@ -1394,7 +1398,9 @@ public class Main {
@Override
public void disconnected() {
Main.mainFrame.getPanel().refreshBreakPoints();
if (Main.mainFrame != null && Main.mainFrame.getPanel() != null) {
Main.mainFrame.getPanel().refreshBreakPoints();
}
}
});
flashDebugger.addConnectionListener(debugHandler);

View File

@@ -17,6 +17,9 @@
package com.jpexs.decompiler.flash.gui.abc;
import com.jpexs.debugger.flash.Variable;
import com.jpexs.debugger.flash.VariableType;
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.abc.ABC;
import com.jpexs.decompiler.flash.abc.ClassPath;
@@ -38,6 +41,13 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.TraitMultinameUsage;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser;
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
import com.jpexs.decompiler.flash.action.parser.script.ActionScriptLexer;
import com.jpexs.decompiler.flash.action.parser.script.ParsedSymbol;
import com.jpexs.decompiler.flash.action.parser.script.SymbolType;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.AppDialog;
import com.jpexs.decompiler.flash.gui.AppStrings;
@@ -66,6 +76,9 @@ import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import de.hameister.treetable.MyTreeTable;
import de.hameister.treetable.MyTreeTableModel;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.FlowLayout;
@@ -82,8 +95,13 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
@@ -101,7 +119,11 @@ import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
import javax.swing.event.EventListenerList;
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;
import javax.swing.table.TableModel;
import javax.swing.text.Highlighter;
@@ -263,30 +285,167 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
decompiledTextArea.clearScript();
}
public static class VariablesTableModel implements TableModel {
public static class VariableNode {
// DebuggerHandler.VariableChangedListener varChangeListener;
List<TableModelListener> tableListeners = new ArrayList<>();
public List<VariableNode> path = new ArrayList<>();
private List<Variable> vars;
private List<Long> varIds;
public Long parentId;
public int level;
public List<Long> getVarIds() {
return varIds;
}
public Variable thisVar;
public Variable thisTrait;
public long thisTraitId;
public List<Variable> getVars() {
return new ArrayList<>(vars);
}
private List<Variable> childs;
private List<Variable> childTraits;
public VariablesTableModel(List<Variable> vars, List<Long> varIds) {
this.vars = vars;
this.varIds = varIds;
@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));
return hash;
}
@Override
public int getRowCount() {
return vars.size();
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final VariableNode other = (VariableNode) obj;
if (!Objects.equals(this.parentId, other.parentId)) {
return false;
}
if (this.thisVar == null && other.thisVar == null) {
return true;
}
if (this.thisVar == null) {
return false;
}
if (other.thisVar == null) {
return false;
}
return Objects.equals(this.thisVar.name, other.thisVar.name);
}
public boolean loaded = false;
private static boolean isTraits(Variable v) {
return (v.vType == VariableType.UNKNOWN && "traits".equals(v.typeName));
}
@Override
public String toString() {
if (level == 0) {
return "root"; //TODO: localize?
}
return thisVar.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() {
InGetVariable igv = Main.getDebugHandler().getVariable(parentId, thisVar.name, true);
childs = new ArrayList<>();
childTraits = new ArrayList<>();
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);
} else {
curTrait = igv.childs.get(i);
}
}
}
private void ensureLoaded() {
if (!loaded) {
reloadChildren();
loaded = true;
}
}
public VariableNode getChildAt(int index) {
ensureLoaded();
Long parId = 0L;
if (thisVar != null && thisVar.vType == VariableType.OBJECT) {
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;
}
public int getChildCount() {
ensureLoaded();
return childs.size();
}
public VariableNode(int level, Variable thisVar, Long parentId, Variable thisTrait) {
this.parentId = parentId;
this.thisVar = thisVar;
this.level = level;
this.thisTrait = thisTrait;
}
public VariableNode(int level, Variable thisVar, Long parentId, Variable thisTrait, Long thisTraitId, List<Variable> vars, List<Variable> varTraits) {
this.parentId = parentId;
this.thisVar = thisVar;
this.level = level;
this.childs = vars;
this.thisTrait = thisTrait;
this.childTraits = varTraits;
this.path.add(this);
loaded = true;
}
}
public static class VariablesTableModel implements MyTreeTableModel {
List<TableModelListener> tableListeners = new ArrayList<>();
VariableNode root;
private Map<VariableNode, List<VariableNode>> nodeCache = new HashMap<>();
protected EventListenerList listenerList = new EventListenerList();
private static final int CHANGED = 0;
private static final int INSERTED = 1;
private static final int REMOVED = 2;
private static final int STRUCTURE_CHANGED = 3;
private MyTreeTable ttable;
public VariablesTableModel(MyTreeTable ttable, List<Variable> vars, List<Long> parentIds) {
this.ttable = ttable;
List<Variable> varTraits = new ArrayList<>();
for (int i = 0; i < vars.size(); i++) {
varTraits.add(null);
}
root = new VariableNode(0, null, 0L, null, 0L, vars, varTraits);
}
@Override
@@ -310,17 +469,21 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
return MyTreeTableModel.class;
}
return String.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false; //columnIndex == 2; //TODO: edit variables
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Variable v = vars.get(rowIndex);
public Object getValueAt(Object node, int columnIndex) {
if (node == root) {
if (columnIndex == 0) {
return "root";
}
return "";
}
Variable v = ((VariableNode) node).thisVar;
switch (columnIndex) {
case 0:
@@ -335,24 +498,157 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
}
return typeStr;
case 2:
return v.getValueAsStr();
switch (v.vType) {
case VariableType.OBJECT:
case VariableType.MOVIECLIP:
case VariableType.FUNCTION:
return v.getTypeAsStr() + "(" + v.value + ")";
case VariableType.STRING:
return "\"" + Helper.escapeActionScriptString("" + v.value) + "\"";
default:
return "" + v.value;
}
}
return null;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
//Main.getDebugHandler().setVariableValue(rowIndex, "" + aValue);
public boolean isCellEditable(Object node, int column) {
return column == 0 || (column == 2 && node != root && ((VariableNode) node).thisVar.isPrimitive);
}
@Override
public void addTableModelListener(TableModelListener l) {
tableListeners.add(l);
public void setValueAt(Object aValue, Object node, int column) {
ActionScriptLexer lexer = new ActionScriptLexer(new StringReader("" + aValue));
ParsedSymbol symb;
try {
symb = lexer.lex();
ParsedSymbol f = lexer.yylex();
if (f.type != SymbolType.EOF) {
return;
}
} catch (IOException | ActionParseException ex) {
return;
}
int valType;
switch (symb.type) {
case DOUBLE:
valType = VariableType.NUMBER;
break;
case INTEGER:
valType = VariableType.NUMBER;
break;
case NULL:
valType = VariableType.NULL;
break;
case STRING:
valType = VariableType.STRING;
break;
case UNDEFINED:
valType = VariableType.UNDEFINED;
break;
default:
return;
}
Main.getDebugHandler().setVariable(((VariableNode) node).parentId, ((VariableNode) node).thisVar.name, valType, symb.value);
//((VariableNode) node).refresh();
Object path[] = new Object[((VariableNode) node).path.size()];
for (int i = 0; i < path.length; i++) {
path[i] = ((VariableNode) node).path.get(i);
}
valueForPathChanged(new TreePath(path), aValue);
//fireTreeNodesChanged(this, path, new int[0]/*removed*/, new Object[]{node});
}
@Override
public void removeTableModelListener(TableModelListener l) {
tableListeners.remove(l);
public Object getRoot() {
return root;
}
@Override
public Object getChild(Object parent, int index) {
return ((VariableNode) parent).getChildAt(index);
}
@Override
public int getChildCount(Object parent) {
int cnt = ((VariableNode) parent).getChildCount();
return cnt;
}
@Override
public boolean isLeaf(Object node) {
return getChildCount(node) == 0;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
fireTreeNodesChanged(ttable, path.getParentPath().getPath(), new int[0], new Object[]{path.getLastPathComponent()});
}
@Override
public int getIndexOfChild(Object parent, Object child) {
int cnt = getChildCount(parent);
for (int i = 0; i < cnt; i++) {
if (getChild(parent, i) == child) {
return i;
}
}
return -1;
}
@Override
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
protected void fireTreeNodesChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(CHANGED, source, path, childIndices, children);
}
protected void fireTreeNodesInserted(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(INSERTED, source, path, childIndices, children);
}
protected void fireTreeNodesRemoved(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(REMOVED, source, path, childIndices, children);
}
protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
fireTreeNode(STRUCTURE_CHANGED, source, path, childIndices, children);
}
private void fireTreeNode(int changeType, Object source, Object[] path, int[] childIndices, Object[] children) {
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = new TreeModelEvent(source, path, childIndices, children);
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == TreeModelListener.class) {
switch (changeType) {
case CHANGED:
((TreeModelListener) listeners[i + 1]).treeNodesChanged(e);
break;
case INSERTED:
((TreeModelListener) listeners[i + 1]).treeNodesInserted(e);
break;
case REMOVED:
((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e);
break;
case STRUCTURE_CHANGED:
((TreeModelListener) listeners[i + 1]).treeStructureChanged(e);
break;
default:
break;
}
}
}
}
}
@@ -650,6 +946,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
int dpos = decompiledTextArea.getLocalDeclarationOfPos(pos, new Reference<>(null));
if (dpos > -1) {
decompiledTextArea.setCaretPosition(dpos);
}
}
@@ -872,8 +1169,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
decompiledTextArea.gotoLine((int) ex.line);
decompiledTextArea.markError();
View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
} catch (Throwable ex) {
Logger.getLogger(ABCPanel.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(ABCPanel.class
.getName()).log(Level.SEVERE, null, ex);
}
}