1 package org.antlr.works.components.grammar; 2 3 import org.antlr.works.ate.ATEPanel; 4 import org.antlr.works.ate.ATEPanelDelegate; 5 import org.antlr.works.ate.ATETextPane; 6 import org.antlr.works.ate.syntax.generic.ATESyntaxLexer; 7 import org.antlr.works.ate.syntax.misc.ATELine; 8 import org.antlr.works.ate.syntax.misc.ATEThread; 9 import org.antlr.works.ate.syntax.misc.ATEToken; 10 import org.antlr.works.completion.AutoCompletionMenu; 11 import org.antlr.works.completion.AutoCompletionMenuDelegate; 12 import org.antlr.works.completion.RuleTemplates; 13 import org.antlr.works.components.ComponentContainer; 14 import org.antlr.works.components.ComponentEditor; 15 import org.antlr.works.debugger.Debugger; 16 import org.antlr.works.editor.*; 17 import org.antlr.works.find.FindAndReplace; 18 import org.antlr.works.grammar.EngineGrammar; 19 import org.antlr.works.grammar.decisiondfa.DecisionDFAEngine; 20 import org.antlr.works.interpreter.EditorInterpreter; 21 import org.antlr.works.menu.*; 22 import org.antlr.works.navigation.GoToHistory; 23 import org.antlr.works.navigation.GoToRule; 24 import org.antlr.works.prefs.AWPrefs; 25 import org.antlr.works.stats.StatisticsAW; 26 import org.antlr.works.syntax.*; 27 import org.antlr.works.syntax.element.ElementAction; 28 import org.antlr.works.syntax.element.ElementBlock; 29 import org.antlr.works.syntax.element.ElementReference; 30 import org.antlr.works.syntax.element.ElementRule; 31 import org.antlr.works.utils.Console; 32 import org.antlr.works.visualization.Visual; 33 import org.antlr.xjlib.appkit.app.XJApplication; 34 import org.antlr.xjlib.appkit.menu.XJMainMenuBar; 35 import org.antlr.xjlib.appkit.menu.XJMenu; 36 import org.antlr.xjlib.appkit.menu.XJMenuItem; 37 import org.antlr.xjlib.appkit.menu.XJMenuItemCheck; 38 import org.antlr.xjlib.appkit.swing.XJTree; 39 import org.antlr.xjlib.appkit.text.XJURLLabel; 40 import org.antlr.xjlib.appkit.undo.XJUndo; 41 import org.antlr.xjlib.appkit.undo.XJUndoDelegate; 42 import org.antlr.xjlib.appkit.utils.XJAlert; 43 import org.antlr.xjlib.appkit.utils.XJDialogProgress; 44 import org.antlr.xjlib.appkit.utils.XJDialogProgressDelegate; 45 import org.antlr.xjlib.foundation.XJUtils; 46 47 import javax.swing.*; 48 import javax.swing.event.ChangeEvent ; 49 import javax.swing.event.ChangeListener ; 50 import javax.swing.text.BadLocationException ; 51 import javax.swing.tree.DefaultMutableTreeNode ; 52 import javax.swing.tree.TreePath ; 53 import java.awt.*; 54 import java.awt.event.ActionEvent ; 55 import java.awt.event.ActionListener ; 56 import java.awt.event.MouseAdapter ; 57 import java.awt.event.MouseEvent ; 58 import java.awt.print.PrinterException ; 59 import java.io.File ; 60 import java.util.*; 61 import java.util.List ; 62 92 93 public class CEditorGrammar extends ComponentEditor implements AutoCompletionMenuDelegate, 94 EditorProvider, ATEPanelDelegate, 95 XJUndoDelegate, InspectorDelegate, 96 GrammarSyntaxDelegate 97 { 98 99 100 101 public AutoCompletionMenu autoCompletionMenu; 102 public RuleTemplates ruleTemplates; 103 104 105 106 public FindAndReplace findAndReplace; 107 public DecisionDFAEngine decisionDFAEngine; 108 109 public GoToRule goToRule; 110 public GoToHistory goToHistory; 111 112 113 114 public EditorBreakpointManager breakpointManager; 115 public EditorFoldingManager foldingManager; 116 public EditorUnderlyingManager underlyingManager; 117 public EditorAnalysisManager analysisManager; 118 119 120 121 public GrammarSyntaxEngine parserEngine; 122 public EditorRules rules; 123 public Visual visual; 124 public EditorInterpreter interpreter; 125 public Debugger debugger; 126 127 128 129 public EditorConsole console; 130 public EditorToolbar toolbar; 131 public EditorMenu editorMenu; 132 public EditorIdeas editorIdeas; 133 public EditorTips editorTips; 134 public EditorInspector editorInspector; 135 public EditorPersistence persistence; 136 137 138 139 public MenuFolding menuFolding; 140 public MenuFind menuFind; 141 public MenuGrammar menuGrammar; 142 public MenuRefactor menuRefactor; 143 public MenuGoTo menuGoTo; 144 public MenuGenerate menuGenerate; 145 public MenuDebugger menuDebugger; 146 public MenuSCM menuSCM; 147 public MenuExport menuExport; 148 149 public ATEPanel textEditor; 150 151 152 153 protected JScrollPane rulesScrollPane; 154 protected XJTree rulesTree; 155 156 protected JTabbedPane tabbedPane; 157 158 protected JLabel infoLabel; 159 protected JLabel cursorLabel; 160 protected JLabel writableLabel; 161 protected JLabel scmLabel; 162 protected ConsoleStatus consoleStatus; 163 164 protected JSplitPane rulesTextSplitPane; 165 protected JSplitPane upDownSplitPane; 166 167 168 169 protected boolean windowFirstDisplay = true; 170 protected String lastSelectedRule; 171 protected CEditorGrammarDelegate delegate; 172 173 protected List <EditorTab> tabs = new ArrayList<EditorTab>(); 174 protected AfterParseOperations afterParserOp; 175 176 177 178 protected EngineGrammar engineGrammar; 179 protected GrammarSyntax grammarSyntax; 180 181 182 private XJDialogProgress progress; 183 184 public CEditorGrammar(ComponentContainer container) { 185 super(container); 186 afterParserOp = new AfterParseOperations(); 187 } 188 189 public void setDelegate(CEditorGrammarDelegate delegate) { 190 this.delegate = delegate; 191 } 192 193 public void create() { 194 initCore(); 195 196 createInterface(); 197 198 initEditor(); 199 initMenus(); 200 201 initManagers(); 202 initComponents(); 203 204 initAutoCompletion(); 205 initTools(); 206 207 awakeInstances(); 208 awakeInterface(); 209 210 register(); 211 } 212 213 public void assemble() { 214 rulesTextSplitPane = new JSplitPane(); 215 rulesTextSplitPane.setBorder(null); 216 rulesTextSplitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); 217 rulesTextSplitPane.setLeftComponent(rulesScrollPane); 218 rulesTextSplitPane.setRightComponent(textEditor); 219 rulesTextSplitPane.setContinuousLayout(true); 220 rulesTextSplitPane.setOneTouchExpandable(true); 221 222 upDownSplitPane = new JSplitPane(); 223 upDownSplitPane.setBorder(null); 224 upDownSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); 225 upDownSplitPane.add(rulesTextSplitPane, JSplitPane.TOP); 226 upDownSplitPane.add(tabbedPane, JSplitPane.BOTTOM); 227 upDownSplitPane.setContinuousLayout(true); 228 upDownSplitPane.setOneTouchExpandable(true); 229 230 delegate = new CEditorGrammarDefaultDelegate(upDownSplitPane); 231 232 mainPanel.add(upDownSplitPane, BorderLayout.CENTER); 233 } 234 235 protected void initComponents() { 236 rules = new EditorRules(this, rulesTree); 237 visual = new Visual(this); 238 } 239 240 protected void initTools() { 241 goToRule = new GoToRule(this, getXJFrame(), getTextPane()); 242 goToHistory = new GoToHistory(); 243 findAndReplace = new FindAndReplace(this); 244 } 245 246 protected void initAutoCompletion() { 247 autoCompletionMenu = new AutoCompletionMenu(this, getTextPane(), getXJFrame()); 248 ruleTemplates = new RuleTemplates(this, getTextPane(), getXJFrame()); 249 } 250 251 protected void initCore() { 252 decisionDFAEngine = new DecisionDFAEngine(this); 253 parserEngine = new GrammarSyntaxEngine(); 254 grammarSyntax = new GrammarSyntax(this); 255 interpreter = new EditorInterpreter(this); 256 debugger = new Debugger(this); 257 } 258 259 protected void initEditor() { 260 console = new EditorConsole(this); 261 console.makeCurrent(); 262 263 editorMenu = new EditorMenu(this); 264 editorIdeas = new EditorIdeas(this); 265 editorTips = new EditorTips(this); 266 editorInspector = new EditorInspector(grammarSyntax, decisionDFAEngine, this); 267 268 persistence = new EditorPersistence(this); 269 270 engineGrammar = new EngineGrammar(this); 271 } 272 273 protected void initMenus() { 274 menuFolding = new MenuFolding(this); 275 menuFind = new MenuFind(this); 276 menuGrammar = new MenuGrammar(this); 277 menuRefactor = new MenuRefactor(this); 278 menuGoTo = new MenuGoTo(this); 279 menuGenerate = new MenuGenerate(this); 280 menuDebugger = new MenuDebugger(this); 281 menuSCM = new MenuSCM(this); 282 menuExport = new MenuExport(this); 283 } 284 285 protected void initManagers() { 286 breakpointManager = new EditorBreakpointManager(this); 287 textEditor.setBreakpointManager(breakpointManager); 288 289 foldingManager = new EditorFoldingManager(this); 290 textEditor.setFoldingManager(foldingManager); 291 292 underlyingManager = new EditorUnderlyingManager(this); 293 textEditor.setUnderlyingManager(underlyingManager); 294 295 analysisManager = new EditorAnalysisManager(this); 296 textEditor.setAnalysisManager(analysisManager); 297 } 298 299 protected void awakeInstances() { 300 editorIdeas.awake(); 301 editorTips.awake(); 302 303 menuSCM.awake(); 304 305 interpreter.awake(); 306 debugger.awake(); 307 308 toolbar.awake(); 309 310 rules.setKeyBindings(textEditor.getKeyBindings()); 311 312 textEditor.setParserEngine(parserEngine); 313 } 314 315 protected void createTextEditor() { 316 textEditor = new ATEPanel(getXJFrame()); 317 textEditor.setEditorKit(new EditorATEEditorKit(this)); 318 textEditor.setSyntaxColoring(true); 319 textEditor.setDelegate(this); 320 applyPrefs(); 321 } 322 323 protected void createRulesPane() { 324 rulesTree = new XJTree() { 325 public String getToolTipText(MouseEvent e) { 326 TreePath path = getPathForLocation(e.getX(), e.getY()); 327 if(path == null) 328 return ""; 329 330 DefaultMutableTreeNode node = (DefaultMutableTreeNode ) path.getLastPathComponent(); 331 EditorRules.RuleTreeUserObject n = (EditorRules.RuleTreeUserObject) node.getUserObject(); 332 if(n == null) 333 return ""; 334 335 ElementRule r = n.rule; 336 if(r == null || !r.hasErrors()) 337 return ""; 338 else 339 return r.getErrorMessageHTML(); 340 } 341 }; 342 rulesTree.setBorder(null); 343 rulesTree.setToolTipText(""); 345 rulesTree.setDragEnabled(true); 346 347 rulesScrollPane = new JScrollPane(rulesTree); 348 rulesScrollPane.setWheelScrollingEnabled(true); 349 } 350 351 public JComponent getRulesComponent() { 352 return rulesScrollPane; 353 } 354 355 protected void createTabbedPane() { 356 tabbedPane = new JTabbedPane(); 357 tabbedPane.setTabPlacement(JTabbedPane.BOTTOM); 358 tabbedPane.addMouseListener(new TabbedPaneMouseListener()); 359 tabbedPane.addChangeListener(new TabbedPaneChangeListener()); 360 } 361 362 public JComponent getTabbedComponent() { 363 return tabbedPane; 364 } 365 366 protected void createToolbar() { 367 toolbar = new EditorToolbar(this); 368 } 369 370 protected void createStatusBar() { 371 infoLabel = new JLabel(); 372 cursorLabel = new JLabel(); 373 writableLabel = new JLabel(); 374 scmLabel = new JLabel(); 375 consoleStatus = new ConsoleStatus(); 376 377 statusBar.add(Box.createHorizontalStrut(5)); 378 statusBar.add(infoLabel); 379 statusBar.add(Box.createHorizontalStrut(5)); 380 statusBar.add(createSeparator()); 381 statusBar.add(Box.createHorizontalStrut(5)); 382 statusBar.add(cursorLabel); 383 statusBar.add(Box.createHorizontalStrut(5)); 384 statusBar.add(createSeparator()); 385 statusBar.add(Box.createHorizontalStrut(5)); 386 statusBar.add(writableLabel); 387 statusBar.add(Box.createHorizontalStrut(5)); 388 statusBar.add(createSeparator()); 389 statusBar.add(Box.createHorizontalStrut(5)); 390 statusBar.add(consoleStatus.getPanel()); 391 statusBar.add(Box.createHorizontalStrut(5)); 392 statusBar.add(createSeparator()); 393 statusBar.add(Box.createHorizontalStrut(5)); 394 statusBar.add(scmLabel); 395 } 396 397 protected void createInterface() { 398 createTextEditor(); 399 createRulesPane(); 400 createTabbedPane(); 401 createToolbar(); 402 createStatusBar(); 403 } 404 405 protected void awakeInterface() { 406 addTab(visual); 407 addTab(interpreter); 408 addTab(debugger); 409 addTab(console); 410 411 selectVisualizationTab(); 412 } 413 414 protected void register() { 415 getXJFrame().registerUndo(this, getTextPane()); 416 } 417 418 public void applyPrefs() { 419 afterParserOp.setDefaultThreshold(AWPrefs.getParserDelay()); 420 textEditor.setFoldingEnabled(AWPrefs.getFoldingEnabled()); 421 textEditor.setLineNumberEnabled(AWPrefs.getLineNumberEnabled()); 422 textEditor.setHighlightCursorLine(AWPrefs.getHighlightCursorEnabled()); 423 textEditor.refresh(); 424 initAutoCompletion(); 427 applyFont(); 428 } 429 430 public void applyFont() { 431 getTextPane().setFont(new Font(AWPrefs.getEditorFont(), Font.PLAIN, AWPrefs.getEditorFontSize())); 432 getTextPane().setTabSize(AWPrefs.getEditorTabSize()); 433 } 434 435 public void close() { 436 afterParserOp.stop(); 437 toolbar.close(); 438 editorIdeas.close(); 439 editorMenu.close(); 440 debugger.close(); 441 visual.close(); 442 super.close(); 443 } 444 445 public void selectVisualizationTab() { 446 selectTab(visual.getTabComponent()); 447 } 448 449 public void selectInterpreterTab() { 450 selectTab(interpreter.getTabComponent()); 451 makeBottomComponentVisible(); 452 } 453 454 public void selectDebuggerTab() { 455 selectTab(debugger.getTabComponent()); 456 makeBottomComponentVisible(); 457 } 458 459 public void selectConsoleTab() { 460 selectTab(console.getTabComponent()); 461 makeBottomComponentVisible(); 462 } 463 464 public void addTab(EditorTab tab) { 465 468 int index = getSimilarTab(tab); 469 if(index > 3) { 470 tabs.remove(index); 471 tabs.add(index, tab); 472 tabbedPane.removeTabAt(index); 473 tabbedPane.insertTab(tab.getTabName(), null, tab.getTabComponent(), null, index); 474 } else { 475 tabs.add(tab); 476 tabbedPane.add(tab.getTabName(), tab.getTabComponent()); 477 } 478 479 selectTab(tab.getTabComponent()); 480 } 481 482 public int getSimilarTab(EditorTab tab) { 483 for (int i = 0; i < tabs.size(); i++) { 484 EditorTab t = tabs.get(i); 485 if(t.getTabName().equals(tab.getTabName())) 486 return i; 487 } 488 return -1; 489 } 490 491 public EditorTab getSelectedTab() { 492 return tabs.get(tabbedPane.getSelectedIndex()); 493 } 494 495 public void selectTab(Component c) { 496 if(tabbedPane.getSelectedComponent() != c) { 497 tabbedPane.setSelectedComponent(c); 498 refreshMainMenuBar(); 499 } 500 } 501 502 public void makeBottomComponentVisible() { 503 if(!isBottomComponentVisible()) { 504 setBottomComponentVisible(true); 505 } 506 } 507 508 public void setBottomComponentVisible(boolean visible) { 509 if(delegate != null) 510 delegate.setBottomComponentVisible(visible); 511 } 512 513 public boolean isBottomComponentVisible() { 514 return delegate != null && delegate.isBottomComponentVisible(); 515 } 516 517 public JComponent getToolbarComponent() { 518 return toolbar.getToolbar(); 519 } 520 521 public EngineGrammar getEngineGrammar() { 522 return engineGrammar; 523 } 524 525 public EditorConsole getConsole() { 526 return console; 527 } 528 529 public ATETextPane getTextPane() { 530 return textEditor.getTextPane(); 531 } 532 533 public ATEPanel getTextEditor() { 534 return textEditor; 535 } 536 537 public Debugger getDebugger() { 538 return debugger; 539 } 540 541 public GrammarSyntax getSyntax() { 542 return grammarSyntax; 543 } 544 545 public GrammarSyntaxParser getParser() { 546 return (GrammarSyntaxParser)parserEngine.getParser(); 547 } 548 549 public void toggleAutoIndent() { 550 textEditor.setAutoIndent(!textEditor.autoIndent()); 551 } 552 553 public void toggleSyntaxColoring() { 554 StatisticsAW.shared().recordEvent(StatisticsAW.EVENT_TOGGLE_SYNTAX_COLORING); 555 textEditor.toggleSyntaxColoring(); 556 } 557 558 public void toggleRulesSorting() { 559 StatisticsAW.shared().recordEvent(StatisticsAW.EVENT_TOGGLE_RULE_SORT); 560 rules.toggleSorting(); 561 interpreter.setRules(getRules()); 562 } 563 564 public void toggleSyntaxDiagram() { 565 StatisticsAW.shared().recordEvent(StatisticsAW.EVENT_TOGGLE_SYNTAX_DIAGRAM); 566 visual.setEnable(!visual.isEnable()); 567 if(visual.isEnable()) { 568 visual.setText(getText(), getFileName()); 569 } 570 updateVisualization(false); 571 } 572 573 public void toggleNFAOptimization() { 574 visual.toggleNFAOptimization(); 575 updateVisualization(false); 576 } 577 578 public void toggleIdeas() { 579 StatisticsAW.shared().recordEvent(StatisticsAW.EVENT_TOGGLE_IDEAS); 580 editorIdeas.toggleEnabled(); 581 } 582 583 public void toggleTips() { 584 editorTips.toggleEnabled(); 585 } 586 587 public void toggleUnderlying() { 588 textEditor.setUnderlying(!textEditor.isUnderlying()); 589 textEditor.refresh(); 590 } 591 592 public void toggleAnalysis() { 593 textEditor.toggleAnalysis(); 594 } 595 596 public void changeUpdate() { 597 ateChangeUpdate(-1, -1, false); 598 } 599 600 public void beginGroupChange(String name) { 601 disableTextPane(false); 602 beginTextPaneUndoGroup(name); 603 } 604 605 public void endGroupChange() { 606 endTextPaneUndoGroup(); 607 enableTextPane(false); 608 textEditor.parse(); 609 changeDone(); 610 } 611 612 public void enableTextPane(boolean undo) { 613 textEditor.setEnableRecordChange(true); 614 if(undo) 615 enableTextPaneUndo(); 616 } 617 618 public void disableTextPane(boolean undo) { 619 textEditor.setEnableRecordChange(false); 620 if(undo) 621 disableTextPaneUndo(); 622 } 623 624 public void beginTextPaneUndoGroup(String name) { 625 XJUndo undo = getXJFrame().getUndo(getTextPane()); 626 if(undo != null) 627 undo.beginUndoGroup(name); 628 } 629 630 public void endTextPaneUndoGroup() { 631 XJUndo undo = getXJFrame().getUndo(getTextPane()); 632 if(undo != null) 633 undo.endUndoGroup(); 634 } 635 636 public void enableTextPaneUndo() { 637 XJUndo undo = getXJFrame().getUndo(getTextPane()); 638 if(undo != null) 639 undo.enableUndo(); 640 } 641 642 public void disableTextPaneUndo() { 643 XJUndo undo = getXJFrame().getUndo(getTextPane()); 644 if(undo != null) 645 undo.disableUndo(); 646 } 647 648 public void undoManagerWillUndo(boolean redo) { 649 } 650 651 public void undoManagerDidUndo(boolean redo) { 652 changeUpdate(); 653 } 654 655 public void loadText(String text) { 656 disableTextPaneUndo(); 657 try { 658 textEditor.loadText(text); 659 grammarChanged(); 660 } catch(Exception e) { 661 e.printStackTrace(); 662 } finally { 663 enableTextPaneUndo(); 664 } 665 } 666 667 public void setText(String text) { 668 textEditor.setText(text); 669 grammarChanged(); 670 textEditor.parse(); 671 changeDone(); 672 } 673 674 public synchronized String getText() { 675 return getTextPane().getText(); 676 } 677 678 public void createRuleAtIndex(boolean lexer, String name, String content) { 679 menuRefactor.createRuleAtIndex(lexer, name, content); 680 } 681 682 public void deleteRuleAtCurrentPosition() { 683 menuRefactor.deleteRuleAtIndex(getCaretPosition()); 684 } 685 686 public void removeLeftRecursion() { 687 menuRefactor.removeLeftRecursion(); 688 } 689 690 public void convertLiteralsToSingleQuote() { 691 menuRefactor.convertLiteralsToSingleQuote(); 692 } 693 694 public void replaceText(int leftIndex, int rightIndex, String text) { 695 textEditor.replaceText(leftIndex, rightIndex, text); 696 } 697 698 public void selectTextRange(int start, int end) { 699 textEditor.selectTextRange(start, end); 700 } 701 702 public void deselectTextRange() { 703 textEditor.deselectTextRange(); 704 } 705 706 public int getSelectionLeftIndexOnTokenBoundary() { 707 ATEToken t = getTokenAtPosition(getTextPane().getSelectionStart()); 708 if(t == null) 709 return -1; 710 else 711 return t.getStartIndex(); 712 } 713 714 public int getSelectionRightIndexOnTokenBoundary() { 715 ATEToken t = getTokenAtPosition(getTextPane().getSelectionEnd()); 716 if(t == null) 717 return -1; 718 else 719 return t.getEndIndex(); 720 } 721 722 public synchronized boolean isFileWritable() { 723 String path = getFilePath(); 724 if(path == null) { 725 return true; 726 } else { 727 File f = new File (path); 728 return !f.exists() || f.canWrite(); 729 } 730 } 731 732 public synchronized String getFileFolder() { 733 return XJUtils.getPathByDeletingLastComponent(getFilePath()); 734 } 735 736 public String getTokenVocabFile(String tokenVocabName) { 737 String filePath = getFileFolder(); 738 if(filePath == null) { 739 return null; 740 } 741 742 String path = XJUtils.concatPath(filePath, tokenVocabName); 743 if(new File (path).exists()) { 744 return path; 745 } 746 747 path = XJUtils.concatPath(AWPrefs.getOutputPath(), tokenVocabName); 749 if(new File (path).exists()) { 750 return path; 751 } 752 753 return null; 754 } 755 756 public synchronized String getFilePath() { 757 return getDocument().getDocumentPath(); 758 } 759 760 public synchronized String getFileName() { 761 return getDocument().getDocumentName(); 762 } 763 764 public Container getWindowContainer() { 765 return getXJFrame().getJavaContainer(); 766 } 767 768 public GrammarSyntaxEngine getParserEngine() { 769 return parserEngine; 770 } 771 772 public List <ElementRule> getRules() { 773 if(rules.isSorted()) { 774 return rules.getSortedRules(); 775 } else 776 return rules.getRules(); 777 } 778 779 public List <ElementRule> getSortedRules() { 780 return rules.getSortedRules(); 781 } 782 783 public List <ElementBlock> getBlocks() { 784 return parserEngine.getBlocks(); 785 } 786 787 public List <ElementAction> getActions() { 788 return parserEngine.getActions(); 789 } 790 791 public List <ElementReference> getReferences() { 792 return parserEngine.getReferences(); 793 } 794 795 public List <ATEToken> getTokens() { 796 return textEditor.getTokens(); 797 } 798 799 public List <ATELine> getLines() { 800 return textEditor.getLines(); 801 } 802 803 public void goToHistoryRememberCurrentPosition() { 804 goToHistory.addPosition(getCaretPosition()); 805 refreshMainMenuBar(); 806 } 807 808 public ElementReference getCurrentReference() { 809 return getReferenceAtPosition(getCaretPosition()); 810 } 811 812 public ElementReference getReferenceAtPosition(int pos) { 813 List <ElementReference> refs = getReferences(); 814 for (ElementReference ref : refs) { 815 if (ref.containsIndex(pos)) 816 return ref; 817 } 818 return null; 819 } 820 821 public ATEToken getCurrentToken() { 822 return getTokenAtPosition(getCaretPosition()); 823 } 824 825 public ATEToken getTokenAtPosition(int pos) { 826 List <ATEToken> tokens = getTokens(); 827 if(tokens == null) 828 return null; 829 830 for (ATEToken token : tokens) { 831 if (token.containsIndex(pos)) 832 return token; 833 } 834 return null; 835 } 836 837 public ElementRule getCurrentRule() { 838 return rules.getEnclosingRuleAtPosition(getCaretPosition()); 839 } 840 841 public ElementAction getCurrentAction() { 842 List <ElementAction> actions = parserEngine.getActions(); 843 int position = getCaretPosition(); 844 for (ElementAction action : actions) { 845 if (action.containsIndex(position)) 846 return action; 847 } 848 return null; 849 } 850 851 public void setCaretPosition(int position) { 852 setCaretPosition(position, AWPrefs.getSmoothScrolling()); 853 } 854 855 public void setCaretPosition(int position, boolean animate) { 856 ElementRule rule = rules.getEnclosingRuleAtPosition(position); 857 if(rule != null && !rule.isExpanded()) { 858 foldingManager.toggleFolding(rule); 859 } 860 textEditor.setCaretPosition(position, true, animate); 861 } 862 863 public int getCaretPosition() { 864 return textEditor.getCaretPosition(); 865 } 866 867 public void customizeFileMenu(XJMenu menu) { 868 editorMenu.customizeFileMenu(menu); 869 } 870 871 public void customizeMenuBar(XJMainMenuBar menubar) { 872 editorMenu.customizeMenuBar(menubar); 873 } 874 875 public void menuItemState(XJMenuItem item) { 876 editorMenu.menuItemState(item); 877 } 878 879 public void handleMenuSelected(XJMenu menu) { 880 editorMenu.handleMenuSelected(menu); 881 } 882 883 public void updateVisualization(boolean immediate) { 884 if(visual.isEnable()) { 885 ElementRule r = rules.getEnclosingRuleAtPosition(getCaretPosition()); 886 if(r == null) { 887 visual.setPlaceholder("Select a rule to display its syntax diagram"); 888 } else { 889 if(r.hasErrors() && r.needsToBuildErrors()) { 890 engineGrammar.computeRuleErrors(r); 891 } 892 893 visual.setRule(r, immediate); 894 } 895 } else { 896 visual.setPlaceholder("Syntax Diagram Disabled"); 897 } 898 } 899 900 904 public void engineGrammarDidAnalyze() { 905 if(!visual.update()) { 907 updateVisualization(true); 908 } 909 updateInformation(); 910 } 911 912 public void updateInformation() { 913 String t; 914 int size = 0; 915 if(parserEngine.getRules() != null) 916 size = parserEngine.getRules().size(); 917 switch(size) { 918 case 0: 919 t = "No rules"; 920 break; 921 case 1: 922 t = "One rule"; 923 break; 924 default: 925 t = size+" rules"; 926 break; 927 } 928 929 int warnings = grammarSyntax.getNumberOfRulesWithErrors(); 930 if(warnings > 0) 931 t += " ("+warnings+" warning"+(warnings>0?"s":"")+")"; 932 933 infoLabel.setText(t); 934 935 if(isFileWritable()) { 936 writableLabel.setText("Writable"); 937 } else { 938 writableLabel.setText("Read-only"); 939 } 940 } 941 942 public void updateCursorInfo() { 943 cursorLabel.setText(textEditor.getCurrentLinePosition()+":"+textEditor.getCurrentColumnPosition()); 944 } 945 946 public void updateSCMStatus(String status) { 947 scmLabel.setVisible(AWPrefs.getP4Enabled()); 948 if(status != null) 949 scmLabel.setText("SCM Status: "+status); 950 else 951 scmLabel.setText(""); 952 } 953 954 957 958 public void rulesCaretPositionDidChange() { 959 updateVisualization(false); 960 } 961 962 public void rulesDidSelectRule() { 963 updateVisualization(true); 964 } 965 966 public void rulesDidChange() { 967 interpreter.updateIgnoreTokens(getRules()); 968 } 969 970 public JPopupMenu rulesGetContextualMenu(List selectedObjects) { 971 if(selectedObjects.isEmpty()) 972 return null; 973 974 ContextualMenuFactory factory = new ContextualMenuFactory(editorMenu); 975 factory.addItem(EditorMenu.MI_GROUP_RULE); 976 factory.addItem(EditorMenu.MI_UNGROUP_RULE); 977 factory.addSeparator(); 978 XJMenuItemCheck item = (XJMenuItemCheck) factory.addItem(EditorMenu.MI_IGNORE_RULE); 979 item.setSelected(rules.getFirstSelectedRuleIgnoredFlag()); 980 981 return factory.menu; 982 } 983 984 986 public void ateParserWillParse() { 987 persistence.store(); 988 } 989 990 public void ateParserDidParse() { 991 updateInformation(); 992 updateCursorInfo(); 993 994 if(windowFirstDisplay) { 995 windowFirstDisplay = false; 996 afterParseOperations(); 997 SwingUtilities.invokeLater(new Runnable () { 998 public void run() { 999 updateVisualization(true); 1000 executeFirstOpeningOperations(); 1001 findTokensToIgnore(true); 1002 } 1003 }); 1004 } else { 1005 afterParserOp.awakeThread(); 1006 } 1007 } 1008 1009 public void afterParseOperations() { 1010 persistence.restore(); 1011 1012 interpreter.setRules(getRules()); 1013 rules.parserDidParse(); 1014 grammarSyntax.parserDidParse(); 1015 decisionDFAEngine.reset(); 1016 decisionDFAEngine.refreshMenu(); 1017 1018 editorIdeas.display(getCaretPosition()); 1022 1023 visual.setText(getText(), getFileName()); 1024 updateVisualization(false); 1025 1026 textEditor.damage(); 1028 textEditor.repaint(); 1029 } 1030 1031 public void changeDone() { 1032 grammarChanged(); 1033 getDocument().changeDone(); 1034 } 1035 1036 public boolean ensureDocumentSaved() { 1037 return getDocument().getDocumentPath() != null || getDocument().performSave(false) == XJApplication.YES; 1038 } 1039 1040 public void grammarChanged() { 1041 engineGrammar.makeDirty(); 1042 } 1043 1044 public void consolePrint(String s, int level) { 1045 consoleStatus.showLevel(level); 1046 } 1047 1048 public void clearConsoleStatus() { 1049 consoleStatus.clearMessage(); 1050 } 1051 1052 public void notificationPrefsChanged() { 1053 applyPrefs(); 1054 updateSCMStatus(null); 1055 } 1056 1057 public void notificationDebuggerStarted() { 1058 refreshMainMenuBar(); 1059 editorIdeas.hide(); 1060 } 1061 1062 public void componentShouldLayout(Dimension size) { 1063 if(rulesTextSplitPane != null) 1064 rulesTextSplitPane.setDividerLocation((int)(size.width*0.2)); 1065 if(upDownSplitPane != null) 1066 upDownSplitPane.setDividerLocation((int)(size.height*0.5)); 1067 1068 interpreter.componentShouldLayout(); 1069 debugger.componentShouldLayout(size); 1070 } 1071 1072 public void componentDidAwake() { 1073 updateInformation(); 1074 updateCursorInfo(); 1075 menuSCM.setSilent(true); 1076 menuSCM.queryFileStatus(); 1077 1078 SwingUtilities.invokeLater(new Runnable () { 1082 public void run() { 1083 getTextPane().requestFocusInWindow(); 1084 } 1085 }); 1086 } 1087 1088 public void componentActivated() { 1089 grammarSyntax.resetTokenVocab(); 1090 grammarSyntax.rebuildAll(); 1091 textEditor.getTextPane().setWritable(isFileWritable()); 1092 textEditor.refresh(); 1093 updateInformation(); 1094 } 1095 1096 public void componentDidHide() { 1097 editorIdeas.hide(); 1101 } 1102 1103 public void componentIsSelected() { 1104 getTextPane().requestFocusInWindow(); 1105 } 1106 1107 public void componentDocumentContentChanged() { 1108 int oldCursorPosition = getCaretPosition(); 1110 getDocument().reload(); 1111 grammarChanged(); 1112 setCaretPosition(Math.min(oldCursorPosition, getText().length())); 1113 } 1114 1115 1118 1119 public List <String > autoCompletionMenuGetMatchingWordsForPartialWord(String partialWord) { 1120 if(parserEngine == null || parserEngine.getRules() == null) 1121 return null; 1122 1123 partialWord = partialWord.toLowerCase(); 1124 List <String > matchingRules = new ArrayList<String >(); 1125 1126 if(rules.isRuleAtIndex(getCaretPosition())) { 1127 1129 List <ElementRule> sortedRules = Collections.list(Collections.enumeration(parserEngine.getRules())); 1130 Collections.sort(sortedRules,new Comparator<ElementRule>() { 1131 public int compare(ElementRule o1, ElementRule o2) { 1132 return o1.name.compareToIgnoreCase(o2.name); 1133 } 1134 }); 1135 1136 for (ElementRule rule : sortedRules) { 1137 if (rule.name.toLowerCase().startsWith(partialWord) && !matchingRules.contains(rule.name)) 1138 matchingRules.add(rule.name); 1139 } 1140 } else { 1141 1143 List <ElementReference> sortedUndefinedReferences = Collections.list(Collections.enumeration(grammarSyntax.getUndefinedReferences())); 1144 Collections.sort(sortedUndefinedReferences,new Comparator<ElementReference>() { 1145 public int compare(ElementReference o1, ElementReference o2) { 1146 return o1.rule.name.compareToIgnoreCase(o2.rule.name); 1147 } 1148 }); 1149 1150 for (ElementReference ref : sortedUndefinedReferences) { 1151 String attr = ref.token.getAttribute(); 1152 if (attr.toLowerCase().startsWith(partialWord) 1153 && !attr.equals(partialWord) 1154 && !matchingRules.contains(attr)) { 1155 matchingRules.add(attr); 1156 } 1157 } 1158 } 1159 1160 return matchingRules; 1161 } 1162 1163 public void autoCompletionMenuWillDisplay() { 1164 editorIdeas.hide(); 1166 } 1167 1168 public void ateChangeUpdate(int offset, int length, boolean insert) { 1169 changeDone(); 1170 visual.cancelDrawingProcess(); 1171 } 1172 1173 public void ateAutoIndent(int offset, int length) { 1174 try { 1175 GrammarAutoIndent.autoIndentOnSpecificKeys(this, getTextPane().getDocument(), offset, length); 1176 } catch (BadLocationException e) { 1177 } 1179 } 1180 1181 public void ateMousePressed(Point point) { 1182 if(!debugger.isRunning()) 1183 editorIdeas.display(point); 1184 } 1185 1186 public void ateMouseExited() { 1187 if(getTextPane().hasFocus()) { 1188 editorTips.hide(); 1191 } 1192 } 1193 1194 public void ateMouseMoved(Point relativePoint) { 1195 if(getTextPane().hasFocus()) { 1196 Point absolutePoint = SwingUtilities.convertPoint(getTextPane(), relativePoint, getJavaContainer()); 1197 editorTips.display(relativePoint, absolutePoint); 1198 } 1199 } 1200 1201 public void ateInvokePopUp(Component component, int x, int y) { 1202 JPopupMenu m = editorMenu.getContextualMenu(textEditor.getTextIndexAtPosition(x, y)); 1203 if(m != null) 1204 m.show(component, x, y); 1205 } 1206 1207 public void ateCaretUpdate(int index) { 1208 updateCursorInfo(); 1209 if(getTextPane().hasFocus()) { 1210 editorIdeas.hide(); 1211 if(!debugger.isRunning()) 1212 editorIdeas.display(getCaretPosition()); 1213 } 1214 1215 autoCompletionMenu.updateAutoCompleteList(); 1217 1218 ElementRule rule = rules.selectRuleInTreeAtPosition(index); 1223 if(rule == null || rule.name == null) { 1224 updateVisualization(false); 1225 lastSelectedRule = null; 1226 return; 1227 } 1228 1229 if(lastSelectedRule == null || !lastSelectedRule.equals(rule.name)) { 1230 lastSelectedRule = rule.name; 1231 updateVisualization(false); 1232 } 1233 } 1234 1235 public void executeFirstOpeningOperations() { 1236 checkGrammarVersion(); 1238 } 1239 1240 public void checkGrammarVersion() { 1241 1244 boolean version2 = false; 1245 List <ATEToken> tokens = parserEngine.getTokens(); 1246 for(int index=0; index<tokens.size(); index++) { 1247 ATEToken t = tokens.get(index); 1248 if(t.type == ATESyntaxLexer.TOKEN_ID && t.getAttribute().equals("class")) { 1249 if(index+2<tokens.size()) { 1250 ATEToken t2 = tokens.get(index+2); 1251 if(t2.type == ATESyntaxLexer.TOKEN_ID && t2.getAttribute().equals("extends")) { 1252 version2 = true; 1253 break; 1254 } 1255 } 1256 } 1257 } 1258 1259 if(version2) { 1260 XJAlert.display(getWindowContainer(), "Incompatible Grammar Version", "This grammar does not appear to be an ANTLR 3.x grammar." + 1261 "\nANTLRWorks includes ANTLR 3.x and therefore only ANTLR 3.x grammars are recognized."); 1262 } 1263 } 1264 1265 public void findTokensToIgnore(boolean reset) { 1266 rules.findTokensToIgnore(reset); 1267 interpreter.setRules(getRules()); 1268 } 1269 1270 public boolean wasSaving = false; 1271 1272 public boolean componentDocumentWillSave() { 1273 AWPrefs.setLastSavedDocument(getFilePath()); 1274 1275 if(menuSCM.isFileWritable()) 1276 return true; 1277 1278 if(XJAlert.displayAlertYESNO(getWindowContainer(), "Cannot Save", "This file is currently closed in the SCM depot.\nDo you want to open it for edit before saving its content ?") == XJAlert.YES) { 1279 menuSCM.editFile(); 1281 wasSaving = true; 1284 } 1285 return false; 1286 } 1287 1288 public void scmCommandsDidComplete() { 1289 if(wasSaving) { 1290 wasSaving = false; 1291 getDocument().performSave(false); 1292 } 1293 } 1294 1295 public static final String KEY_SPLITPANE_A = "KEY_SPLITPANE_A"; 1296 public static final String KEY_SPLITPANE_B = "KEY_SPLITPANE_B"; 1297 public static final String KEY_INTERPRETER = "KEY_INTERPRETER"; 1298 public static final String KEY_DEBUGGER = "KEY_DEBUGGER"; 1299 1300 public void setPersistentData(Map data) { 1301 if(data == null) 1302 return; 1303 1304 Integer i = (Integer )data.get(KEY_SPLITPANE_A); 1305 if(i != null && rulesTextSplitPane != null) 1306 rulesTextSplitPane.setDividerLocation(i.intValue()); 1307 1308 i = (Integer )data.get(KEY_SPLITPANE_B); 1309 if(i != null && upDownSplitPane != null) 1310 upDownSplitPane.setDividerLocation(i.intValue()); 1311 1312 interpreter.setPersistentData((Map) data.get(KEY_INTERPRETER)); 1313 debugger.setPersistentData((Map) data.get(KEY_DEBUGGER)); 1314 } 1315 1316 public Map<String , Object > getPersistentData() { 1317 Map<String ,Object > data = new HashMap<String , Object >(); 1318 if(rulesTextSplitPane != null) 1319 data.put(KEY_SPLITPANE_A, rulesTextSplitPane.getDividerLocation()); 1320 if(upDownSplitPane != null) 1321 data.put(KEY_SPLITPANE_B, upDownSplitPane.getDividerLocation()); 1322 data.put(KEY_INTERPRETER, interpreter.getPersistentData()); 1323 data.put(KEY_DEBUGGER, debugger.getPersistentData()); 1324 return data; 1325 } 1326 1327 public void print() { 1328 try { 1329 textEditor.print(); 1330 } catch (PrinterException e) { 1331 XJAlert.display(getWindowContainer(), "Print Error", "An error occurred while printing:\n"+e.toString()); 1332 } 1333 } 1334 1335 public void showProgress(String title, XJDialogProgressDelegate delegate) { 1336 if(progress == null) 1337 progress = new XJDialogProgress(getWindowContainer()); 1338 progress.setInfo(title); 1339 progress.setCancellable(true); 1340 progress.setDelegate(delegate); 1341 progress.setIndeterminate(true); 1342 progress.display(); 1343 } 1344 1345 public void hideProgress() { 1346 progress.close(); 1347 } 1348 1349 1352 protected class AfterParseOperations extends ATEThread { 1353 1354 public AfterParseOperations() { 1355 start(); 1356 } 1357 1358 protected void threadRun() throws Exception { 1359 afterParseOperations(); 1360 } 1361 } 1362 1363 protected class ConsoleStatus { 1364 1365 public Box box; 1366 public XJURLLabel label; 1367 public boolean visible; 1368 public int currentDisplayedLevel; 1369 1370 public ConsoleStatus() { 1371 box = Box.createHorizontalBox(); 1372 1373 label = new XJURLLabel(new ActionListener () { 1374 public void actionPerformed(ActionEvent e) { 1375 selectConsoleTab(); 1376 clearMessage(); 1377 } 1378 }); 1379 1380 clearMessage(); 1381 } 1382 1383 public void showMessage(String message, Color color) { 1384 label.setText(message); 1385 label.setUnvisitedURLColor(color); 1386 label.setVisitedURLColor(color); 1387 label.repaint(); 1388 } 1389 1390 public void showLevel(int level) { 1391 if(level == Console.LEVEL_NORMAL) 1392 return; 1393 1394 if(!visible) { 1395 visible = true; 1396 box.removeAll(); 1397 box.add(label); 1398 box.revalidate(); 1399 } 1400 1401 if(level > currentDisplayedLevel) { 1402 currentDisplayedLevel = level; 1403 if(level == Console.LEVEL_ERROR) 1404 showMessage("Errors reported in console", Color.red); 1405 else 1406 showMessage("Warnings reported in console", Color.blue); 1407 } 1408 } 1409 1410 public void clearMessage() { 1411 label.setText(""); 1412 box.removeAll(); 1413 box.add(Box.createHorizontalStrut(20)); 1414 visible = false; 1415 currentDisplayedLevel = Console.LEVEL_NORMAL; 1416 } 1417 1418 public JComponent getPanel() { 1419 return box; 1420 } 1421 } 1422 1423 protected class TabbedPaneMouseListener extends MouseAdapter { 1424 1425 protected static final int CLOSING_INDEX_LIMIT = 4; 1426 1427 public void displayPopUp(MouseEvent event) { 1428 if(tabbedPane.getSelectedIndex() < CLOSING_INDEX_LIMIT) 1429 return; 1430 1431 if(!event.isPopupTrigger()) 1432 return; 1433 1434 JPopupMenu popup = new JPopupMenu(); 1435 JMenuItem item = new JMenuItem("Close"); 1436 item.addActionListener(new ActionListener () { 1437 public void actionPerformed(ActionEvent event) { 1438 if(tabbedPane.getSelectedIndex() < CLOSING_INDEX_LIMIT) 1439 return; 1440 1441 tabs.remove(tabbedPane.getSelectedIndex()); 1442 tabbedPane.removeTabAt(tabbedPane.getSelectedIndex()); 1443 } 1444 }); 1445 popup.add(item); 1446 popup.show(event.getComponent(), event.getX(), event.getY()); 1447 } 1448 1449 public void mousePressed(MouseEvent event) { 1450 displayPopUp(event); 1451 } 1452 1453 public void mouseReleased(MouseEvent event) { 1454 displayPopUp(event); 1455 } 1456 } 1457 1458 protected class TabbedPaneChangeListener implements ChangeListener { 1459 public void stateChanged(ChangeEvent e) { 1460 refreshMainMenuBar(); 1461 } 1462 } 1463 1464} 1465 | Popular Tags |