1 31 32 package org.antlr.works.editor; 33 34 import org.antlr.xjlib.appkit.swing.XJTree; 35 import org.antlr.xjlib.appkit.swing.XJTreeDelegate; 36 import org.antlr.xjlib.foundation.XJSystem; 37 import org.antlr.works.ate.swing.ATEKeyBindings; 38 import org.antlr.works.ate.syntax.generic.ATESyntaxLexer; 39 import org.antlr.works.ate.syntax.misc.ATEToken; 40 import org.antlr.works.components.grammar.CEditorGrammar; 41 import org.antlr.works.stats.StatisticsAW; 42 import org.antlr.works.syntax.GrammarSyntaxEngine; 43 import org.antlr.works.syntax.GrammarSyntaxLexer; 44 import org.antlr.works.syntax.element.ElementAction; 45 import org.antlr.works.syntax.element.ElementGroup; 46 import org.antlr.works.syntax.element.ElementReference; 47 import org.antlr.works.syntax.element.ElementRule; 48 import org.antlr.works.utils.IconManager; 49 50 import javax.swing.*; 51 import javax.swing.event.TreeSelectionEvent ; 52 import javax.swing.event.TreeSelectionListener ; 53 import javax.swing.text.BadLocationException ; 54 import javax.swing.text.Document ; 55 import javax.swing.tree.*; 56 import java.awt.*; 57 import java.awt.datatransfer.DataFlavor ; 58 import java.awt.datatransfer.Transferable ; 59 import java.awt.datatransfer.UnsupportedFlavorException ; 60 import java.awt.dnd.DnDConstants ; 61 import java.awt.dnd.DragSource ; 62 import java.awt.event.ActionEvent ; 63 import java.awt.event.KeyEvent ; 64 import java.awt.event.MouseAdapter ; 65 import java.awt.event.MouseEvent ; 66 import java.io.IOException ; 67 import java.util.*; 68 import java.util.List ; 69 70 public class EditorRules implements XJTreeDelegate { 71 72 protected CEditorGrammar editor; 73 74 protected boolean programmaticallySelectingRule = false; 75 protected boolean selectNextRule = false; 76 77 protected XJTree rulesTree; 78 protected DefaultMutableTreeNode rulesTreeRootNode; 79 protected DefaultTreeModel rulesTreeModel; 80 protected List <String > rulesTreeExpandedNodes; 81 protected RuleTreeUserObject selectedObject; 82 83 protected boolean sort; 84 85 public EditorRules(CEditorGrammar editor, XJTree rulesTree) { 86 this.editor = editor; 87 this.rulesTree = rulesTree; 88 89 rulesTree.setDelegate(this); 90 rulesTree.setEnableDragAndDrop(); 91 92 rulesTreeRootNode = new DefaultMutableTreeNode(new RuleTreeUserObject((ElementRule)null)); 93 rulesTreeModel = new DefaultTreeModel(rulesTreeRootNode); 94 rulesTreeExpandedNodes = new ArrayList<String >(); 95 96 rulesTree.setModel(rulesTreeModel); 97 rulesTree.addMouseListener(new RuleTreeMouseListener()); 98 rulesTree.addTreeSelectionListener(new RuleTreeSelectionListener()); 99 100 rulesTree.setRootVisible(false); 101 rulesTree.setShowsRootHandles(true); 102 rulesTree.setCellRenderer(new RulesTableRenderer()); 103 rulesTree.setRowHeight(17); 104 rulesTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); 105 } 106 107 public void setKeyBindings(ATEKeyBindings keyBindings) { 108 keyBindings.addKeyBinding("RULE_MOVE_UP", KeyStroke.getKeyStroke(KeyEvent.VK_UP, Event.CTRL_MASK), 109 new RuleMoveUpAction()); 110 keyBindings.addKeyBinding("RULE_MOVE_DOWN", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, Event.CTRL_MASK), 111 new RuleMoveDownAction()); 112 } 113 114 public GrammarSyntaxEngine getParserEngine() { 115 return editor.getParserEngine(); 116 } 117 118 public boolean isSorted() { 119 return sort; 120 } 121 122 public void setSorted(boolean flag) { 123 this.sort = flag; 124 } 125 126 public void toggleSorting() { 127 sort = !sort; 128 rebuildTree(); 129 } 130 131 public void ignoreSelectedRules(boolean flag) { 132 for (ElementRule r : getSelectedRules()) { 133 r.ignored = flag; 134 } 135 rulesTree.repaint(); 136 editor.rulesDidChange(); 137 } 138 139 143 144 public void findTokensToIgnore(boolean reset) { 145 List <ElementRule> rules = getRules(); 146 if(rules == null || rules.isEmpty()) 147 return; 148 149 findTokensToIgnore(rules, reset); 150 151 rulesTree.repaint(); 152 } 153 154 public static void findTokensToIgnore(List <ElementRule> rules, boolean reset) { 155 for (ElementRule rule : rules) { 156 if(reset) 157 rule.ignored = false; 158 159 List <ElementAction> actions = rule.getActions(); 160 if (actions == null || actions.isEmpty()) 161 continue; 162 163 for (ElementAction action : actions) { 164 List <ATEToken> tokens = action.getTokens(); 165 for (int t = 0; t < tokens.size(); t++) { 166 ATEToken token = tokens.get(t); 167 169 if ((token.type == ATESyntaxLexer.TOKEN_ID || token.type == GrammarSyntaxLexer.TOKEN_REFERENCE) 170 && token.getAttribute().equals("channel") && t + 3 < tokens.size()) 171 { 172 ATEToken t1 = tokens.get(t + 1); 173 ATEToken t2 = tokens.get(t + 2); 174 if (t1.type != ATESyntaxLexer.TOKEN_CHAR || !t1.getAttribute().equals("=")) 175 continue; 176 177 if (t2.type != ATESyntaxLexer.TOKEN_ID || !t2.getAttribute().equals("HIDDEN")) 178 continue; 179 180 rule.ignored = true; 181 break; 182 } 183 if (token.type == GrammarSyntaxLexer.TOKEN_ID && token.getAttribute().equals("skip")) { 184 if (tokens.size() == 5 && t == 1) { 186 rule.ignored = true; 187 break; 188 } 189 } 190 } 191 } 192 } 193 } 194 195 public boolean getFirstSelectedRuleIgnoredFlag() { 196 List <ElementRule> selectedRules = getSelectedRules(); 197 if(selectedRules == null || selectedRules.isEmpty()) 198 return false; 199 else 200 return (selectedRules.get(0)).ignored; 201 } 202 203 public class RuleMoveUpAction extends AbstractAction { 204 public void actionPerformed(ActionEvent event) { 205 ElementRule sourceRule = getEnclosingRuleAtPosition(editor.getCaretPosition()); 206 int previousRuleIndex = getParserEngine().getRules().indexOf(sourceRule)-1; 207 if(previousRuleIndex>=0) { 208 ElementRule targetRule = getParserEngine().getRuleAtIndex(previousRuleIndex); 209 moveRule(sourceRule, targetRule, true); 210 } 211 } 212 } 213 214 public class RuleMoveDownAction extends AbstractAction { 215 public void actionPerformed(ActionEvent event) { 216 ElementRule targetRule = getEnclosingRuleAtPosition(editor.getCaretPosition()); 217 int nextRuleIndex = getParserEngine().getRules().indexOf(targetRule)+1; 218 ElementRule sourceRule = getParserEngine().getRuleAtIndex(nextRuleIndex); 219 if(sourceRule != null) { 220 moveRule(sourceRule, targetRule, true); 221 selectNextRule = true; 222 } 223 } 224 } 225 226 public void refreshRules() { 227 saveExpandedNodes(); 228 rulesTreeModel.reload(); 229 restoreExpandedNodes(); 230 231 selectRuleInTreeAtPosition(editor.getCaretPosition()); 233 } 234 235 public ElementGroup getSelectedGroup() { 236 DefaultMutableTreeNode node = (DefaultMutableTreeNode)rulesTree.getSelectionPath().getLastPathComponent(); 237 RuleTreeUserObject n = (RuleTreeUserObject)node.getUserObject(); 238 if(n.group != null) 239 return n.group; 240 else 241 return null; 242 } 243 244 public ElementGroup findOpenGroupClosestToLocation(int location) { 245 List <ElementGroup> groups = getParserEngine().getGroups(); 247 if(groups == null || groups.isEmpty()) 248 return null; 249 250 ElementGroup previous = null; 251 for (ElementGroup group : groups) { 252 if (!group.openGroup) 253 continue; 254 255 ATEToken t = group.token; 256 if (t.getStartIndex() > location) 257 break; 258 259 previous = group; 260 } 261 return previous; 262 } 263 264 public ElementGroup findClosingGroupForGroup(ElementGroup group) { 265 List <ElementGroup> groups = getParserEngine().getGroups(); 266 if(groups == null || groups.isEmpty()) 267 return null; 268 269 int index = groups.indexOf(group)+1; 270 if(index == -1) 271 return null; 272 273 int open = 0; 274 while(index < groups.size()) { 275 ElementGroup g = groups.get(index); 276 if(g.openGroup) 277 open++; 278 else if(open == 0) 279 return g; 280 else 281 open--; 282 index++; 283 } 284 return null; 285 } 286 287 public List <ElementRule> getRules() { 288 return getParserEngine().getRules(); 289 } 290 291 public List <ElementRule> getSortedRules() { 292 return getSortedRules(getRules()); 293 } 294 295 public List <ElementRule> getSortedRules(List <ElementRule> rules) { 296 if(rules == null) 297 return null; 298 299 List <ElementRule> sortedRules = new ArrayList<ElementRule>(rules); 300 Collections.sort(sortedRules); 301 if(!sortedRules.isEmpty()) { 302 ElementRule firstRule = sortedRules.get(0); 303 if(firstRule.lexer) { 304 for(int index=0; index<sortedRules.size(); index++) { 305 ElementRule rule = sortedRules.get(0); 306 if(!rule.lexer) 307 break; 308 309 sortedRules.add(rule); 310 sortedRules.remove(0); 311 } 312 } 313 } 314 return sortedRules; 315 } 316 317 public List <ElementRule> getSelectedRules() { 318 List <ElementRule> rules = new ArrayList<ElementRule>(); for (Object o1 : rulesTree.getSelectedNodes()) { 320 DefaultMutableTreeNode node = (DefaultMutableTreeNode) o1; 321 RuleTreeUserObject o = (RuleTreeUserObject) node.getUserObject(); 322 if (o.rule != null) 323 rules.add(o.rule); 324 } 325 return rules; 326 } 327 328 public ElementRule getLastRule() { 329 List <ElementRule> rules = getParserEngine().getRules(); 330 if(rules != null && !rules.isEmpty()) 331 return rules.get(rules.size()-1); 332 else 333 return null; 334 } 335 336 public ElementRule getLastParserRule() { 337 List <ElementRule> rules = getParserEngine().getRules(); 338 for(int index = rules.size()-1; index>0; index--) { 339 ElementRule rule = rules.get(index); 340 if(!rule.lexer) 341 return rule; 342 } 343 return null; 344 } 345 346 public ElementRule getLastLexerRule() { 347 List <ElementRule> rules = getParserEngine().getRules(); 348 for(int index = rules.size()-1; index>0; index--) { 349 ElementRule rule = rules.get(index); 350 if(rule.lexer) 351 return rule; 352 } 353 return null; 354 } 355 356 public ElementRule getRuleWithName(String name) { 357 List <ElementRule> rules = getParserEngine().getRules(); 358 for (ElementRule r : rules) { 359 if (r.name.equals(name)) 360 return r; 361 } 362 return null; 363 } 364 365 public List <String > getRulesStartingWith(String match) { 366 List <String > matches = new ArrayList<String >(); 367 if(getParserEngine().getRules() == null) 368 return matches; 369 370 List <ElementRule> rules = getParserEngine().getRules(); 371 for (ElementRule r : rules) { 372 String rname = r.name.toLowerCase(); 373 if (rname.startsWith(match) && !matches.contains(r.name)) 374 matches.add(r.name); 375 } 376 return matches; 377 } 378 379 public List <ElementReference> getReferencesInRule(ElementRule rule) { 380 if(getParserEngine().getRules() == null) 381 return null; 382 383 List <ElementReference> refs = new ArrayList<ElementReference>(); 384 for (ElementReference r : getParserEngine().getReferences()) { 385 if (r.rule == rule) 386 refs.add(r); 387 } 388 return refs; 389 } 390 391 public ElementRule getEnclosingRuleAtPosition(int pos) { 392 if(getParserEngine().getRules() == null) 393 return null; 394 395 for (ElementRule r : getParserEngine().getRules()) { 396 if (r.containsIndex(pos)) 397 return r; 398 } 399 return null; 400 } 401 402 public ElementRule selectRuleInTreeAtPosition(int pos) { 403 if(programmaticallySelectingRule || getParserEngine().getRules() == null) 404 return null; 405 406 programmaticallySelectingRule = true; 407 ElementRule rule = getEnclosingRuleAtPosition(pos); 408 selectRuleInTree(rule); 409 programmaticallySelectingRule = false; 410 return rule; 411 } 412 413 public ElementRule selectRuleNameInTree(String name) { 414 if(programmaticallySelectingRule || getParserEngine().getRules() == null) 415 return null; 416 417 ElementRule rule = null; 418 programmaticallySelectingRule = true; 419 for (ElementRule r : getParserEngine().getRules()) { 420 if (r.name.equals(name)) { 421 selectRuleInTree(r); 422 rule = r; 423 break; 424 } 425 } 426 programmaticallySelectingRule = false; 427 return rule; 428 } 429 430 public ElementRule getRuleAtIndex(int index) { 431 if(getParserEngine().getRules() == null) 432 return null; 433 434 for (ElementRule r : getParserEngine().getRules()) { 435 if (index >= r.getStartIndex() && index <= r.getEndIndex()) 436 return r; 437 } 438 return null; 439 } 440 441 public boolean isRuleAtIndex(int index) { 442 return getRuleAtIndex(index) != null; 443 } 444 445 public void selectNextRule() { 446 ElementRule rule = getEnclosingRuleAtPosition(editor.getCaretPosition()); 447 int index = getParserEngine().getRules().indexOf(rule)+1; 448 rule = getParserEngine().getRuleAtIndex(index); 449 if(rule != null) { 450 editor.setCaretPosition(rule.getStartIndex()); 451 editor.rulesCaretPositionDidChange(); 452 } 453 } 454 455 public void selectRuleInTree(ElementRule rule) { 456 if(rule == null) 457 return; 458 459 Enumeration enumeration = rulesTreeRootNode.depthFirstEnumeration(); 460 while(enumeration.hasMoreElements()) { 461 DefaultMutableTreeNode node = (DefaultMutableTreeNode)enumeration.nextElement(); 462 RuleTreeUserObject n = (RuleTreeUserObject)node.getUserObject(); 463 if(n != null && n.rule == rule) { 464 TreePath path = new TreePath(node.getPath()); 465 rulesTree.setSelectionPath(path); 466 rulesTree.scrollPathToVisible(path); 467 break; 468 } 469 } 470 } 471 472 public void goToRule(ElementRule rule) { 473 editor.setCaretPosition(rule.start.getStartIndex()); 474 } 475 476 public void rebuildTree() { 477 saveExpandedNodes(); 478 rememberSelectedTreeItem(); 479 480 rulesTreeRootNode.removeAllChildren(); 481 482 List <ElementRule> rules = getParserEngine().getRules(); 483 List <ElementGroup> groups = getParserEngine().getGroups(); 484 if(rules == null || groups == null) 485 return; 486 487 if(groups.isEmpty()) { 488 buildTree(rulesTreeRootNode, rules, 0, rules.size()-1); 489 } else { 490 Stack<DefaultMutableTreeNode> parentStack = new Stack<DefaultMutableTreeNode>(); 491 parentStack.add(rulesTreeRootNode); 492 493 int ruleIndex = 0; 494 for (ElementGroup group : groups) { 495 DefaultMutableTreeNode parentNode = parentStack.peek(); 496 if (group.ruleIndex >= 0) { 497 buildTree(parentNode, rules, ruleIndex, group.ruleIndex); 498 ruleIndex = group.ruleIndex + 1; 499 } 500 501 if (group.openGroup) { 502 DefaultMutableTreeNode node = new DefaultMutableTreeNode(new RuleTreeUserObject(group)); 503 parentNode.add(node); 504 parentStack.push(node); 505 } else { 506 if (parentStack.size() > 1) 507 parentStack.pop(); 508 } 509 } 510 511 if(ruleIndex < rules.size()) { 512 DefaultMutableTreeNode parentNode = parentStack.peek(); 513 buildTree(parentNode, rules, ruleIndex, rules.size()-1); 514 } 515 } 516 517 rulesTreeModel.reload(); 518 519 restoreSelectedTreeItem(); 520 restoreExpandedNodes(); 521 } 522 523 public void rememberSelectedTreeItem() { 524 DefaultMutableTreeNode node = rulesTree.getSelectedNode(); 525 selectedObject = null; 526 if(node != null) 527 selectedObject = (RuleTreeUserObject)node.getUserObject(); 528 } 529 530 public void restoreSelectedTreeItem() { 531 if(selectedObject == null) 532 return; 533 534 DefaultMutableTreeNode node = findNodeWithRuleName(selectedObject.rule.name); 535 if(node == null) 536 return; 537 538 programmaticallySelectingRule = true; 539 TreePath path = new TreePath(node.getPath()); 540 rulesTree.setSelectionPath(path); 541 rulesTree.scrollPathToVisible(path); 542 programmaticallySelectingRule = false; 543 } 544 545 public void saveExpandedNodes() { 546 rulesTreeExpandedNodes.clear(); 547 Enumeration e = rulesTreeRootNode.depthFirstEnumeration(); 548 while(e.hasMoreElements()) { 549 DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement(); 550 if(!node.isLeaf() && !node.isRoot() && rulesTree.isExpanded(new TreePath(node.getPath()))) { 551 RuleTreeUserObject n = (RuleTreeUserObject)node.getUserObject(); 552 rulesTreeExpandedNodes.add(n.group.name); 553 } 554 } 555 } 556 557 public void restoreExpandedNodes() { 558 for (String groupName : rulesTreeExpandedNodes) { 559 DefaultMutableTreeNode node = findNodeWithGroupName(groupName); 560 if (node != null) 561 rulesTree.expandPath(new TreePath(node.getPath())); 562 } 563 } 564 565 public DefaultMutableTreeNode findNodeWithGroupName(String groupName) { 566 Enumeration e = rulesTreeRootNode.depthFirstEnumeration(); 567 while(e.hasMoreElements()) { 568 DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement(); 569 RuleTreeUserObject n = (RuleTreeUserObject)node.getUserObject(); 570 if(n.group != null && n.group.name.equalsIgnoreCase(groupName)) 571 return node; 572 } 573 return null; 574 } 575 576 public DefaultMutableTreeNode findNodeWithRuleName(String ruleName) { 577 Enumeration e = rulesTreeRootNode.depthFirstEnumeration(); 578 while(e.hasMoreElements()) { 579 DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement(); 580 RuleTreeUserObject n = (RuleTreeUserObject)node.getUserObject(); 581 if(n.rule != null && n.rule.name.equalsIgnoreCase(ruleName)) 582 return node; 583 } 584 return null; 585 } 586 587 protected void buildTree(DefaultMutableTreeNode parentNode, List <ElementRule> rules, int from, int to) { 588 List <ElementRule> subrules = rules.subList(from, to+1); 590 if(sort && !subrules.isEmpty()) { 591 subrules = getSortedRules(subrules); 592 Collections.sort(subrules); 593 ElementRule firstRule = subrules.get(0); 594 if(firstRule.lexer) { 595 for(int index=0; index<subrules.size(); index++) { 596 ElementRule rule = subrules.get(0); 597 if(!rule.lexer) 598 break; 599 600 subrules.add(rule); 601 subrules.remove(0); 602 } 603 } 604 } 605 606 for (ElementRule rule : subrules) { 607 parentNode.add(new DefaultMutableTreeNode(new RuleTreeUserObject(rule))); 608 } 609 } 610 611 public void parserDidParse() { 612 rebuildTree(); 613 if(selectNextRule) { 614 selectNextRule = false; 617 selectNextRule(); 618 } else 619 selectRuleInTreeAtPosition(editor.getCaretPosition()); 620 } 621 622 public boolean moveRule(ElementRule sourceRule, ElementRule targetRule, boolean dropAbove) { 623 if(sourceRule == null || targetRule == null) 624 return false; 625 626 String sourceRuleText = editor.getText().substring(sourceRule.getStartIndex(), sourceRule.getEndIndex()+1); 627 628 try { 629 Document doc = editor.getTextPane().getDocument(); 630 631 int removeStartIndex = sourceRule.getStartIndex(); 632 int targetInsertionIndex = dropAbove ? targetRule.getStartIndex() : targetRule.getEndIndex(); 633 634 637 int removeLength = sourceRule.getLength()+1; 639 if(removeStartIndex+removeLength > doc.getLength()) 640 removeLength--; 641 642 if(sourceRule.getStartIndex()>targetRule.getStartIndex()) { 643 doc.remove(removeStartIndex, removeLength); 644 doc.insertString(targetInsertionIndex, "\n"+sourceRuleText, null); 645 editor.setCaretPosition(targetInsertionIndex); 646 } else { 647 doc.insertString(targetInsertionIndex, "\n"+sourceRuleText, null); 648 doc.remove(removeStartIndex, removeLength); 649 editor.setCaretPosition(targetInsertionIndex-removeLength); 650 } 651 return true; 652 } catch (BadLocationException e) { 653 editor.console.print(e); 654 return false; 655 } 656 } 657 658 public void selectRuleFromUserAction() { 659 if(programmaticallySelectingRule) 662 return; 663 664 666 if(rulesTree.getSelectionCount() != 1) 667 return; 668 669 TreePath selPath[] = rulesTree.getSelectionPaths(); 670 if(selPath == null) 671 return; 672 673 List <ElementRule> selRules = new ArrayList<ElementRule>(); 674 for (TreePath aSelPath : selPath) { 675 DefaultMutableTreeNode node = (DefaultMutableTreeNode) aSelPath.getLastPathComponent(); 676 RuleTreeUserObject n = (RuleTreeUserObject) node.getUserObject(); 677 if (n.rule != null) 678 selRules.add(n.rule); 679 } 680 681 if(!selRules.isEmpty()) { 682 goToRule(selRules.get(0)); 683 rulesTree.requestFocusInWindow(); 685 } 686 } 687 688 public Cursor xjTreeDragSourceDefaultCursor(XJTree tree) { 689 return DragSource.DefaultMoveDrop; 690 } 691 692 public int xjTreeDragAndDropConstants(XJTree tree) { 693 return DnDConstants.ACTION_MOVE; 694 } 695 696 public boolean xjTreeDrop(XJTree tree, Object sourceObject, Object targetObject, int dropLocation) { 697 StatisticsAW.shared().recordEvent(StatisticsAW.EVENT_DROP_RULE); 698 699 ElementRule sourceRule = ((EditorRules.RuleTreeUserObject) sourceObject).rule; 700 ElementRule targetRule = ((EditorRules.RuleTreeUserObject) targetObject).rule; 701 702 return moveRule(sourceRule, targetRule, dropLocation == XJTree.DROP_ABOVE); 703 } 704 705 public static final Color HIGHLIGHTED_COLOR = new Color(0, 0.5f, 1, 0.4f); 706 707 public static class RulesTableRenderer extends DefaultTreeCellRenderer { 708 709 public Component getTreeCellRendererComponent( 710 JTree tree, 711 Object value, 712 boolean sel, 713 boolean expanded, 714 boolean leaf, 715 int row, 716 boolean hasFocus) 717 { 718 Component r = super.getTreeCellRendererComponent( 719 tree, value, sel, 720 expanded, leaf, row, 721 hasFocus); 722 723 if(XJSystem.isWindows()) { 725 setBackgroundSelectionColor(HIGHLIGHTED_COLOR); 726 } 727 728 setIcon(null); 729 setToolTipText(""); 730 731 DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 732 RuleTreeUserObject n = (RuleTreeUserObject)node.getUserObject(); 733 if(n.rule != null) { 734 if(n.rule.lexer) 735 setIcon(IconManager.shared().getIconLexer()); 736 else 737 setIcon(IconManager.shared().getIconParser()); 738 } 739 740 setFont(getFont().deriveFont(Font.PLAIN)); 741 setForeground(Color.black); 742 743 if(n.rule != null) { 744 if(n.rule.hasErrors()) { 745 setForeground(Color.red); 746 setToolTipText(n.rule.getErrorMessageHTML()); 747 } 748 if(n.rule.ignored) 749 setFont(getFont().deriveFont(Font.ITALIC)); 750 } 751 752 return r; 753 } 754 } 755 756 public class RuleTreeSelectionListener implements TreeSelectionListener { 757 public void valueChanged(TreeSelectionEvent e) { 758 selectRuleFromUserAction(); 759 } 760 } 761 762 public class RuleTreeMouseListener extends MouseAdapter { 763 764 public void mousePressed(MouseEvent e) { 765 selectRuleFromUserAction(); 766 checkForPopupTrigger(e); 767 } 768 769 public void mouseReleased(MouseEvent e) { 770 checkForPopupTrigger(e); 771 } 772 773 public void checkForPopupTrigger(MouseEvent e) { 774 if(e.isPopupTrigger()) { 775 rulesTree.modifySelectionIfNecessary(e); 776 777 List <Object > selectedObjects = new ArrayList<Object >(); for (Object o : rulesTree.getSelectedNodes()) { 779 DefaultMutableTreeNode node = (DefaultMutableTreeNode) o; 780 selectedObjects.add(node.getUserObject()); 781 } 782 JPopupMenu menu = editor.rulesGetContextualMenu(selectedObjects); 783 if(menu != null) 784 menu.show(e.getComponent(), e.getX(), e.getY()); 785 } 786 } 787 788 } 789 790 public static class RuleTreeUserObject implements Transferable { 791 792 public ElementRule rule; 793 public ElementGroup group; 794 795 public RuleTreeUserObject(ElementRule rule) { 796 this.rule = rule; 797 } 798 799 public RuleTreeUserObject(ElementGroup group) { 800 this.group = group; 801 } 802 803 public String toString() { 804 if(group != null) 805 return group.name; 806 else if(rule != null) 807 return rule.name; 808 else 809 return ""; 810 } 811 812 public DataFlavor [] getTransferDataFlavors() { 813 return new DataFlavor [0]; 814 } 815 816 public boolean isDataFlavorSupported(DataFlavor flavor) { 817 return false; 818 } 819 820 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException , IOException { 821 return null; 822 } 823 } 824 825 } 826 | Popular Tags |