| 1 package org.antlr.works.awtree; 2 3 import org.antlr.runtime.CommonToken; 4 import org.antlr.runtime.tree.ParseTree; 5 import org.antlr.xjlib.appkit.gview.GView; 6 import org.antlr.xjlib.appkit.gview.base.Rect; 7 import org.antlr.xjlib.appkit.gview.object.GElement; 8 import org.antlr.xjlib.appkit.gview.object.GElementRect; 9 import org.antlr.xjlib.appkit.gview.object.GLink; 10 import org.antlr.xjlib.appkit.gview.shape.SLinkElbow; 11 12 import javax.swing.*; 13 import javax.swing.tree.TreeNode ; 14 import java.awt.*; 15 import java.util.HashMap ; 16 import java.util.Map ; 17 47 48 public class AWTreeGraphView extends GView { 49 50 public static final boolean DRAGGABLE = false; 51 52 public static final int HORIZONTAL_GAP = 20; 53 public static final int VERTICAL_GAP = 20; 54 55 public static final int MARGIN = 10; 56 57 public static final Color HIGHLIGHTED_COLOR = new Color(0, 0.5f, 1, 0.4f); 58 public static final Font DEFAULT_FONT = new Font("Monospaced", Font.PLAIN, 11); 59 60 protected TreeNode root; 61 protected GElementNode highlightedNode; 62 63 protected Map <TreeNode ,GElement> treeNodeToGElementMap = new HashMap <TreeNode , GElement>(); 64 protected Map <GElement,TreeNode > gelementToTreeNodeMap = new HashMap <GElement, TreeNode >(); 65 66 protected AWTreePanel panel; 67 protected AWTreeModel model; 68 69 protected Graphics2D g2d; 70 protected FontMetrics fontMetrics; 71 72 protected boolean dirty = true; 73 74 public AWTreeGraphView(AWTreePanel panel) { 75 this.panel = panel; 76 setPreferredSize(new Dimension(0, 0)); 77 setFocusable(true); 78 } 79 80 public void addDefaultEventManager() { 81 } 83 84 public void setModel(AWTreeModel model) { 85 this.model = model; 86 } 87 88 public void setRoot(TreeNode root) { 89 this.root = root; 90 } 91 92 public void clear() { 93 if(model != null) 94 model.clear(); 95 clearMaps(); 96 } 97 98 public void refresh() { 99 100 dirty = true; 101 102 105 rebuild(); 106 107 108 repaint(); 109 } 110 111 public void rebuild() { 112 if(g2d == null || root == null) 113 return; 114 115 if(dirty) { 116 dirty = false; 117 if(model == null) 118 rebuildNoModel(); 119 else 120 rebuildWithModel(); 121 } 122 } 123 124 public void clearMaps() { 125 treeNodeToGElementMap.clear(); 126 gelementToTreeNodeMap.clear(); 127 } 128 129 public void mapNodeAndElement(TreeNode node, GElement element) { 130 treeNodeToGElementMap.put(node, element); 131 gelementToTreeNodeMap.put(element, node); 132 } 133 134 public TreeNode getTreeNodeForElement(GElementNode elem) { 135 return gelementToTreeNodeMap.get(elem); 136 } 137 138 public GElementNode getGElementForNode(TreeNode node) { 139 if(node == null) 140 return null; 141 else 142 return (GElementNode)treeNodeToGElementMap.get(node); 143 } 144 145 148 149 public void rebuildNoModel() { 150 clearMaps(); 151 152 GElement element = buildGraph(null); 153 element.move(MARGIN, MARGIN); 154 155 setSizeMargin(MARGIN); 156 setRootElement(element); 157 } 158 159 public GElementNode buildGraph(TreeNode node) { 160 if(node == null) 161 node = root; 162 163 GElementNode nodeElement = getGElementForNode(node); 164 if(nodeElement == null) 165 nodeElement = createGElement(node); 166 167 168 for(int index=0; index<node.getChildCount(); index++) { 169 TreeNode child = node.getChildAt(index); 170 171 172 addChildElement(nodeElement, createGElement(child)); 173 174 175 buildGraph(child); 176 } 177 178 179 adjustElementPositionRelativeToItsChildren(node, false); 180 181 return nodeElement; 182 } 183 184 187 189 public void rebuildWithModel() { 190 for(int n=0; n<model.getNewNodesCount(); n++) { 191 TreeNode parent = model.getNewNodeParentAtIndex(n); 192 TreeNode child = model.getNewNodeAtIndex(n); 193 194 GElementNode parentElement = getGElementForNode(parent); 195 if(parentElement == null) { 196 parentElement = createGElement(root); 197 parentElement.move(MARGIN, MARGIN); 198 setSizeMargin(MARGIN); 199 setRootElement(parentElement); 200 } 201 202 GElementNode childElement = createGElement(child); 203 addChildElement(parentElement, childElement); 204 adjustElementPositionRelativeToItsChildren(parent, true); 205 } 206 207 autoAdjustSize(); 208 209 model.clearNewNodes(); 210 } 211 212 public void paintComponent(Graphics g) { 213 if(g2d != g) { 214 g2d = (Graphics2D)g; 215 g2d.setFont(DEFAULT_FONT); 216 fontMetrics = g2d.getFontMetrics(); 217 } 218 rebuild(); 219 super.paintComponent(g); 220 } 221 222 public void addChildElement(GElementNode parent, GElementNode child) { 223 224 double x = parent.getLastChildRightSpan(); 225 226 227 if(x > 0) 228 x += HORIZONTAL_GAP; 229 else 230 x = parent.getLeft(); 231 232 233 child.setPositionOfUpperLeftCorner(x, parent.getBottom()+VERTICAL_GAP); 234 235 236 GLink link = new GLink(parent, GLink.ANCHOR_BOTTOM, 237 child, GLink.ANCHOR_TOP, 238 GLink.SHAPE_ELBOW, "", 0); 239 link.setDraggable(DRAGGABLE); 240 241 242 SLinkElbow l = (SLinkElbow)link.getLink(); 243 l.setOutOffsetLength(10); 244 l.getArrow().setLength(6); 245 246 247 parent.addElement(link); 248 parent.addElement(child); 249 } 250 251 252 253 public void adjustElementPositionRelativeToItsChildren(TreeNode node, boolean recursive) { 254 GElementNode element = getGElementForNode(node); 255 if(element == null) 256 return; 257 258 double elementWidth = element.getWidth(); 259 double childrenWidth = element.getLastChildRightSpan()-element.getFirstChildLeftSpan(); 260 261 262 if(childrenWidth == 0) 263 return; 264 265 268 double x = Math.min(element.getLeft(), element.getFirstChildLeftSpan()); 269 double y = element.getTop(); 270 double spanWidth = Math.max(elementWidth, childrenWidth); 271 272 276 double childrenOffset = spanWidth*0.5-childrenWidth*0.5; 277 278 279 double offset = x+childrenOffset-element.getFirstChildLeftSpan(); 280 element.move(offset, 0); 281 282 283 element.setPositionOfUpperLeftCorner(x+spanWidth*0.5-elementWidth*0.5, y); 284 285 286 element.setSpanWidth(spanWidth); 287 288 289 if(recursive) 290 adjustElementPositionRelativeToItsChildren(node.getParent(), recursive); 291 } 292 293 public String getNodeLabel(TreeNode node) { 294 if(node instanceof ParseTree) { 295 Object payload = ((ParseTree)node).payload; 296 if(payload instanceof CommonToken) { 297 CommonToken t = (CommonToken)payload; 298 return t.getText(); 299 } else { 300 return payload.toString(); 301 } 302 } 303 return node.toString(); 304 } 305 306 public Color getNodeColor(TreeNode node) { 307 if(node instanceof AWTreeNode) 308 return ((AWTreeNode)node).getColor(); 309 else 310 return Color.black; 311 } 312 313 public GElementNode createGElement(TreeNode node) { 314 Color nodeColor = getNodeColor(node); 315 String nodeLabel = getNodeLabel(node); 316 317 double width = (nodeLabel==null?0:fontMetrics.stringWidth(nodeLabel))+16; 318 double height = fontMetrics.getHeight()+8; 319 320 GElementNode element = new GElementNode(); 321 element.setDraggable(DRAGGABLE); 322 323 326 element.setSize(width, height); 327 element.setPositionOfUpperLeftCorner(0, 0); 328 329 element.setLabel(nodeLabel); 330 element.setColor(nodeColor); 331 element.setLabelColor(nodeColor); 332 333 334 mapNodeAndElement(node, element); 335 336 return element; 337 } 338 339 public void highlightNode(TreeNode node) { 340 if(highlightedNode != null) { 341 highlightedNode.setHighlighted(false); 342 highlightedNode = null; 343 } 344 345 GElementNode element = getGElementForNode(node); 346 if(element == null) 347 return; 348 349 element.setHighlighted(true); 350 highlightedNode = element; 351 352 scrollNodeToVisible(node); 353 354 repaint(); 355 } 356 357 360 public void repaintNode(TreeNode node) { 361 GElementNode element = getGElementForNode(node); 362 if(element == null) 363 return; 364 365 if(node instanceof AWTreeNode) { 366 Color nodeColor = ((AWTreeNode)node).getColor(); 367 element.setColor(nodeColor); 368 element.setLabelColor(nodeColor); 369 } 370 } 371 372 public void scrollNodeToVisible(TreeNode node) { 373 GElementNode element = getGElementForNode(node); 374 if(element == null) 375 return; 376 377 scrollElementToVisible(element); 378 } 379 380 @Override  381 public JPopupMenu getContextualMenu(GElement element) { 382 return panel.getContextualMenu(); 383 } 384 385 public static class GElementNode extends GElementRect { 386 387 public boolean highlighted = false; 388 public double spanWidth = 0; 389 390 public void setHighlighted(boolean flag) { 391 this.highlighted = flag; 392 } 393 394 @Override  395 public void draw(Graphics2D g) { 396 if(highlighted && isVisibleInClip(g)) { 397 Rectangle r = getFrame().rectangle(); 398 g.setColor(HIGHLIGHTED_COLOR); 399 g.fillRect(r.x, r.y, r.width, r.height); 400 } 401 402 super.draw(g); 403 } 404 405 408 public void setSpanWidth(double width) { 409 spanWidth = width; 410 } 411 412 public double getLeftSpan() { 413 if(spanWidth <= getWidth()) 414 return getLeft(); 415 else 416 return getLeft()-(spanWidth-getWidth())*0.5; 417 } 418 419 public double getRightSpan() { 420 if(spanWidth <= getWidth()) 421 return getRight(); 422 else 423 return getRight()+(spanWidth-getWidth())*0.5; 424 } 425 426 429 public double getLastChildRightSpan() { 430 if(elements == null) 431 return 0; 432 433 for (int i = elements.size()-1; i >= 0; i--) { 434 GElement element = (GElement) elements.get(i); 435 if(element instanceof GElementNode) { 436 GElementNode n = (GElementNode)element; 437 return n.getRightSpan(); 438 } 439 } 440 441 return 0; 442 } 443 444 447 public double getFirstChildLeftSpan() { 448 if(elements == null) 449 return 0; 450 451 for (GElement element : elements) { 452 if (element instanceof GElementNode) { 453 GElementNode n = (GElementNode) element; 454 return n.getLeftSpan(); 455 } 456 } 457 458 return 0; 459 } 460 461 464 465 public double getLeft() { 466 return getFrame().r.x; 467 } 468 469 public double getTop() { 470 return getFrame().r.y; 471 } 472 473 public double getRight() { 474 Rect r = getFrame(); 475 return r.r.x+r.r.width; 476 } 477 478 public double getBottom() { 479 Rect r = getFrame(); 480 return r.r.y+r.r.height; 481 } 482 483 public void setTop(double top) { 484 position.y = top+getHeight()*0.5; 485 } 486 } 487 } 488 | Popular Tags |