Implement our own RhinoDebugger subclass to display scripts in a nice table.

The current implementation is merged from helma_1_4 branch and a bit quirky
in regard to repository script source names
This commit is contained in:
hns 2005-03-14 16:30:32 +00:00
parent fb04c05289
commit f7e929441c
3 changed files with 276 additions and 11 deletions

View file

@ -17,6 +17,8 @@
package helma.scripting.rhino; 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.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.*;
@ -27,8 +29,6 @@ import helma.util.CacheMap;
import helma.util.SystemMap; import helma.util.SystemMap;
import helma.util.WrappedMap; import helma.util.WrappedMap;
import org.mozilla.javascript.*; import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.debugger.Main;
import org.mozilla.javascript.tools.debugger.ScopeProvider;
import java.io.*; import java.io.*;
import java.text.*; import java.text.*;
@ -65,7 +65,7 @@ public final class RhinoCore implements ScopeProvider {
// Any error that may have been found in global code // Any error that may have been found in global code
String globalError; String globalError;
Main debugger = null; HelmaDebugger debugger = null;
/** /**
* Create a Rhino evaluator for the given application and request evaluator. * Create a Rhino evaluator for the given application and request evaluator.
@ -86,12 +86,7 @@ public final class RhinoCore implements ScopeProvider {
// Set up visual debugger if rhino.debug = true // Set up visual debugger if rhino.debug = true
if ("true".equals(app.getProperty("rhino.debug"))) { if ("true".equals(app.getProperty("rhino.debug"))) {
debugger = new Main(app.getName() + " Debugger"); initDebugger(context);
debugger.setScopeProvider(this);
debugger.pack();
debugger.setVisible(true);
debugger.contextCreated(context);
debugger.contextEntered(context);
} }
// Set default optimization level according to whether debugger is on // Set default optimization level according to whether debugger is on
@ -153,6 +148,19 @@ public final class RhinoCore implements ScopeProvider {
} }
} }
void initDebugger(Context context) {
if (debugger == null) {
debugger = new HelmaDebugger(app.getName());
debugger.setScopeProvider(this);
debugger.pack();
debugger.setLocation(60, 60);
}
if (!debugger.isVisible())
debugger.setVisible(true);
debugger.contextCreated(context);
debugger.contextEntered(context);
}
/** /**
* Initialize the evaluator, making sure the minimum type information * Initialize the evaluator, making sure the minimum type information
* necessary to bootstrap the rest is parsed. * necessary to bootstrap the rest is parsed.

View file

@ -156,8 +156,7 @@ public class RhinoEngine implements ScriptingEngine {
// if visual debugger is on let it know we're entering a context // if visual debugger is on let it know we're entering a context
if (core.debugger != null) { if (core.debugger != null) {
core.debugger.contextCreated(context); core.initDebugger(context);
core.debugger.contextEntered(context);
} }
if ("true".equals(app.getProperty("rhino.trace"))) { if ("true".equals(app.getProperty("rhino.trace"))) {

View file

@ -0,0 +1,258 @@
/*
* Helma License Notice
*
* The contents of this file are subject to the Helma License
* Version 2.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://adele.helma.org/download/helma/license.txt
*
* Copyright 1998-2003 Helma Software. All Rights Reserved.
*
* $RCSfile$
* $Author$
* $Revision$
* $Date$
*/
package helma.scripting.rhino.debug;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.debug.DebuggableScript;
import org.mozilla.javascript.debug.DebugFrame;
import javax.swing.*;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.*;
import helma.util.StringUtils;
public class HelmaDebugger extends Main implements TreeSelectionListener {
JTree tree;
JList list;
DebuggerTreeNode treeRoot;
DefaultTreeModel treeModel;
HashMap treeNodes = new HashMap();
HashMap scripts = new HashMap();
public HelmaDebugger(String name) {
super(name);
Container contentPane = getContentPane();
Component main = contentPane.getComponent(1);
contentPane.remove(main);
treeRoot = new DebuggerTreeNode(name);
tree = new JTree(treeRoot);
treeModel = new DefaultTreeModel(treeRoot);
tree.setModel(treeModel);
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,
String source) {
String sourceName = fnOrScript.getSourceName();
if (!treeNodes.containsKey(sourceName)) {
createTreeNode(sourceName);
}
super.handleCompilationDone(cx, fnOrScript, source);
}
void createTreeNode(String sourceName) {
String[] path = StringUtils.split(sourceName, ":/\\");
DebuggerTreeNode node = treeRoot;
DebuggerTreeNode newNode = null;
for (int i = 1; i < path.length; i++) {
DebuggerTreeNode n = node.get(path[i]);
if (n == null) {
n = new DebuggerTreeNode(path[i]);
node.add(n);
if (newNode == null) newNode = n;
}
node = n;
}
treeNodes.put(sourceName, node);
scripts.put(node, sourceName);
if (newNode != null) {
SwingUtilities.invokeLater(new NodeInserter(newNode));
}
}
void openScript(TreePath path) {
if (path == null)
return;
Object node = path.getLastPathComponent();
if (node == null)
return;
String script = (String) scripts.get(node);
if (script == null)
return;
JInternalFrame w = (JInternalFrame) fileWindows.get(script);
if (w != null) {
try {
if (w.isIcon())
w.setMaximum(true);
w.show();
w.setSelected(true);
} catch (Exception exc) {
}
} else {
SourceInfo si = (SourceInfo) sourceNames.get(script);
if (si == null) {
System.out.println("debugger error: Couldn't find source: " + script);
}
swingInvoke(CreateFileWindow.action(this, si, -1));
}
// display functions for opened script file
Vector functions = new Vector();
Iterator it = functionNames.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
ScriptItem si = (ScriptItem) entry.getValue();
if (script.equals(si.getSourceInfo().getUrl())) {
functions.add(entry.getKey());
}
}
Collections.sort(functions);
list.setListData(functions);
}
void openFunction(String function) {
if (function == null)
return;
ScriptItem item = (ScriptItem) functionNames.get(function);
if (item != null) {
SourceInfo si = item.getSourceInfo();
String url = si.getUrl();
int lineNumber = item.getFirstLine();
FileWindow w = getFileWindow(url);
if (w == null) {
CreateFileWindow.action(this, si, lineNumber).run();
w = getFileWindow(url);
w.setPosition(-1);
}
int start = w.getPosition(lineNumber - 1);
int end = w.getPosition(lineNumber) - 1;
w.textArea.select(start);
w.textArea.setCaretPosition(start);
w.textArea.moveCaretPosition(end);
try {
if (w.isIcon())
w.setMaximum(true);
w.show();
requestFocus();
w.requestFocus();
w.textArea.requestFocus();
} catch (Exception exc) {
}
}
}
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (node == null) return;
Object script = scripts.get(node);
if (script != null) {
// openScript(script);
}
}
class DebuggerTreeNode extends DefaultMutableTreeNode {
public DebuggerTreeNode(Object obj) {
super(obj);
}
public DebuggerTreeNode get(String name) {
Enumeration children = this.children();
while (children.hasMoreElements()) {
DebuggerTreeNode node = (DebuggerTreeNode) children.nextElement();
if (node != null && name.equals(node.getUserObject()))
return node;
}
return null;
}
}
class NodeInserter implements Runnable {
MutableTreeNode node;
NodeInserter(MutableTreeNode node) {
this.node = node;
}
public void run() {
MutableTreeNode parent = (MutableTreeNode) node.getParent();
if (parent == treeRoot && treeRoot.getChildCount() == 1) {
tree.makeVisible(new TreePath(new Object[]{parent, node}));
}
treeModel.insertNodeInto(node, parent, parent.getIndex(node));
}
}
}