mirror of
https://github.com/processing/processing4.git
synced 2026-02-12 10:00:42 +01:00
359 lines
9.8 KiB
Java
Executable File
359 lines
9.8 KiB
Java
Executable File
/*
|
|
* Copyright (C) 2012 Martin Leopold <m@martinleopold.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
package processing.mode.experimental;
|
|
|
|
import com.sun.jdi.ArrayReference;
|
|
import com.sun.jdi.ObjectReference;
|
|
import com.sun.jdi.StringReference;
|
|
import com.sun.jdi.Value;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Enumeration;
|
|
import java.util.List;
|
|
import javax.swing.tree.MutableTreeNode;
|
|
import javax.swing.tree.TreeNode;
|
|
|
|
/**
|
|
* Model for a variable in the variable inspector. Has a type and name and
|
|
* optionally a value. Can have sub-variables (as is the case for objects, and
|
|
* arrays).
|
|
*
|
|
* @author Martin Leopold <m@martinleopold.com>
|
|
*/
|
|
public class VariableNode implements MutableTreeNode {
|
|
|
|
public static final int TYPE_UNKNOWN = -1;
|
|
public static final int TYPE_OBJECT = 0;
|
|
public static final int TYPE_ARRAY = 1;
|
|
public static final int TYPE_INTEGER = 2;
|
|
public static final int TYPE_FLOAT = 3;
|
|
public static final int TYPE_BOOLEAN = 4;
|
|
public static final int TYPE_CHAR = 5;
|
|
public static final int TYPE_STRING = 6;
|
|
public static final int TYPE_LONG = 7;
|
|
public static final int TYPE_DOUBLE = 8;
|
|
public static final int TYPE_BYTE = 9;
|
|
public static final int TYPE_SHORT = 10;
|
|
public static final int TYPE_VOID = 11;
|
|
protected String type;
|
|
protected String name;
|
|
protected Value value;
|
|
protected List<MutableTreeNode> children = new ArrayList();
|
|
protected MutableTreeNode parent;
|
|
|
|
/**
|
|
* Construct a {@link VariableNode}.
|
|
* @param name the name
|
|
* @param type the type
|
|
* @param value the value
|
|
*/
|
|
public VariableNode(String name, String type, Value value) {
|
|
this.name = name;
|
|
this.type = type;
|
|
this.value = value;
|
|
}
|
|
|
|
public void setValue(Value value) {
|
|
this.value = value;
|
|
}
|
|
|
|
public Value getValue() {
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Get a String representation of this variable nodes value.
|
|
*
|
|
* @return a String representing the value.
|
|
*/
|
|
public String getStringValue() {
|
|
String str;
|
|
if (value != null) {
|
|
if (getType() == TYPE_OBJECT) {
|
|
str = "instance of " + type;
|
|
} else if (getType() == TYPE_ARRAY) {
|
|
//instance of int[5] (id=998) --> instance of int[5]
|
|
str = value.toString().substring(0, value.toString().lastIndexOf(" "));
|
|
} else if (getType() == TYPE_STRING) {
|
|
str = ((StringReference) value).value(); // use original string value (without quotes)
|
|
} else {
|
|
str = value.toString();
|
|
}
|
|
} else {
|
|
str = "null";
|
|
}
|
|
return str;
|
|
}
|
|
|
|
public String getTypeName() {
|
|
return type;
|
|
}
|
|
|
|
public int getType() {
|
|
if (type == null) {
|
|
return TYPE_UNKNOWN;
|
|
}
|
|
if (type.endsWith("[]")) {
|
|
return TYPE_ARRAY;
|
|
}
|
|
if (type.equals("int")) {
|
|
return TYPE_INTEGER;
|
|
}
|
|
if (type.equals("long")) {
|
|
return TYPE_LONG;
|
|
}
|
|
if (type.equals("byte")) {
|
|
return TYPE_BYTE;
|
|
}
|
|
if (type.equals("short")) {
|
|
return TYPE_SHORT;
|
|
}
|
|
if (type.equals("float")) {
|
|
return TYPE_FLOAT;
|
|
}
|
|
if (type.equals("double")) {
|
|
return TYPE_DOUBLE;
|
|
}
|
|
if (type.equals("char")) {
|
|
return TYPE_CHAR;
|
|
}
|
|
if (type.equals("java.lang.String")) {
|
|
return TYPE_STRING;
|
|
}
|
|
if (type.equals("boolean")) {
|
|
return TYPE_BOOLEAN;
|
|
}
|
|
if (type.equals("void")) {
|
|
return TYPE_VOID; //TODO: check if this is correct
|
|
}
|
|
return TYPE_OBJECT;
|
|
}
|
|
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
public void setName(String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
/**
|
|
* Add a {@link VariableNode} as child.
|
|
*
|
|
* @param c the {@link VariableNode} to add.
|
|
*/
|
|
public void addChild(VariableNode c) {
|
|
children.add(c);
|
|
c.setParent(this);
|
|
}
|
|
|
|
/**
|
|
* Add multiple {@link VariableNode}s as children.
|
|
*
|
|
* @param children the list of {@link VariableNode}s to add.
|
|
*/
|
|
public void addChildren(List<VariableNode> children) {
|
|
for (VariableNode child : children) {
|
|
addChild(child);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public TreeNode getChildAt(int i) {
|
|
return children.get(i);
|
|
}
|
|
|
|
@Override
|
|
public int getChildCount() {
|
|
return children.size();
|
|
}
|
|
|
|
@Override
|
|
public TreeNode getParent() {
|
|
return parent;
|
|
}
|
|
|
|
@Override
|
|
public int getIndex(TreeNode tn) {
|
|
return children.indexOf(tn);
|
|
}
|
|
|
|
@Override
|
|
public boolean getAllowsChildren() {
|
|
if (value == null) {
|
|
return false;
|
|
}
|
|
|
|
// handle strings
|
|
if (getType() == TYPE_STRING) {
|
|
return false;
|
|
}
|
|
|
|
// handle arrays
|
|
if (getType() == TYPE_ARRAY) {
|
|
ArrayReference array = (ArrayReference) value;
|
|
return array.length() > 0;
|
|
}
|
|
// handle objects
|
|
if (getType() == TYPE_OBJECT) { // this also rules out null
|
|
// check if this object has any fields
|
|
ObjectReference obj = (ObjectReference) value;
|
|
return !obj.referenceType().visibleFields().isEmpty();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This controls the default icon and disclosure triangle.
|
|
*
|
|
* @return true, will show "folder" icon and disclosure triangle.
|
|
*/
|
|
@Override
|
|
public boolean isLeaf() {
|
|
//return children.size() == 0;
|
|
return !getAllowsChildren();
|
|
}
|
|
|
|
@Override
|
|
public Enumeration children() {
|
|
return Collections.enumeration(children);
|
|
}
|
|
|
|
/**
|
|
* Get a String representation of this {@link VariableNode}.
|
|
*
|
|
* @return the name of the variable (for sorting to work).
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
return getName(); // for sorting
|
|
}
|
|
|
|
/**
|
|
* Get a String description of this {@link VariableNode}. Contains the type,
|
|
* name and value.
|
|
*
|
|
* @return the description
|
|
*/
|
|
public String getDescription() {
|
|
String str = "";
|
|
if (type != null) {
|
|
str += type + " ";
|
|
}
|
|
str += name;
|
|
str += " = " + getStringValue();
|
|
return str;
|
|
}
|
|
|
|
@Override
|
|
public void insert(MutableTreeNode mtn, int i) {
|
|
children.add(i, this);
|
|
}
|
|
|
|
@Override
|
|
public void remove(int i) {
|
|
MutableTreeNode mtn = children.remove(i);
|
|
if (mtn != null) {
|
|
mtn.setParent(null);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void remove(MutableTreeNode mtn) {
|
|
children.remove(mtn);
|
|
mtn.setParent(null);
|
|
}
|
|
|
|
/**
|
|
* Remove all children from this {@link VariableNode}.
|
|
*/
|
|
public void removeAllChildren() {
|
|
for (MutableTreeNode mtn : children) {
|
|
mtn.setParent(null);
|
|
}
|
|
children.clear();
|
|
}
|
|
|
|
@Override
|
|
public void setUserObject(Object o) {
|
|
if (o instanceof Value) {
|
|
value = (Value) o;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeFromParent() {
|
|
parent.remove(this);
|
|
this.parent = null;
|
|
}
|
|
|
|
@Override
|
|
public void setParent(MutableTreeNode mtn) {
|
|
parent = mtn;
|
|
}
|
|
|
|
/**
|
|
* Test for equality. To be equal, two {@link VariableNode}s need to have
|
|
* equal type, name and value.
|
|
*
|
|
* @param obj the object to test for equality with this {@link VariableNode}
|
|
* @return true if the given object is equal to this {@link VariableNode}
|
|
*/
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (obj == null) {
|
|
return false;
|
|
}
|
|
if (getClass() != obj.getClass()) {
|
|
return false;
|
|
}
|
|
final VariableNode other = (VariableNode) obj;
|
|
if ((this.type == null) ? (other.type != null) : !this.type.equals(other.type)) {
|
|
//System.out.println("type not equal");
|
|
return false;
|
|
}
|
|
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
|
//System.out.println("name not equal");
|
|
return false;
|
|
}
|
|
if (this.value != other.value && (this.value == null || !this.value.equals(other.value))) {
|
|
//System.out.println("value not equal");
|
|
return false;
|
|
}
|
|
// if (this.parent != other.parent && (this.parent == null || !this.parent.equals(other.parent))) {
|
|
// System.out.println("parent not equal: " + this.parent + "/" + other.parent);
|
|
// return false;
|
|
// }
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns a hash code based on type, name and value.
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
int hash = 3;
|
|
hash = 97 * hash + (this.type != null ? this.type.hashCode() : 0);
|
|
hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
|
|
hash = 97 * hash + (this.value != null ? this.value.hashCode() : 0);
|
|
// hash = 97 * hash + (this.parent != null ? this.parent.hashCode() : 0);
|
|
return hash;
|
|
}
|
|
}
|