Hack: Move over Rhino debugger to helma.scripting.rhino.debug because most of the internals
are defined as package-private so there's no way to subclass unless we're in the same package.
This commit is contained in:
parent
2373d63719
commit
fb04c05289
8 changed files with 4838 additions and 0 deletions
63
src/helma/scripting/rhino/debug/AbstractCellEditor.java
Normal file
63
src/helma/scripting/rhino/debug/AbstractCellEditor.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
package helma.scripting.rhino.debug;
|
||||||
|
import java.awt.Component;
|
||||||
|
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.awt.AWTEvent;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import java.util.EventObject;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class AbstractCellEditor implements CellEditor {
|
||||||
|
|
||||||
|
protected EventListenerList listenerList = new EventListenerList();
|
||||||
|
|
||||||
|
public Object getCellEditorValue() { return null; }
|
||||||
|
public boolean isCellEditable(EventObject e) { return true; }
|
||||||
|
public boolean shouldSelectCell(EventObject anEvent) { return false; }
|
||||||
|
public boolean stopCellEditing() { return true; }
|
||||||
|
public void cancelCellEditing() {}
|
||||||
|
|
||||||
|
public void addCellEditorListener(CellEditorListener l) {
|
||||||
|
listenerList.add(CellEditorListener.class, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCellEditorListener(CellEditorListener l) {
|
||||||
|
listenerList.remove(CellEditorListener.class, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify all listeners that have registered interest for
|
||||||
|
* notification on this event type.
|
||||||
|
* @see EventListenerList
|
||||||
|
*/
|
||||||
|
protected void fireEditingStopped() {
|
||||||
|
// Guaranteed to return a non-null array
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
// Process the listeners last to first, notifying
|
||||||
|
// those that are interested in this event
|
||||||
|
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||||
|
if (listeners[i]==CellEditorListener.class) {
|
||||||
|
((CellEditorListener)listeners[i+1]).editingStopped(new ChangeEvent(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify all listeners that have registered interest for
|
||||||
|
* notification on this event type.
|
||||||
|
* @see EventListenerList
|
||||||
|
*/
|
||||||
|
protected void fireEditingCanceled() {
|
||||||
|
// Guaranteed to return a non-null array
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
// Process the listeners last to first, notifying
|
||||||
|
// those that are interested in this event
|
||||||
|
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||||
|
if (listeners[i]==CellEditorListener.class) {
|
||||||
|
((CellEditorListener)listeners[i+1]).editingCanceled(new ChangeEvent(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
198
src/helma/scripting/rhino/debug/AbstractTreeTableModel.java
Normal file
198
src/helma/scripting/rhino/debug/AbstractTreeTableModel.java
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/*
|
||||||
|
* @(#)AbstractTreeTableModel.java 1.2 98/10/27
|
||||||
|
*
|
||||||
|
* Copyright 1997, 1998 by Sun Microsystems, Inc.,
|
||||||
|
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is the confidential and proprietary information
|
||||||
|
* of Sun Microsystems, Inc. ("Confidential Information"). You
|
||||||
|
* shall not disclose such Confidential Information and shall use
|
||||||
|
* it only in accordance with the terms of the license agreement
|
||||||
|
* you entered into with Sun.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package helma.scripting.rhino.debug;
|
||||||
|
import javax.swing.tree.*;
|
||||||
|
|
||||||
|
import javax.swing.event.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @version 1.2 10/27/98
|
||||||
|
* An abstract implementation of the TreeTableModel interface, handling the list
|
||||||
|
* of listeners.
|
||||||
|
* @author Philip Milne
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractTreeTableModel implements TreeTableModel {
|
||||||
|
protected Object root;
|
||||||
|
protected EventListenerList listenerList = new EventListenerList();
|
||||||
|
|
||||||
|
public AbstractTreeTableModel(Object root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Default implmentations for methods in the TreeModel interface.
|
||||||
|
//
|
||||||
|
|
||||||
|
public Object getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLeaf(Object node) {
|
||||||
|
return getChildCount(node) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void valueForPathChanged(TreePath path, Object newValue) {}
|
||||||
|
|
||||||
|
// This is not called in the JTree's default mode: use a naive implementation.
|
||||||
|
public int getIndexOfChild(Object parent, Object child) {
|
||||||
|
for (int i = 0; i < getChildCount(parent); i++) {
|
||||||
|
if (getChild(parent, i).equals(child)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTreeModelListener(TreeModelListener l) {
|
||||||
|
listenerList.add(TreeModelListener.class, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTreeModelListener(TreeModelListener l) {
|
||||||
|
listenerList.remove(TreeModelListener.class, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify all listeners that have registered interest for
|
||||||
|
* notification on this event type. The event instance
|
||||||
|
* is lazily created using the parameters passed into
|
||||||
|
* the fire method.
|
||||||
|
* @see EventListenerList
|
||||||
|
*/
|
||||||
|
protected void fireTreeNodesChanged(Object source, Object[] path,
|
||||||
|
int[] childIndices,
|
||||||
|
Object[] children) {
|
||||||
|
// Guaranteed to return a non-null array
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
TreeModelEvent e = null;
|
||||||
|
// Process the listeners last to first, notifying
|
||||||
|
// those that are interested in this event
|
||||||
|
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||||
|
if (listeners[i]==TreeModelListener.class) {
|
||||||
|
// Lazily create the event:
|
||||||
|
if (e == null)
|
||||||
|
e = new TreeModelEvent(source, path,
|
||||||
|
childIndices, children);
|
||||||
|
((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify all listeners that have registered interest for
|
||||||
|
* notification on this event type. The event instance
|
||||||
|
* is lazily created using the parameters passed into
|
||||||
|
* the fire method.
|
||||||
|
* @see EventListenerList
|
||||||
|
*/
|
||||||
|
protected void fireTreeNodesInserted(Object source, Object[] path,
|
||||||
|
int[] childIndices,
|
||||||
|
Object[] children) {
|
||||||
|
// Guaranteed to return a non-null array
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
TreeModelEvent e = null;
|
||||||
|
// Process the listeners last to first, notifying
|
||||||
|
// those that are interested in this event
|
||||||
|
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||||
|
if (listeners[i]==TreeModelListener.class) {
|
||||||
|
// Lazily create the event:
|
||||||
|
if (e == null)
|
||||||
|
e = new TreeModelEvent(source, path,
|
||||||
|
childIndices, children);
|
||||||
|
((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify all listeners that have registered interest for
|
||||||
|
* notification on this event type. The event instance
|
||||||
|
* is lazily created using the parameters passed into
|
||||||
|
* the fire method.
|
||||||
|
* @see EventListenerList
|
||||||
|
*/
|
||||||
|
protected void fireTreeNodesRemoved(Object source, Object[] path,
|
||||||
|
int[] childIndices,
|
||||||
|
Object[] children) {
|
||||||
|
// Guaranteed to return a non-null array
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
TreeModelEvent e = null;
|
||||||
|
// Process the listeners last to first, notifying
|
||||||
|
// those that are interested in this event
|
||||||
|
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||||
|
if (listeners[i]==TreeModelListener.class) {
|
||||||
|
// Lazily create the event:
|
||||||
|
if (e == null)
|
||||||
|
e = new TreeModelEvent(source, path,
|
||||||
|
childIndices, children);
|
||||||
|
((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify all listeners that have registered interest for
|
||||||
|
* notification on this event type. The event instance
|
||||||
|
* is lazily created using the parameters passed into
|
||||||
|
* the fire method.
|
||||||
|
* @see EventListenerList
|
||||||
|
*/
|
||||||
|
protected void fireTreeStructureChanged(Object source, Object[] path,
|
||||||
|
int[] childIndices,
|
||||||
|
Object[] children) {
|
||||||
|
// Guaranteed to return a non-null array
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
TreeModelEvent e = null;
|
||||||
|
// Process the listeners last to first, notifying
|
||||||
|
// those that are interested in this event
|
||||||
|
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||||
|
if (listeners[i]==TreeModelListener.class) {
|
||||||
|
// Lazily create the event:
|
||||||
|
if (e == null)
|
||||||
|
e = new TreeModelEvent(source, path,
|
||||||
|
childIndices, children);
|
||||||
|
((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Default impelmentations for methods in the TreeTableModel interface.
|
||||||
|
//
|
||||||
|
|
||||||
|
public Class getColumnClass(int column) { return Object.class; }
|
||||||
|
|
||||||
|
/** By default, make the column with the Tree in it the only editable one.
|
||||||
|
* Making this column editable causes the JTable to forward mouse
|
||||||
|
* and keyboard events in the Tree column to the underlying JTree.
|
||||||
|
*/
|
||||||
|
public boolean isCellEditable(Object node, int column) {
|
||||||
|
return getColumnClass(column) == TreeTableModel.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueAt(Object aValue, Object node, int column) {}
|
||||||
|
|
||||||
|
|
||||||
|
// Left to be implemented in the subclass:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* public Object getChild(Object parent, int index)
|
||||||
|
* public int getChildCount(Object parent)
|
||||||
|
* public int getColumnCount()
|
||||||
|
* public String getColumnName(Object node, int column)
|
||||||
|
* public Object getValueAt(Object node, int column)
|
||||||
|
*/
|
||||||
|
}
|
356
src/helma/scripting/rhino/debug/JTreeTable.java
Normal file
356
src/helma/scripting/rhino/debug/JTreeTable.java
Normal file
|
@ -0,0 +1,356 @@
|
||||||
|
/*
|
||||||
|
* @(#)JTreeTable.java 1.2 98/10/27
|
||||||
|
*
|
||||||
|
* Copyright 1997, 1998 by Sun Microsystems, Inc.,
|
||||||
|
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is the confidential and proprietary information
|
||||||
|
* of Sun Microsystems, Inc. ("Confidential Information"). You
|
||||||
|
* shall not disclose such Confidential Information and shall use
|
||||||
|
* it only in accordance with the terms of the license agreement
|
||||||
|
* you entered into with Sun.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package helma.scripting.rhino.debug;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import javax.swing.tree.*;
|
||||||
|
import javax.swing.table.*;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
|
import java.util.EventObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This example shows how to create a simple JTreeTable component,
|
||||||
|
* by using a JTree as a renderer (and editor) for the cells in a
|
||||||
|
* particular column in the JTable.
|
||||||
|
*
|
||||||
|
* @version 1.2 10/27/98
|
||||||
|
*
|
||||||
|
* @author Philip Milne
|
||||||
|
* @author Scott Violet
|
||||||
|
*/
|
||||||
|
public class JTreeTable extends JTable {
|
||||||
|
/** A subclass of JTree. */
|
||||||
|
protected TreeTableCellRenderer tree;
|
||||||
|
|
||||||
|
public JTreeTable(TreeTableModel treeTableModel) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// Create the tree. It will be used as a renderer and editor.
|
||||||
|
tree = new TreeTableCellRenderer(treeTableModel);
|
||||||
|
|
||||||
|
// Install a tableModel representing the visible rows in the tree.
|
||||||
|
super.setModel(new TreeTableModelAdapter(treeTableModel, tree));
|
||||||
|
|
||||||
|
// Force the JTable and JTree to share their row selection models.
|
||||||
|
ListToTreeSelectionModelWrapper selectionWrapper = new
|
||||||
|
ListToTreeSelectionModelWrapper();
|
||||||
|
tree.setSelectionModel(selectionWrapper);
|
||||||
|
setSelectionModel(selectionWrapper.getListSelectionModel());
|
||||||
|
|
||||||
|
// Install the tree editor renderer and editor.
|
||||||
|
setDefaultRenderer(TreeTableModel.class, tree);
|
||||||
|
setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
|
||||||
|
|
||||||
|
// No grid.
|
||||||
|
setShowGrid(false);
|
||||||
|
|
||||||
|
// No intercell spacing
|
||||||
|
setIntercellSpacing(new Dimension(0, 0));
|
||||||
|
|
||||||
|
// And update the height of the trees row to match that of
|
||||||
|
// the table.
|
||||||
|
if (tree.getRowHeight() < 1) {
|
||||||
|
// Metal looks better like this.
|
||||||
|
setRowHeight(18);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden to message super and forward the method to the tree.
|
||||||
|
* Since the tree is not actually in the component hieachy it will
|
||||||
|
* never receive this unless we forward it in this manner.
|
||||||
|
*/
|
||||||
|
public void updateUI() {
|
||||||
|
super.updateUI();
|
||||||
|
if(tree != null) {
|
||||||
|
tree.updateUI();
|
||||||
|
}
|
||||||
|
// Use the tree's default foreground and background colors in the
|
||||||
|
// table.
|
||||||
|
LookAndFeel.installColorsAndFont(this, "Tree.background",
|
||||||
|
"Tree.foreground", "Tree.font");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Workaround for BasicTableUI anomaly. Make sure the UI never tries to
|
||||||
|
* paint the editor. The UI currently uses different techniques to
|
||||||
|
* paint the renderers and editors and overriding setBounds() below
|
||||||
|
* is not the right thing to do for an editor. Returning -1 for the
|
||||||
|
* editing row in this case, ensures the editor is never painted.
|
||||||
|
*/
|
||||||
|
public int getEditingRow() {
|
||||||
|
return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 :
|
||||||
|
editingRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden to pass the new rowHeight to the tree.
|
||||||
|
*/
|
||||||
|
public void setRowHeight(int rowHeight) {
|
||||||
|
super.setRowHeight(rowHeight);
|
||||||
|
if (tree != null && tree.getRowHeight() != rowHeight) {
|
||||||
|
tree.setRowHeight(getRowHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tree that is being shared between the model.
|
||||||
|
*/
|
||||||
|
public JTree getTree() {
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A TreeCellRenderer that displays a JTree.
|
||||||
|
*/
|
||||||
|
public class TreeTableCellRenderer extends JTree implements
|
||||||
|
TableCellRenderer {
|
||||||
|
/** Last table/tree row asked to renderer. */
|
||||||
|
protected int visibleRow;
|
||||||
|
|
||||||
|
public TreeTableCellRenderer(TreeModel model) {
|
||||||
|
super(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updateUI is overridden to set the colors of the Tree's renderer
|
||||||
|
* to match that of the table.
|
||||||
|
*/
|
||||||
|
public void updateUI() {
|
||||||
|
super.updateUI();
|
||||||
|
// Make the tree's cell renderer use the table's cell selection
|
||||||
|
// colors.
|
||||||
|
TreeCellRenderer tcr = getCellRenderer();
|
||||||
|
if (tcr instanceof DefaultTreeCellRenderer) {
|
||||||
|
DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer)tcr);
|
||||||
|
// For 1.1 uncomment this, 1.2 has a bug that will cause an
|
||||||
|
// exception to be thrown if the border selection color is
|
||||||
|
// null.
|
||||||
|
// dtcr.setBorderSelectionColor(null);
|
||||||
|
dtcr.setTextSelectionColor(UIManager.getColor
|
||||||
|
("Table.selectionForeground"));
|
||||||
|
dtcr.setBackgroundSelectionColor(UIManager.getColor
|
||||||
|
("Table.selectionBackground"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the row height of the tree, and forwards the row height to
|
||||||
|
* the table.
|
||||||
|
*/
|
||||||
|
public void setRowHeight(int rowHeight) {
|
||||||
|
if (rowHeight > 0) {
|
||||||
|
super.setRowHeight(rowHeight);
|
||||||
|
if (JTreeTable.this != null &&
|
||||||
|
JTreeTable.this.getRowHeight() != rowHeight) {
|
||||||
|
JTreeTable.this.setRowHeight(getRowHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is overridden to set the height to match that of the JTable.
|
||||||
|
*/
|
||||||
|
public void setBounds(int x, int y, int w, int h) {
|
||||||
|
super.setBounds(x, 0, w, JTreeTable.this.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sublcassed to translate the graphics such that the last visible
|
||||||
|
* row will be drawn at 0,0.
|
||||||
|
*/
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
g.translate(0, -visibleRow * getRowHeight());
|
||||||
|
super.paint(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TreeCellRenderer method. Overridden to update the visible row.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TreeTableCellEditor implementation. Component returned is the
|
||||||
|
* JTree.
|
||||||
|
*/
|
||||||
|
public class TreeTableCellEditor extends AbstractCellEditor implements
|
||||||
|
TableCellEditor {
|
||||||
|
public Component getTableCellEditorComponent(JTable table,
|
||||||
|
Object value,
|
||||||
|
boolean isSelected,
|
||||||
|
int r, int c) {
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden to return false, and if the event is a mouse event
|
||||||
|
* it is forwarded to the tree.<p>
|
||||||
|
* The behavior for this is debatable, and should really be offered
|
||||||
|
* as a property. By returning false, all keyboard actions are
|
||||||
|
* implemented in terms of the table. By returning true, the
|
||||||
|
* tree would get a chance to do something with the keyboard
|
||||||
|
* events. For the most part this is ok. But for certain keys,
|
||||||
|
* such as left/right, the tree will expand/collapse where as
|
||||||
|
* the table focus should really move to a different column. Page
|
||||||
|
* up/down should also be implemented in terms of the table.
|
||||||
|
* By returning false this also has the added benefit that clicking
|
||||||
|
* outside of the bounds of the tree node, but still in the tree
|
||||||
|
* column will select the row, whereas if this returned true
|
||||||
|
* that wouldn't be the case.
|
||||||
|
* <p>By returning false we are also enforcing the policy that
|
||||||
|
* the tree will never be editable (at least by a key sequence).
|
||||||
|
*/
|
||||||
|
public boolean isCellEditable(EventObject e) {
|
||||||
|
if (e instanceof MouseEvent) {
|
||||||
|
for (int counter = getColumnCount() - 1; counter >= 0;
|
||||||
|
counter--) {
|
||||||
|
if (getColumnClass(counter) == TreeTableModel.class) {
|
||||||
|
MouseEvent me = (MouseEvent)e;
|
||||||
|
MouseEvent newME = new MouseEvent(tree, me.getID(),
|
||||||
|
me.getWhen(), me.getModifiers(),
|
||||||
|
me.getX() - getCellRect(0, counter, true).x,
|
||||||
|
me.getY(), me.getClickCount(),
|
||||||
|
me.isPopupTrigger());
|
||||||
|
tree.dispatchEvent(newME);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel
|
||||||
|
* to listen for changes in the ListSelectionModel it maintains. Once
|
||||||
|
* a change in the ListSelectionModel happens, the paths are updated
|
||||||
|
* in the DefaultTreeSelectionModel.
|
||||||
|
*/
|
||||||
|
class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel {
|
||||||
|
/** Set to true when we are updating the ListSelectionModel. */
|
||||||
|
protected boolean updatingListSelectionModel;
|
||||||
|
|
||||||
|
public ListToTreeSelectionModelWrapper() {
|
||||||
|
super();
|
||||||
|
getListSelectionModel().addListSelectionListener
|
||||||
|
(createListSelectionListener());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list selection model. ListToTreeSelectionModelWrapper
|
||||||
|
* listens for changes to this model and updates the selected paths
|
||||||
|
* accordingly.
|
||||||
|
*/
|
||||||
|
ListSelectionModel getListSelectionModel() {
|
||||||
|
return listSelectionModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is overridden to set <code>updatingListSelectionModel</code>
|
||||||
|
* and message super. This is the only place DefaultTreeSelectionModel
|
||||||
|
* alters the ListSelectionModel.
|
||||||
|
*/
|
||||||
|
public void resetRowSelection() {
|
||||||
|
if(!updatingListSelectionModel) {
|
||||||
|
updatingListSelectionModel = true;
|
||||||
|
try {
|
||||||
|
super.resetRowSelection();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
updatingListSelectionModel = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Notice how we don't message super if
|
||||||
|
// updatingListSelectionModel is true. If
|
||||||
|
// updatingListSelectionModel is true, it implies the
|
||||||
|
// ListSelectionModel has already been updated and the
|
||||||
|
// paths are the only thing that needs to be updated.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns an instance of ListSelectionHandler.
|
||||||
|
*/
|
||||||
|
protected ListSelectionListener createListSelectionListener() {
|
||||||
|
return new ListSelectionHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If <code>updatingListSelectionModel</code> is false, this will
|
||||||
|
* reset the selected paths from the selected rows in the list
|
||||||
|
* selection model.
|
||||||
|
*/
|
||||||
|
protected void updateSelectedPathsFromSelectedRows() {
|
||||||
|
if(!updatingListSelectionModel) {
|
||||||
|
updatingListSelectionModel = true;
|
||||||
|
try {
|
||||||
|
// This is way expensive, ListSelectionModel needs an
|
||||||
|
// enumerator for iterating.
|
||||||
|
int min = listSelectionModel.getMinSelectionIndex();
|
||||||
|
int max = listSelectionModel.getMaxSelectionIndex();
|
||||||
|
|
||||||
|
clearSelection();
|
||||||
|
if(min != -1 && max != -1) {
|
||||||
|
for(int counter = min; counter <= max; counter++) {
|
||||||
|
if(listSelectionModel.isSelectedIndex(counter)) {
|
||||||
|
TreePath selPath = tree.getPathForRow
|
||||||
|
(counter);
|
||||||
|
|
||||||
|
if(selPath != null) {
|
||||||
|
addSelectionPath(selPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
updatingListSelectionModel = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class responsible for calling updateSelectedPathsFromSelectedRows
|
||||||
|
* when the selection of the list changse.
|
||||||
|
*/
|
||||||
|
class ListSelectionHandler implements ListSelectionListener {
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
updateSelectedPathsFromSelectedRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3640
src/helma/scripting/rhino/debug/Main.java
Normal file
3640
src/helma/scripting/rhino/debug/Main.java
Normal file
File diff suppressed because it is too large
Load diff
43
src/helma/scripting/rhino/debug/ScopeProvider.java
Normal file
43
src/helma/scripting/rhino/debug/ScopeProvider.java
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Rhino JavaScript Debugger code, released
|
||||||
|
* November 21, 2000.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is See Beyond Corporation.
|
||||||
|
|
||||||
|
* Portions created by See Beyond are
|
||||||
|
* Copyright (C) 2000 See Beyond Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Christopher Oliver
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* terms of the GNU Public License (the "GPL"), in which case the
|
||||||
|
* provisions of the GPL are applicable instead of those above.
|
||||||
|
* If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of the GPL and not to allow others to use your
|
||||||
|
* version of this file under the NPL, indicate your decision by
|
||||||
|
* deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this
|
||||||
|
* file under either the NPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino.debug;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.Scriptable;
|
||||||
|
|
||||||
|
public interface ScopeProvider {
|
||||||
|
public Scriptable getScope();
|
||||||
|
};
|
71
src/helma/scripting/rhino/debug/TreeTableModel.java
Normal file
71
src/helma/scripting/rhino/debug/TreeTableModel.java
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* TreeTableModel.java
|
||||||
|
*
|
||||||
|
* Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This software is the confidential and proprietary information of Sun
|
||||||
|
* Microsystems, Inc. ("Confidential Information"). You shall not
|
||||||
|
* disclose such Confidential Information and shall use it only in
|
||||||
|
* accordance with the terms of the license agreement you entered into
|
||||||
|
* with Sun.
|
||||||
|
*
|
||||||
|
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
|
||||||
|
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
|
||||||
|
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
|
||||||
|
* THIS SOFTWARE OR ITS DERIVATIVES.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package helma.scripting.rhino.debug;
|
||||||
|
import javax.swing.tree.TreeModel;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TreeTableModel is the model used by a JTreeTable. It extends TreeModel
|
||||||
|
* to add methods for getting inforamtion about the set of columns each
|
||||||
|
* node in the TreeTableModel may have. Each column, like a column in
|
||||||
|
* a TableModel, has a name and a type associated with it. Each node in
|
||||||
|
* the TreeTableModel can return a value for each of the columns and
|
||||||
|
* set that value if isCellEditable() returns true.
|
||||||
|
*
|
||||||
|
* @author Philip Milne
|
||||||
|
* @author Scott Violet
|
||||||
|
*/
|
||||||
|
public interface TreeTableModel extends TreeModel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the number ofs availible column.
|
||||||
|
*/
|
||||||
|
public int getColumnCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name for column number <code>column</code>.
|
||||||
|
*/
|
||||||
|
public String getColumnName(int column);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type for column number <code>column</code>.
|
||||||
|
*/
|
||||||
|
public Class getColumnClass(int column);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to be displayed for node <code>node</code>,
|
||||||
|
* at column number <code>column</code>.
|
||||||
|
*/
|
||||||
|
public Object getValueAt(Object node, int column);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the the value for node <code>node</code>,
|
||||||
|
* at column number <code>column</code> is editable.
|
||||||
|
*/
|
||||||
|
public boolean isCellEditable(Object node, int column);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value for node <code>node</code>,
|
||||||
|
* at column number <code>column</code>.
|
||||||
|
*/
|
||||||
|
public void setValueAt(Object aValue, Object node, int column);
|
||||||
|
}
|
128
src/helma/scripting/rhino/debug/TreeTableModelAdapter.java
Normal file
128
src/helma/scripting/rhino/debug/TreeTableModelAdapter.java
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* @(#)TreeTableModelAdapter.java 1.2 98/10/27
|
||||||
|
*
|
||||||
|
* Copyright 1997, 1998 by Sun Microsystems, Inc.,
|
||||||
|
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is the confidential and proprietary information
|
||||||
|
* of Sun Microsystems, Inc. ("Confidential Information"). You
|
||||||
|
* shall not disclose such Confidential Information and shall use
|
||||||
|
* it only in accordance with the terms of the license agreement
|
||||||
|
* you entered into with Sun.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package helma.scripting.rhino.debug;
|
||||||
|
import javax.swing.JTree;
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
|
import javax.swing.event.TreeExpansionEvent;
|
||||||
|
import javax.swing.event.TreeExpansionListener;
|
||||||
|
import javax.swing.event.TreeModelEvent;
|
||||||
|
import javax.swing.event.TreeModelListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a wrapper class takes a TreeTableModel and implements
|
||||||
|
* the table model interface. The implementation is trivial, with
|
||||||
|
* all of the event dispatching support provided by the superclass:
|
||||||
|
* the AbstractTableModel.
|
||||||
|
*
|
||||||
|
* @version 1.2 10/27/98
|
||||||
|
*
|
||||||
|
* @author Philip Milne
|
||||||
|
* @author Scott Violet
|
||||||
|
*/
|
||||||
|
public class TreeTableModelAdapter extends AbstractTableModel
|
||||||
|
{
|
||||||
|
JTree tree;
|
||||||
|
TreeTableModel treeTableModel;
|
||||||
|
|
||||||
|
public TreeTableModelAdapter(TreeTableModel treeTableModel, JTree tree) {
|
||||||
|
this.tree = tree;
|
||||||
|
this.treeTableModel = treeTableModel;
|
||||||
|
|
||||||
|
tree.addTreeExpansionListener(new TreeExpansionListener() {
|
||||||
|
// Don't use fireTableRowsInserted() here; the selection model
|
||||||
|
// would get updated twice.
|
||||||
|
public void treeExpanded(TreeExpansionEvent event) {
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
public void treeCollapsed(TreeExpansionEvent event) {
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Install a TreeModelListener that can update the table when
|
||||||
|
// tree changes. We use delayedFireTableDataChanged as we can
|
||||||
|
// not be guaranteed the tree will have finished processing
|
||||||
|
// the event before us.
|
||||||
|
treeTableModel.addTreeModelListener(new TreeModelListener() {
|
||||||
|
public void treeNodesChanged(TreeModelEvent e) {
|
||||||
|
delayedFireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void treeNodesInserted(TreeModelEvent e) {
|
||||||
|
delayedFireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void treeNodesRemoved(TreeModelEvent e) {
|
||||||
|
delayedFireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void treeStructureChanged(TreeModelEvent e) {
|
||||||
|
delayedFireTableDataChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrappers, implementing TableModel interface.
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes fireTableDataChanged after all the pending events have been
|
||||||
|
* processed. SwingUtilities.invokeLater is used to handle this.
|
||||||
|
*/
|
||||||
|
protected void delayedFireTableDataChanged() {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
339
src/helma/scripting/rhino/debug/VariableModel.java
Normal file
339
src/helma/scripting/rhino/debug/VariableModel.java
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Netscape Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/NPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Rhino JavaScript Debugger code, released
|
||||||
|
* November 21, 2000.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is SeeBeyond Corporation.
|
||||||
|
|
||||||
|
* Portions created by SeeBeyond are
|
||||||
|
* Copyright (C) 2000 SeeBeyond Technology Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Christopher Oliver
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the
|
||||||
|
* terms of the GNU Public License (the "GPL"), in which case the
|
||||||
|
* provisions of the GPL are applicable instead of those above.
|
||||||
|
* If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of the GPL and not to allow others to use your
|
||||||
|
* version of this file under the NPL, indicate your decision by
|
||||||
|
* deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this
|
||||||
|
* file under either the NPL or the GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino.debug;
|
||||||
|
import org.mozilla.javascript.*;
|
||||||
|
import javax.swing.event.TableModelEvent;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
public class VariableModel extends AbstractTreeTableModel
|
||||||
|
implements TreeTableModel {
|
||||||
|
|
||||||
|
// Names of the columns.
|
||||||
|
|
||||||
|
static protected String[] cNames = { " Name", " Value"};
|
||||||
|
|
||||||
|
// Types of the columns.
|
||||||
|
|
||||||
|
static protected Class[] cTypes = {TreeTableModel.class, String.class};
|
||||||
|
|
||||||
|
|
||||||
|
public VariableModel(Scriptable scope) {
|
||||||
|
super(scope == null ? null : new VariableNode(scope, "this"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Some convenience methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
protected Object getObject(Object node) {
|
||||||
|
VariableNode varNode = ((VariableNode)node);
|
||||||
|
if (varNode == null) return null;
|
||||||
|
return varNode.getObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object[] getChildren(Object node) {
|
||||||
|
VariableNode varNode = ((VariableNode)node);
|
||||||
|
return varNode.getChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The TreeModel interface
|
||||||
|
//
|
||||||
|
|
||||||
|
public int getChildCount(Object node) {
|
||||||
|
Object[] children = getChildren(node);
|
||||||
|
return (children == null) ? 0 : children.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getChild(Object node, int i) {
|
||||||
|
return getChildren(node)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The superclass's implementation would work, but this is more efficient.
|
||||||
|
public boolean isLeaf(Object node) {
|
||||||
|
if (node == null) return true;
|
||||||
|
VariableNode varNode = (VariableNode)node;
|
||||||
|
Object[] children = varNode.getChildren();
|
||||||
|
if (children != null && children.length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(Object node, int column) {
|
||||||
|
return column == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The TreeTableNode interface.
|
||||||
|
//
|
||||||
|
|
||||||
|
public int getColumnCount() {
|
||||||
|
return cNames.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnName(int column) {
|
||||||
|
return cNames[column];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getColumnClass(int column) {
|
||||||
|
return cTypes[column];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValueAt(Object node, int column) {
|
||||||
|
Context cx = Context.enter();
|
||||||
|
try {
|
||||||
|
Object value = getObject(node);
|
||||||
|
switch (column) {
|
||||||
|
case 0: // Name
|
||||||
|
VariableNode varNode = (VariableNode)node;
|
||||||
|
String name = "";
|
||||||
|
if (varNode.name != null) {
|
||||||
|
return name + varNode.name;
|
||||||
|
}
|
||||||
|
return name + "[" + varNode.index + "]";
|
||||||
|
case 1: // Value
|
||||||
|
if (value == Undefined.instance ||
|
||||||
|
value == ScriptableObject.NOT_FOUND) {
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
if (value instanceof NativeCall) {
|
||||||
|
return "[object Call]";
|
||||||
|
}
|
||||||
|
String result;
|
||||||
|
try {
|
||||||
|
result = Context.toString(value);
|
||||||
|
} catch (RuntimeException exc) {
|
||||||
|
result = exc.getMessage();
|
||||||
|
}
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
int len = result.length();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
char ch = result.charAt(i);
|
||||||
|
if (Character.isISOControl(ch)) {
|
||||||
|
ch = ' ';
|
||||||
|
}
|
||||||
|
buf.append(ch);
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
} catch (Exception exc) {
|
||||||
|
//exc.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
cx.exit();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScope(Scriptable scope) {
|
||||||
|
VariableNode rootVar = (VariableNode)root;
|
||||||
|
rootVar.scope = scope;
|
||||||
|
fireTreeNodesChanged(this,
|
||||||
|
new Object[]{root},
|
||||||
|
null, new Object[]{root});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class VariableNode {
|
||||||
|
Scriptable scope;
|
||||||
|
String name;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
public VariableNode(Scriptable scope, String name) {
|
||||||
|
this.scope = scope;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VariableNode(Scriptable scope, int index) {
|
||||||
|
this.scope = scope;
|
||||||
|
this.name = null;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the the string to be used to display this leaf in the JTree.
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return (name != null ? name : "[" + index + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getObject() {
|
||||||
|
try {
|
||||||
|
if (scope == null) return null;
|
||||||
|
if (name != null) {
|
||||||
|
if (name.equals("this")) {
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
Object result = ScriptableObject.NOT_FOUND;
|
||||||
|
if (name.equals("__proto__")) {
|
||||||
|
result = scope.getPrototype();
|
||||||
|
} else if (name.equals("__parent__")) {
|
||||||
|
result = scope.getParentScope();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
result = ScriptableObject.getProperty(scope, name);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
result = e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == ScriptableObject.NOT_FOUND) {
|
||||||
|
result = Undefined.instance;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
Object result = ScriptableObject.getProperty(scope, index);
|
||||||
|
if (result == ScriptableObject.NOT_FOUND) {
|
||||||
|
result = Undefined.instance;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (Exception exc) {
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] children;
|
||||||
|
|
||||||
|
static final Object[] empty = new Object[0];
|
||||||
|
|
||||||
|
protected Object[] getChildren() {
|
||||||
|
if (children != null) return children;
|
||||||
|
Context cx = Context.enter();
|
||||||
|
try {
|
||||||
|
Object value = getObject();
|
||||||
|
if (value == null) return children = empty;
|
||||||
|
if (value == ScriptableObject.NOT_FOUND ||
|
||||||
|
value == Undefined.instance) {
|
||||||
|
return children = empty;
|
||||||
|
}
|
||||||
|
if (value instanceof Scriptable) {
|
||||||
|
Scriptable scrip = (Scriptable)value;
|
||||||
|
Scriptable proto = scrip.getPrototype();
|
||||||
|
Scriptable parent = scrip.getParentScope();
|
||||||
|
if (scrip.has(0, scrip)) {
|
||||||
|
int len = 0;
|
||||||
|
try {
|
||||||
|
Scriptable start = scrip;
|
||||||
|
Scriptable obj = start;
|
||||||
|
Object result = Undefined.instance;
|
||||||
|
do {
|
||||||
|
if (obj.has("length", start)) {
|
||||||
|
result = obj.get("length", start);
|
||||||
|
if (result != Scriptable.NOT_FOUND)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
obj = obj.getPrototype();
|
||||||
|
} while (obj != null);
|
||||||
|
if (result instanceof Number) {
|
||||||
|
len = ((Number)result).intValue();
|
||||||
|
}
|
||||||
|
} catch (Exception exc) {
|
||||||
|
}
|
||||||
|
if (parent != null) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
if (proto != null) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
children = new VariableNode[len];
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
if (parent != null) {
|
||||||
|
children[i++] = new VariableNode(scrip, "__parent__");
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
if (proto != null) {
|
||||||
|
children[i++] = new VariableNode(scrip, "__proto__");
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
for (; i < len; i++) {
|
||||||
|
children[i] = new VariableNode(scrip, i-j);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int len = 0;
|
||||||
|
Hashtable t = new Hashtable();
|
||||||
|
Object[] ids;
|
||||||
|
if (scrip instanceof ScriptableObject) {
|
||||||
|
ids = ((ScriptableObject)scrip).getAllIds();
|
||||||
|
} else {
|
||||||
|
ids = scrip.getIds();
|
||||||
|
}
|
||||||
|
if (ids == null) ids = empty;
|
||||||
|
if (proto != null) t.put("__proto__", "__proto__");
|
||||||
|
if (parent != null) t.put("__parent__", "__parent__");
|
||||||
|
if (ids.length > 0) {
|
||||||
|
for (int j = 0; j < ids.length; j++) {
|
||||||
|
t.put(ids[j], ids[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ids = new Object[t.size()];
|
||||||
|
Enumeration e = t.keys();
|
||||||
|
int j = 0;
|
||||||
|
while (e.hasMoreElements()) {
|
||||||
|
ids[j++] = e.nextElement().toString();
|
||||||
|
}
|
||||||
|
if (ids != null && ids.length > 0) {
|
||||||
|
java.util.Arrays.sort(ids, new java.util.Comparator() {
|
||||||
|
public int compare(Object l, Object r) {
|
||||||
|
return l.toString().compareToIgnoreCase(r.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
len = ids.length;
|
||||||
|
}
|
||||||
|
children = new VariableNode[len];
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
Object id = ids[i];
|
||||||
|
children[i] = new
|
||||||
|
VariableNode(scrip, id.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception exc) {
|
||||||
|
exc.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
cx.exit();
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue