* Update Rhino to 1.6R3.
* Remove old Rhino 1.5 classes, make Helma debugger subclass Rhino 1.6 classes (not fully functional yet, needs patches to Rhino debugger). * Make helma.doc.DocFunction compile with Rhino 1.6 by introducing intermediary DockenStream class that proxies TokenStream using java reflection.
This commit is contained in:
parent
fc37ba8cb3
commit
e5033685db
14 changed files with 254 additions and 4963 deletions
BIN
lib/rhino.jar
BIN
lib/rhino.jar
Binary file not shown.
|
@ -47,7 +47,7 @@ public class DocFunction extends DocResourceElement {
|
||||||
DocFunction func = new DocFunction(name, res, parent, ACTION);
|
DocFunction func = new DocFunction(name, res, parent, ACTION);
|
||||||
String rawComment = "";
|
String rawComment = "";
|
||||||
try {
|
try {
|
||||||
TokenStream ts = getTokenStream (res);
|
DockenStream ts = getDockenStream (res);
|
||||||
Point p = getPoint (ts);
|
Point p = getPoint (ts);
|
||||||
ts.getToken();
|
ts.getToken();
|
||||||
rawComment = Util.getStringFromFile(res, p, getPoint(ts));
|
rawComment = Util.getStringFromFile(res, p, getPoint(ts));
|
||||||
|
@ -90,7 +90,7 @@ public class DocFunction extends DocResourceElement {
|
||||||
String functionName = null;
|
String functionName = null;
|
||||||
String context = null;
|
String context = null;
|
||||||
|
|
||||||
TokenStream ts = getTokenStream (res);
|
DockenStream ts = getDockenStream (res);
|
||||||
|
|
||||||
while (!ts.eof()) {
|
while (!ts.eof()) {
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ public class DocFunction extends DocResourceElement {
|
||||||
lastToken = token;
|
lastToken = token;
|
||||||
|
|
||||||
// now get a new token
|
// now get a new token
|
||||||
// regular expression syntax is troublesome for the TokenStream
|
// regular expression syntax is troublesome for the DockenStream
|
||||||
// we can safely ignore syntax errors in regular expressions here
|
// we can safely ignore syntax errors in regular expressions here
|
||||||
try {
|
try {
|
||||||
token = ts.getToken();
|
token = ts.getToken();
|
||||||
|
@ -208,7 +208,7 @@ public class DocFunction extends DocResourceElement {
|
||||||
token = ts.getToken();
|
token = ts.getToken();
|
||||||
int level = (token == Token.LC) ? 1 : 0;
|
int level = (token == Token.LC) ? 1 : 0;
|
||||||
while (!ts.eof() && level > 0) {
|
while (!ts.eof() && level > 0) {
|
||||||
// regular expression syntax is troublesome for the TokenStream
|
// regular expression syntax is troublesome for the DockenStream
|
||||||
// we don't need them here, so we just ignore such an error
|
// we don't need them here, so we just ignore such an error
|
||||||
try {
|
try {
|
||||||
token = ts.getToken();
|
token = ts.getToken();
|
||||||
|
@ -250,7 +250,7 @@ public class DocFunction extends DocResourceElement {
|
||||||
/**
|
/**
|
||||||
* creates a rhino token stream for a given file
|
* creates a rhino token stream for a given file
|
||||||
*/
|
*/
|
||||||
protected static TokenStream getTokenStream (Resource res) throws IOException {
|
protected static DockenStream getDockenStream (Resource res) throws IOException {
|
||||||
Reader reader = null;
|
Reader reader = null;
|
||||||
try {
|
try {
|
||||||
reader = new InputStreamReader(res.getInputStream());
|
reader = new InputStreamReader(res.getInputStream());
|
||||||
|
@ -258,18 +258,20 @@ public class DocFunction extends DocResourceElement {
|
||||||
fnfe.printStackTrace();
|
fnfe.printStackTrace();
|
||||||
throw new DocException (fnfe.toString());
|
throw new DocException (fnfe.toString());
|
||||||
}
|
}
|
||||||
String name = res.getName();
|
// String name = res.getName();
|
||||||
int line = 0;
|
Integer line = new Integer(0);
|
||||||
CompilerEnvirons compilerEnv = new CompilerEnvirons();
|
CompilerEnvirons compilerEnv = new CompilerEnvirons();
|
||||||
compilerEnv.initFromContext(Context.getCurrentContext());
|
compilerEnv.initFromContext(Context.getCurrentContext());
|
||||||
return new TokenStream (compilerEnv, reader, null, name, line);
|
ErrorReporter errorReporter = Context.getCurrentContext().getErrorReporter();
|
||||||
|
Parser parser = new Parser(compilerEnv, errorReporter);
|
||||||
|
return new DockenStream (parser, reader, null, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns a pointer to the current position in the TokenStream
|
* returns a pointer to the current position in the DockenStream
|
||||||
*/
|
*/
|
||||||
protected static Point getPoint (TokenStream ts) {
|
protected static Point getPoint (DockenStream ts) {
|
||||||
return new Point (ts.getOffset(), ts.getLineno());
|
return new Point (ts.getOffset(), ts.getLineno());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
112
src/helma/doc/DockenStream.java
Normal file
112
src/helma/doc/DockenStream.java
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2006 Hannes Wallnoefer <hannes@helma.at>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.doc;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.io.Reader;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.*;
|
||||||
|
|
||||||
|
public class DockenStream {
|
||||||
|
|
||||||
|
Object tokenStream;
|
||||||
|
static Constructor cnst;
|
||||||
|
static String[] names = new String[]
|
||||||
|
{ "getToken", "getString", "getOffset", "getLineno", "eof" };
|
||||||
|
static Method[] methods = new Method[5];
|
||||||
|
final static Class[] noclass = new Class[0];
|
||||||
|
final static Object[] noargs = new Object[0];
|
||||||
|
|
||||||
|
int peek;
|
||||||
|
boolean peeked;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Class clazz = Class.forName("org.mozilla.javascript.TokenStream");
|
||||||
|
cnst = clazz.getDeclaredConstructor(new Class[] {Parser.class, Reader.class, String.class, Integer.TYPE});
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
methods[i] = clazz.getDeclaredMethod(names[i], noclass);
|
||||||
|
}
|
||||||
|
cnst.setAccessible(true);
|
||||||
|
Method.setAccessible(methods, true);
|
||||||
|
} catch (Exception x) {
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DockenStream(Parser parser, Reader reader, String name, Integer lineno) {
|
||||||
|
try {
|
||||||
|
tokenStream = cnst.newInstance(new Object[] {parser, reader, name, lineno});
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getToken() {
|
||||||
|
if (peeked) {
|
||||||
|
peeked = false;
|
||||||
|
return peek;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return ((Integer) methods[0].invoke(tokenStream, noargs)).intValue();
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString() {
|
||||||
|
try {
|
||||||
|
return (String) methods[1].invoke(tokenStream, noargs);
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOffset() {
|
||||||
|
try {
|
||||||
|
return ((Integer) methods[2].invoke(tokenStream, noargs)).intValue();
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineno() {
|
||||||
|
try {
|
||||||
|
return ((Integer) methods[3].invoke(tokenStream, noargs)).intValue();
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int peekToken() {
|
||||||
|
if (!peeked) {
|
||||||
|
peek = getToken();
|
||||||
|
peeked = true;
|
||||||
|
}
|
||||||
|
return peek;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eof() {
|
||||||
|
try {
|
||||||
|
return ((Boolean) methods[4].invoke(tokenStream, noargs)).booleanValue();
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ package helma.scripting.rhino;
|
||||||
|
|
||||||
import helma.scripting.rhino.extensions.*;
|
import helma.scripting.rhino.extensions.*;
|
||||||
import helma.scripting.rhino.debug.HelmaDebugger;
|
import helma.scripting.rhino.debug.HelmaDebugger;
|
||||||
import helma.scripting.rhino.debug.ScopeProvider;
|
|
||||||
import helma.framework.core.*;
|
import helma.framework.core.*;
|
||||||
import helma.framework.repository.Resource;
|
import helma.framework.repository.Resource;
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
|
@ -29,6 +28,7 @@ import helma.util.SystemMap;
|
||||||
import helma.util.WrappedMap;
|
import helma.util.WrappedMap;
|
||||||
import helma.util.WeakCacheMap;
|
import helma.util.WeakCacheMap;
|
||||||
import org.mozilla.javascript.*;
|
import org.mozilla.javascript.*;
|
||||||
|
import org.mozilla.javascript.tools.debugger.ScopeProvider;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.*;
|
import java.text.*;
|
||||||
|
@ -72,6 +72,11 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
// as the app remains unchanged
|
// as the app remains unchanged
|
||||||
long updateSnooze = 500;
|
long updateSnooze = 500;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ContextFactory.initGlobal(new HelmaContextFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Rhino evaluator for the given application and request evaluator.
|
* Create a Rhino evaluator for the given application and request evaluator.
|
||||||
*/
|
*/
|
||||||
|
@ -104,7 +109,6 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
app.logError("Invalid rhino optlevel: " + opt);
|
app.logError("Invalid rhino optlevel: " + opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.setOptimizationLevel(optLevel);
|
context.setOptimizationLevel(optLevel);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -148,25 +152,24 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
throw new RuntimeException(e.getMessage());
|
throw new RuntimeException(e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
Context.exit();
|
Context.exit();
|
||||||
|
|
||||||
if (debugger != null) {
|
|
||||||
debugger.contextExited(context);
|
|
||||||
debugger.contextReleased(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initDebugger(Context context) {
|
void initDebugger(Context context) {
|
||||||
|
try {
|
||||||
if (debugger == null) {
|
if (debugger == null) {
|
||||||
debugger = new HelmaDebugger(app.getName());
|
debugger = new HelmaDebugger(app.getName());
|
||||||
debugger.setScopeProvider(this);
|
debugger.setScopeProvider(this);
|
||||||
debugger.pack();
|
// debugger.setScope(global);
|
||||||
debugger.setLocation(60, 60);
|
debugger.attachTo(context.getFactory());
|
||||||
|
// debugger.pack();
|
||||||
|
// debugger.getDebugFrame().setLocation(60, 60);
|
||||||
|
}
|
||||||
|
// if (!debugger.isVisible())
|
||||||
|
// debugger.setVisible(true);
|
||||||
|
} catch (Exception x) {
|
||||||
|
x.printStackTrace();
|
||||||
}
|
}
|
||||||
if (!debugger.isVisible())
|
|
||||||
debugger.setVisible(true);
|
|
||||||
debugger.contextCreated(context);
|
|
||||||
debugger.contextEntered(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1078,3 +1081,12 @@ public final class RhinoCore implements ScopeProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HelmaContextFactory extends ContextFactory {
|
||||||
|
protected boolean hasFeature(Context cx, int featureIndex) {
|
||||||
|
if (featureIndex == Context.FEATURE_DYNAMIC_SCOPE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.hasFeature(cx, featureIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -232,12 +232,6 @@ public class RhinoEngine implements ScriptingEngine {
|
||||||
// core.global.unregisterScope();
|
// core.global.unregisterScope();
|
||||||
thread = null;
|
thread = null;
|
||||||
|
|
||||||
// if visual debugger is on let it know we're exiting a context
|
|
||||||
if (core.debugger != null) {
|
|
||||||
core.debugger.contextExited(context);
|
|
||||||
core.debugger.contextReleased(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop through previous globals and unset them, if necessary.
|
// loop through previous globals and unset them, if necessary.
|
||||||
if (lastGlobals != null) {
|
if (lastGlobals != null) {
|
||||||
for (Iterator i = lastGlobals.keySet().iterator(); i.hasNext();) {
|
for (Iterator i = lastGlobals.keySet().iterator(); i.hasNext();) {
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,198 +0,0 @@
|
||||||
/*
|
|
||||||
* @(#)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)
|
|
||||||
*/
|
|
||||||
}
|
|
|
@ -16,24 +16,30 @@
|
||||||
|
|
||||||
package helma.scripting.rhino.debug;
|
package helma.scripting.rhino.debug;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.tools.debugger.Main;
|
||||||
|
import org.mozilla.javascript.tools.debugger.SwingGui;
|
||||||
|
import org.mozilla.javascript.tools.debugger.Dim;
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
import org.mozilla.javascript.debug.DebuggableScript;
|
import org.mozilla.javascript.debug.DebuggableScript;
|
||||||
|
|
||||||
|
import javax.swing.tree.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.TreeSelectionListener;
|
import javax.swing.event.TreeSelectionListener;
|
||||||
import javax.swing.event.TreeSelectionEvent;
|
import javax.swing.event.TreeSelectionEvent;
|
||||||
import javax.swing.tree.*;
|
import java.util.Enumeration;
|
||||||
import java.awt.*;
|
import java.util.HashMap;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.KeyAdapter;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.*;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import helma.util.StringUtils;
|
import helma.util.StringUtils;
|
||||||
|
|
||||||
public class HelmaDebugger extends Main implements TreeSelectionListener {
|
|
||||||
|
|
||||||
|
public class HelmaDebugger extends Dim implements TreeSelectionListener {
|
||||||
|
|
||||||
|
DebugGui gui;
|
||||||
JTree tree;
|
JTree tree;
|
||||||
JList list;
|
JList list;
|
||||||
DebuggerTreeNode treeRoot;
|
DebuggerTreeNode treeRoot;
|
||||||
|
@ -41,80 +47,22 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
|
||||||
HashMap treeNodes = new HashMap();
|
HashMap treeNodes = new HashMap();
|
||||||
HashMap scriptNames = new HashMap();
|
HashMap scriptNames = new HashMap();
|
||||||
|
|
||||||
public HelmaDebugger(String name) {
|
|
||||||
super(name);
|
|
||||||
Container contentPane = getContentPane();
|
|
||||||
Component main = contentPane.getComponent(1);
|
|
||||||
contentPane.remove(main);
|
|
||||||
|
|
||||||
treeRoot = new DebuggerTreeNode(name);
|
public HelmaDebugger(String title) {
|
||||||
tree = new JTree(treeRoot);
|
gui = new DebugGui(this, title);
|
||||||
treeModel = new DefaultTreeModel(treeRoot);
|
gui.pack();
|
||||||
tree.setModel(treeModel);
|
gui.setVisible(true);
|
||||||
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
|
||||||
tree.addTreeSelectionListener(this);
|
|
||||||
// tree.setRootVisible(false);
|
|
||||||
// track double clicks
|
|
||||||
tree.addMouseListener(new MouseAdapter() {
|
|
||||||
public void mouseClicked(MouseEvent evt) {
|
|
||||||
openScript(tree.getSelectionPath());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// track enter key
|
|
||||||
tree.addKeyListener(new KeyAdapter() {
|
|
||||||
public void keyPressed(KeyEvent evt) {
|
|
||||||
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
|
|
||||||
openScript(tree.getSelectionPath());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JScrollPane treeScroller = new JScrollPane(tree);
|
|
||||||
treeScroller.setPreferredSize(new Dimension(180, 300));
|
|
||||||
|
|
||||||
list = new JList();
|
|
||||||
// no bold font lists for me, thanks
|
|
||||||
list.setFont(list.getFont().deriveFont(Font.PLAIN));
|
|
||||||
list.addMouseListener(new MouseAdapter() {
|
|
||||||
public void mouseClicked(MouseEvent evt) {
|
|
||||||
openFunction((String) list.getSelectedValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
list.addKeyListener(new KeyAdapter() {
|
|
||||||
public void keyPressed(KeyEvent evt) {
|
|
||||||
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
|
|
||||||
openFunction((String) list.getSelectedValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JScrollPane listScroller = new JScrollPane(list);
|
|
||||||
listScroller.setPreferredSize(new Dimension(180, 200));
|
|
||||||
|
|
||||||
JSplitPane split1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
|
||||||
split1.setTopComponent(treeScroller);
|
|
||||||
split1.setBottomComponent(listScroller);
|
|
||||||
split1.setOneTouchExpandable(true);
|
|
||||||
Main.setResizeWeight(split1, 0.66);
|
|
||||||
|
|
||||||
JSplitPane split2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
|
||||||
split2.setLeftComponent(split1);
|
|
||||||
split2.setRightComponent(main);
|
|
||||||
split2.setOneTouchExpandable(true);
|
|
||||||
contentPane.add(split2, BorderLayout.CENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVisible(boolean b) {
|
|
||||||
super.setVisible(b);
|
|
||||||
// hide console window
|
|
||||||
console.hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleCompilationDone(Context cx, DebuggableScript fnOrScript,
|
public void handleCompilationDone(Context cx, DebuggableScript fnOrScript,
|
||||||
String source) {
|
String source) {
|
||||||
String sourceName = fnOrScript.getSourceName();
|
String sourceName = fnOrScript.getSourceName();
|
||||||
FileWindow w = (FileWindow) fileWindows.get(sourceName);
|
// FileWindow w = (FileWindow) fileWindows.get(sourceName);
|
||||||
super.handleCompilationDone(cx, fnOrScript, source);
|
/* super.(cx, fnOrScript, source);
|
||||||
if (!treeNodes.containsKey(sourceName)) {
|
if (!treeNodes.containsKey(sourceName)) {
|
||||||
createTreeNode(sourceName);
|
createTreeNode(sourceName);
|
||||||
}
|
} */
|
||||||
if (w != null) {
|
/* if (w != null) {
|
||||||
// renew existing file window
|
// renew existing file window
|
||||||
int position = w.textArea.getCaretPosition();
|
int position = w.textArea.getCaretPosition();
|
||||||
// System.err.println(" VISIBLE: " + point);
|
// System.err.println(" VISIBLE: " + point);
|
||||||
|
@ -122,10 +70,10 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
|
||||||
w.sourceInfo = (SourceInfo) sourceNames.get(sourceName);
|
w.sourceInfo = (SourceInfo) sourceNames.get(sourceName);
|
||||||
w.updateText();
|
w.updateText();
|
||||||
w.textArea.setCaretPosition(position);
|
w.textArea.setCaretPosition(position);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
void createTreeNode(String sourceName) {
|
void createTreeNode(String sourceName, Dim.SourceInfo sourceInfo) {
|
||||||
String[] path = StringUtils.split(sourceName, ":/\\");
|
String[] path = StringUtils.split(sourceName, ":/\\");
|
||||||
DebuggerTreeNode node = treeRoot;
|
DebuggerTreeNode node = treeRoot;
|
||||||
DebuggerTreeNode newNode = null;
|
DebuggerTreeNode newNode = null;
|
||||||
|
@ -151,27 +99,13 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
|
||||||
Object node = path.getLastPathComponent();
|
Object node = path.getLastPathComponent();
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return;
|
return;
|
||||||
String scriptName = (String) scriptNames.get(node);
|
String sourceName = (String) scriptNames.get(node);
|
||||||
if (scriptName == null)
|
if (sourceName == null)
|
||||||
return;
|
return;
|
||||||
JInternalFrame w = (JInternalFrame) fileWindows.get(scriptName);
|
SourceInfo sourceInfo = sourceInfo(sourceName);
|
||||||
if (w != null) {
|
gui.showSourceText(sourceInfo);
|
||||||
try {
|
|
||||||
if (w.isIcon())
|
|
||||||
w.setMaximum(true);
|
|
||||||
w.show();
|
|
||||||
w.setSelected(true);
|
|
||||||
} catch (Exception exc) {
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SourceInfo si = (SourceInfo) sourceNames.get(scriptName);
|
|
||||||
if (si == null) {
|
|
||||||
System.out.println("debugger error: Couldn't find source: " + scriptName);
|
|
||||||
}
|
|
||||||
swingInvoke(CreateFileWindow.action(this, si, -1));
|
|
||||||
}
|
|
||||||
// display functions for opened script file
|
// display functions for opened script file
|
||||||
Vector functions = new Vector();
|
/*Vector functions = new Vector();
|
||||||
Iterator it = functionNames.entrySet().iterator();
|
Iterator it = functionNames.entrySet().iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Map.Entry entry = (Map.Entry) it.next();
|
Map.Entry entry = (Map.Entry) it.next();
|
||||||
|
@ -181,13 +115,13 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collections.sort(functions);
|
Collections.sort(functions);
|
||||||
list.setListData(functions);
|
list.setListData(functions); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void openFunction(String function) {
|
void openFunction(String function) {
|
||||||
if (function == null)
|
if (function == null)
|
||||||
return;
|
return;
|
||||||
ScriptItem item = (ScriptItem) functionNames.get(function);
|
/* ScriptItem item = (ScriptItem) functionNames.get(function);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
SourceInfo si = item.getSourceInfo();
|
SourceInfo si = item.getSourceInfo();
|
||||||
String url = si.getUrl();
|
String url = si.getUrl();
|
||||||
|
@ -212,8 +146,10 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
|
||||||
w.textArea.requestFocus();
|
w.textArea.requestFocus();
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void valueChanged(TreeSelectionEvent e) {
|
public void valueChanged(TreeSelectionEvent e) {
|
||||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
|
||||||
|
@ -260,5 +196,78 @@ public class HelmaDebugger extends Main implements TreeSelectionListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DebugGui extends SwingGui {
|
||||||
|
public DebugGui(Dim dim, String title) {
|
||||||
|
super(dim, title);
|
||||||
|
Container contentPane = getContentPane();
|
||||||
|
Component main = contentPane.getComponent(1);
|
||||||
|
contentPane.remove(main);
|
||||||
|
|
||||||
|
treeRoot = new DebuggerTreeNode(title);
|
||||||
|
tree = new JTree(treeRoot);
|
||||||
|
treeModel = new DefaultTreeModel(treeRoot);
|
||||||
|
tree.setModel(treeModel);
|
||||||
|
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||||
|
tree.addTreeSelectionListener(HelmaDebugger.this);
|
||||||
|
// tree.setRootVisible(false);
|
||||||
|
// track double clicks
|
||||||
|
tree.addMouseListener(new MouseAdapter() {
|
||||||
|
public void mouseClicked(MouseEvent evt) {
|
||||||
|
openScript(tree.getSelectionPath());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// track enter key
|
||||||
|
tree.addKeyListener(new KeyAdapter() {
|
||||||
|
public void keyPressed(KeyEvent evt) {
|
||||||
|
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
|
||||||
|
openScript(tree.getSelectionPath());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
JScrollPane treeScroller = new JScrollPane(tree);
|
||||||
|
treeScroller.setPreferredSize(new Dimension(180, 300));
|
||||||
|
|
||||||
|
list = new JList();
|
||||||
|
// no bold font lists for me, thanks
|
||||||
|
list.setFont(list.getFont().deriveFont(Font.PLAIN));
|
||||||
|
list.addMouseListener(new MouseAdapter() {
|
||||||
|
public void mouseClicked(MouseEvent evt) {
|
||||||
|
openFunction((String) list.getSelectedValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
list.addKeyListener(new KeyAdapter() {
|
||||||
|
public void keyPressed(KeyEvent evt) {
|
||||||
|
if (evt.getKeyCode() == KeyEvent.VK_ENTER)
|
||||||
|
openFunction((String) list.getSelectedValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
JScrollPane listScroller = new JScrollPane(list);
|
||||||
|
listScroller.setPreferredSize(new Dimension(180, 200));
|
||||||
|
|
||||||
|
JSplitPane split1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||||
|
split1.setTopComponent(treeScroller);
|
||||||
|
split1.setBottomComponent(listScroller);
|
||||||
|
split1.setOneTouchExpandable(true);
|
||||||
|
split1.setResizeWeight(0.66);
|
||||||
|
|
||||||
|
JSplitPane split2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||||
|
split2.setLeftComponent(split1);
|
||||||
|
split2.setRightComponent(main);
|
||||||
|
split2.setOneTouchExpandable(true);
|
||||||
|
contentPane.add(split2, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSourceText(Dim.SourceInfo sourceInfo) {
|
||||||
|
// super.updateSourceText(sourceInfo);
|
||||||
|
String filename = sourceInfo.url();
|
||||||
|
if (!treeNodes.containsKey(filename)) {
|
||||||
|
createTreeNode(filename, sourceInfo);
|
||||||
|
}
|
||||||
|
// System.err.println("UPDATE SOURCE TEXT CALLED: " + sourceInfo.url());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showSourceText(Dim.SourceInfo sourceInfo) {
|
||||||
|
super.updateSourceText(sourceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,356 +0,0 @@
|
||||||
/*
|
|
||||||
* @(#)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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,43 +0,0 @@
|
||||||
/* -*- 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();
|
|
||||||
};
|
|
|
@ -1,71 +0,0 @@
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
/*
|
|
||||||
* @(#)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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,339 +0,0 @@
|
||||||
/* -*- 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