diff --git a/.gitignore b/.gitignore index 613ec67bd..598439978 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,7 @@ hs_err_pid*.log /libsrc/cmykjpeg/nbproject/private/ /libsrc/Plugins/nbproject/private/ /libsrc/Plugins/build/ -/libsrc/Plugins/dist/ \ No newline at end of file +/libsrc/Plugins/dist/ +/libsrc/treetable/nbproject/private/ +/libsrc/treetable/build/ +/libsrc/treetable/dist/ \ No newline at end of file diff --git a/lib/flashdebugger.jar b/lib/flashdebugger.jar index 8b7a7a60c..6f2c726d5 100644 Binary files a/lib/flashdebugger.jar and b/lib/flashdebugger.jar differ diff --git a/lib/treetable.jar b/lib/treetable.jar new file mode 100644 index 000000000..610bf18d4 Binary files /dev/null and b/lib/treetable.jar differ diff --git a/libsrc/cmykjpeg/nbproject/build-impl.xml b/libsrc/cmykjpeg/nbproject/build-impl.xml index 4044e3e5a..ed218bcac 100644 --- a/libsrc/cmykjpeg/nbproject/build-impl.xml +++ b/libsrc/cmykjpeg/nbproject/build-impl.xml @@ -191,7 +191,12 @@ is divided into following sections: - + + + + + + @@ -217,6 +222,7 @@ is divided into following sections: + @@ -693,7 +699,7 @@ is divided into following sections: - + @@ -768,7 +774,7 @@ is divided into following sections: - + @@ -795,7 +801,7 @@ is divided into following sections: - + diff --git a/libsrc/cmykjpeg/nbproject/genfiles.properties b/libsrc/cmykjpeg/nbproject/genfiles.properties index 605d6401d..1b65a7437 100644 --- a/libsrc/cmykjpeg/nbproject/genfiles.properties +++ b/libsrc/cmykjpeg/nbproject/genfiles.properties @@ -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 diff --git a/libsrc/jpproxy/nbproject/build-impl.xml b/libsrc/jpproxy/nbproject/build-impl.xml index fa9ad0fbe..ec2302d65 100644 --- a/libsrc/jpproxy/nbproject/build-impl.xml +++ b/libsrc/jpproxy/nbproject/build-impl.xml @@ -189,7 +189,12 @@ is divided into following sections: - + + + + + + @@ -215,6 +220,7 @@ is divided into following sections: + @@ -680,7 +686,7 @@ is divided into following sections: - + @@ -755,7 +761,7 @@ is divided into following sections: - + @@ -782,7 +788,7 @@ is divided into following sections: - + diff --git a/libsrc/jpproxy/nbproject/genfiles.properties b/libsrc/jpproxy/nbproject/genfiles.properties index 9e4b5fd3d..c37be34a0 100644 --- a/libsrc/jpproxy/nbproject/genfiles.properties +++ b/libsrc/jpproxy/nbproject/genfiles.properties @@ -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 diff --git a/libsrc/treetable/build.xml b/libsrc/treetable/build.xml new file mode 100644 index 000000000..8a974bcd8 --- /dev/null +++ b/libsrc/treetable/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project treetable. + + + diff --git a/libsrc/treetable/manifest.mf b/libsrc/treetable/manifest.mf new file mode 100644 index 000000000..328e8e5bc --- /dev/null +++ b/libsrc/treetable/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/libsrc/treetable/nbproject/build-impl.xml b/libsrc/treetable/nbproject/build-impl.xml new file mode 100644 index 000000000..a53c99b03 --- /dev/null +++ b/libsrc/treetable/nbproject/build-impl.xml @@ -0,0 +1,1419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libsrc/treetable/nbproject/genfiles.properties b/libsrc/treetable/nbproject/genfiles.properties new file mode 100644 index 000000000..d931ac2ee --- /dev/null +++ b/libsrc/treetable/nbproject/genfiles.properties @@ -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 diff --git a/libsrc/treetable/nbproject/project.properties b/libsrc/treetable/nbproject/project.properties new file mode 100644 index 000000000..93930aa33 --- /dev/null +++ b/libsrc/treetable/nbproject/project.properties @@ -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 diff --git a/libsrc/treetable/nbproject/project.xml b/libsrc/treetable/nbproject/project.xml new file mode 100644 index 000000000..69f12b7e3 --- /dev/null +++ b/libsrc/treetable/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + treetable + + + + + + + + + diff --git a/libsrc/treetable/src/de/hameister/treetable/MyAbstractTreeTableModel.java b/libsrc/treetable/src/de/hameister/treetable/MyAbstractTreeTableModel.java new file mode 100644 index 000000000..ba1c398d1 --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyAbstractTreeTableModel.java @@ -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); + } + +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyDataModel.java b/libsrc/treetable/src/de/hameister/treetable/MyDataModel.java new file mode 100644 index 000000000..49ba6079b --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyDataModel.java @@ -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) { + } + +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyDataNode.java b/libsrc/treetable/src/de/hameister/treetable/MyDataNode.java new file mode 100644 index 000000000..6c6c43ff0 --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyDataNode.java @@ -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 children; + + public MyDataNode(String name, String capital, Date declared, Integer area, List 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 getChildren() { + return children; + } + + /** + * Knotentext vom JTree. + */ + public String toString() { + return name; + } +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyTreeTable.java b/libsrc/treetable/src/de/hameister/treetable/MyTreeTable.java new file mode 100644 index 000000000..2da462026 --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyTreeTable.java @@ -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); + } +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyTreeTableCellEditor.java b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableCellEditor.java new file mode 100644 index 000000000..859862d89 --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableCellEditor.java @@ -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; + } + +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyTreeTableCellRenderer.java b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableCellRenderer.java new file mode 100644 index 000000000..30fb20abe --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableCellRenderer.java @@ -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; + } +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyTreeTableModel.java b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableModel.java new file mode 100644 index 000000000..0d24776bc --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableModel.java @@ -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); +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyTreeTableModelAdapter.java b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableModelAdapter.java new file mode 100644 index 000000000..90c906aff --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableModelAdapter.java @@ -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); + } +} diff --git a/libsrc/treetable/src/de/hameister/treetable/MyTreeTableSelectionModel.java b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableSelectionModel.java new file mode 100644 index 000000000..c15bbe052 --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/MyTreeTableSelectionModel.java @@ -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; + } +} diff --git a/libsrc/treetable/src/de/hameister/treetable/TreeTableMain.java b/libsrc/treetable/src/de/hameister/treetable/TreeTableMain.java new file mode 100644 index 000000000..fa9947af2 --- /dev/null +++ b/libsrc/treetable/src/de/hameister/treetable/TreeTableMain.java @@ -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 children1 = new ArrayList(); + 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 children2 = new ArrayList(); + 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 rootNodes = new ArrayList(); + 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); + } +} diff --git a/nbproject/project.xml b/nbproject/project.xml index 286b09cc5..cfa9340f0 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -308,7 +308,7 @@ src - 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/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 build javadoc reports diff --git a/src/com/jpexs/decompiler/flash/gui/DebugPanel.java b/src/com/jpexs/decompiler/flash/gui/DebugPanel.java index 5df50caed..f90e6cd2f 100644 --- a/src/com/jpexs/decompiler/flash/gui/DebugPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/DebugPanel.java @@ -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> 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 locals = new ArrayList<>(); locals.addAll(f.arguments); locals.addAll(f.variables); List 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()); diff --git a/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java b/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java index c951dd3ce..5869e2ecb 100644 --- a/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java +++ b/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java @@ -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; diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 3809ce7ee..fcd4818fc 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -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); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 4433e28d7..57f6c2a79 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -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 tableListeners = new ArrayList<>(); + public List path = new ArrayList<>(); - private List vars; - private List varIds; + public Long parentId; + public int level; - public List getVarIds() { - return varIds; - } + public Variable thisVar; + public Variable thisTrait; + public long thisTraitId; - public List getVars() { - return new ArrayList<>(vars); - } + private List childs; + private List childTraits; - public VariablesTableModel(List vars, List 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 vars, List 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 tableListeners = new ArrayList<>(); + + VariableNode root; + private Map> 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 vars, List parentIds) { + this.ttable = ttable; + List 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 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= 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(null)); if (dpos > -1) { decompiledTextArea.setCaretPosition(dpos); + } } @@ -872,8 +1169,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener