summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-04-28 15:12:42 +0000
committerPaul Phillips <paulp@improving.org>2011-04-28 15:12:42 +0000
commit9a9f73b80261415e08eb782333470bbb84863894 (patch)
tree89766c94d74dd3704946869a7bd6f9e06b29d37a /src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
parent2700617052df7c49e6cc7459947e4337d9de987c (diff)
downloadscala-9a9f73b80261415e08eb782333470bbb84863894.tar.gz
scala-9a9f73b80261415e08eb782333470bbb84863894.tar.bz2
scala-9a9f73b80261415e08eb782333470bbb84863894.zip
Improvements to the AST browser contributed by ...
Improvements to the AST browser contributed by Yuvi Masory. Uses Nimbus LAF when available and improves readability by padding components. Adds menu items and key bindings for expanding and contracting nodes, closing the browser and continuing compilation, and closing the browser and aborting. No review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala126
1 files changed, 111 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index 8fd0017b81..613928856d 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -31,6 +31,9 @@ abstract class TreeBrowsers {
import global._
import nme.EMPTY
+ val borderSize = 10
+
+
def create(): SwingBrowser = new SwingBrowser();
/** Pseudo tree class, so that all JTree nodes are treated uniformly */
@@ -93,37 +96,38 @@ abstract class TreeBrowsers {
listeners = l :: listeners
/** Return the index'th child of parent */
- def getChild(parent: Any, index: Int): AnyRef =
+ def getChild(parent: AnyRef, index: Int): AnyRef =
packChildren(parent)(index)
/** Return the number of children this 'parent' has */
- def getChildCount(parent: Any): Int =
+ def getChildCount(parent: AnyRef): Int =
packChildren(parent).length
/** Return the index of the given child */
- def getIndexOfChild(parent: Any, child: Any): Int =
+ def getIndexOfChild(parent: AnyRef, child: AnyRef): Int =
packChildren(parent) indexOf child
/** Return the root node */
def getRoot(): AnyRef = program
/** Test whether the given node is a leaf */
- def isLeaf(node: Any): Boolean = packChildren(node).isEmpty
+ def isLeaf(node: AnyRef): Boolean = packChildren(node).isEmpty
def removeTreeModelListener(l: TreeModelListener): Unit =
listeners = listeners filterNot (_ == l)
/** we ignore this message for now */
- def valueForPathChanged(path: TreePath, newValue: Any) = ()
+ def valueForPathChanged(path: TreePath, newValue: AnyRef) = ()
/**
* Return a list of children for the given node.
*/
- def packChildren(t: Any): List[AnyRef] =
- TreeInfo.children(t.asInstanceOf[Tree])
+ def packChildren(t: AnyRef): List[AnyRef] = TreeInfo.children(t.asInstanceOf[Tree])
}
+
+
/**
* A window that can host the Tree widget and provide methods for
* displaying information
@@ -132,16 +136,45 @@ abstract class TreeBrowsers {
* @version 1.0
*/
class BrowserFrame(phaseName: String = "unknown") {
- val frame = new JFrame("Scala AST [" + phaseName + "]")
+ try {
+ UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel")
+ }
+ catch {
+ case _ => UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName())
+ }
+
+ val frame = new JFrame("Scala AST after " + phaseName + " phase")
+ frame.setJMenuBar(new ASTMenuBar())
val topLeftPane = new JPanel(new BorderLayout())
val topRightPane = new JPanel(new BorderLayout())
val bottomPane = new JPanel(new BorderLayout())
var splitPane: JSplitPane = _
- var treeModel: TreeModel = _
-
+ var treeModel: ASTTreeModel = _
+ var jTree: JTree = _
val textArea: JTextArea = new JTextArea(30, 120)
+ textArea.setBorder(BorderFactory.createEmptyBorder(borderSize, borderSize, borderSize, borderSize))
+
val infoPanel = new TextInfoPanel()
+
+ private def setExpansionState(root: JTree, expand: Boolean): Unit = {
+ def _setExpansionState(root: JTree, path: TreePath): Unit = {
+ val last = path.getLastPathComponent
+ for (i <- 0 until root.getModel.getChildCount(last)) {
+ val child = root.getModel.getChild(last, i)
+ val childPath = path pathByAddingChild child
+ _setExpansionState(root, childPath)
+ }
+ if (expand) {jTree expandPath path}
+ else {jTree collapsePath path}
+ }
+ _setExpansionState(root, new TreePath(root.getModel.getRoot))
+ }
+
+ def expandAll(subtree: JTree) = setExpansionState(subtree, true)
+ def collapseAll(subtree: JTree) = setExpansionState(subtree, false)
+
+
/** Create a frame that displays the AST.
*
* @param lock The lock is used in order to stop the compilation thread
@@ -160,7 +193,7 @@ abstract class TreeBrowsers {
override def windowClosed(e: WindowEvent): Unit = lock.release
});
- val tree = new JTree(treeModel) {
+ jTree = new JTree(treeModel) {
/** Return the string for a tree node. */
override def convertValueToText(value: Any, sel: Boolean,
exp: Boolean, leaf: Boolean,
@@ -173,7 +206,7 @@ abstract class TreeBrowsers {
}
}
- tree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
+ jTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
def valueChanged(e: javax.swing.event.TreeSelectionEvent): Unit = {
textArea.setText(e.getPath().getLastPathComponent().toString())
infoPanel.update(e.getPath().getLastPathComponent())
@@ -183,9 +216,10 @@ abstract class TreeBrowsers {
val topSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, topLeftPane, topRightPane)
topSplitPane.setResizeWeight(0.5)
- topLeftPane.add(new JScrollPane(tree), BorderLayout.CENTER)
+ jTree.setBorder(
+ BorderFactory.createEmptyBorder(borderSize, borderSize, borderSize, borderSize))
+ topLeftPane.add(new JScrollPane(jTree), BorderLayout.CENTER)
topRightPane.add(new JScrollPane(infoPanel), BorderLayout.CENTER)
-
bottomPane.add(new JScrollPane(textArea), BorderLayout.CENTER)
textArea.setFont(new Font("monospaced", Font.PLAIN, 14))
textArea.setEditable(false)
@@ -196,7 +230,67 @@ abstract class TreeBrowsers {
frame.setVisible(true)
}
- def setTreeModel(tm: TreeModel): Unit = treeModel = tm
+ class ASTMenuBar extends JMenuBar {
+ val menuKey = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
+ val shiftKey = InputEvent.SHIFT_MASK
+ val jmFile = new JMenu("File")
+ // val jmiSaveImage = new JMenuItem(
+ // new AbstractAction("Save Tree Image") {
+ // putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, menuKey, false))
+ // override def actionPerformed(e: ActionEvent) {
+ // //TODO
+ // }
+ // }
+ // )
+
+ // jmFile add jmiSaveImage
+
+ def closeWindow() = frame.getToolkit().getSystemEventQueue().postEvent(
+ new WindowEvent(frame, WindowEvent.WINDOW_CLOSING))
+
+ val jmiCancel = new JMenuItem (
+ new AbstractAction("Cancel Compilation") {
+ putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Q, menuKey + shiftKey, false))
+ override def actionPerformed(e: ActionEvent) {
+ closeWindow()
+ global.currentRun.cancel
+ }
+ }
+ )
+ jmFile add jmiCancel
+
+ val jmiExit = new JMenuItem (
+ new AbstractAction("Exit") {
+ putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Q, menuKey, false))
+ override def actionPerformed(e: ActionEvent) = closeWindow()
+ }
+ )
+ jmFile add jmiExit
+ add(jmFile)
+
+ val jmView = new JMenu("View")
+ val jmiExpand = new JMenuItem(
+ new AbstractAction("Expand All Nodes") {
+ putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, menuKey, false))
+ override def actionPerformed(e: ActionEvent) {
+ expandAll(jTree)
+ }
+ }
+ )
+ jmView add jmiExpand
+ val jmiCollapse = new JMenuItem(
+ new AbstractAction("Collapse All Nodes") {
+ putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_L, menuKey, false))
+ override def actionPerformed(e: ActionEvent) {
+ collapseAll(jTree)
+ }
+ }
+ )
+ jmView add jmiCollapse
+ add(jmView)
+ }
+
+ def setTreeModel(tm: ASTTreeModel): Unit = treeModel = tm
}
/**
@@ -204,6 +298,8 @@ abstract class TreeBrowsers {
*/
class TextInfoPanel extends JTextArea(20, 50) {
+ setBorder(BorderFactory.createEmptyBorder(borderSize, borderSize, borderSize, borderSize))
+ setEditable(false)
setFont(new Font("monospaced", Font.PLAIN, 12))
def update(v: AnyRef): Unit = {