|
SyntaxTreeViewer |
|
1 /* 2 * SyntaxTreeViewer.java 3 * 4 * Copyright (c) 1998-2001, The University of Sheffield. 5 * 6 * This file is part of GATE (see http://gate.ac.uk/), and is free 7 * software, licenced under the GNU Library General Public License, 8 * Version 2, June 1991 (in the distribution as file licence.html, 9 * and also available at http://gate.ac.uk/gate/licence.html). 10 * 11 * Kalina Bontcheva, 20/09/2000 12 * 13 * $Id: SyntaxTreeViewer.java,v 1.22 2003/01/28 10:01:16 marin Exp $ 14 */ 15 16 package gate.gui; 17 18 //java imports 19 import java.util.*; 20 import java.beans.*; 21 import java.net.URL; 22 23 24 //AWT imports - layouts and events 25 import java.awt.*; 26 import java.awt.event.*; 27 28 //SWING imports 29 import javax.swing.*; 30 import javax.swing.event.PopupMenuListener; 31 import javax.swing.event.PopupMenuEvent; 32 33 //GATE imports 34 import gate.util.*; 35 import gate.*; 36 import gate.creole.*; 37 38 39 /** 40 * The SyntaxTreeViewer is capable of showing and editing utterances (fancy 41 * name for sentences) and the 42 * attached syntax trees. It works by taking an utterance and all Token 43 * annotations and constructs the text. Then it also gets all SyntaxTreeNode 44 * annotations and builds and shows the syntac tree for that utterance. The 45 * leaves of the tree are the tokens, which constitute the utterance.<P> 46 * 47 * It is possible to configure the annotation types that are used by the 48 * viewer. The textAnnotationType property specifies the type 49 * of annotation which is used to denote the utterance (sentence). 50 * In GATE, the value of this property is not set directly, but is derived 51 * from the VR configuration information from creole.xml (explained below). 52 * 53 * The treeNodeAnnotationType is the name of the 54 * annotations which encode the SyntaxTreeNodes; default - SyntaxTreeNode. 55 * To change when part of GATE, modify the <PARAMETER> setting of the 56 * TreeViewer entry in creole.xml. Similarly, one can change which annotation 57 * is used for chunking the utterance. By default, it is Token, which is also 58 * specified in creole.xml as a parameter in the treeviewer entry. 59 * 60 * The component assumes that the annotations of type treeNodeAnnotationType have 61 * features called: cat with a value String; consists which is a List either 62 * empty or with annotation ids of the node's children; and optionally 63 * text which contains 64 * the text covered by this annotation. The component will work fine even 65 * without the last feature. Still when it creates annotations, 66 * these will have this feature added. <P> 67 * 68 * 69 * Newly added tree nodes to the tree are added to the document 70 * as annotations and deleted nodes are automatically deleted from the document 71 * only after OK is chosen in the dialog. Cancel does not make any changes 72 * permanent. <P> 73 * 74 * Configuring the viewer in GATE<P> 75 * The viewer is configured in creole.xml. The default entry is: 76 * <PRE> 77 * <RESOURCE> 78 * <NAME>Syntax tree viewer</NAME> 79 * <CLASS>gate.gui.SyntaxTreeViewer</CLASS> 80 * <!-- type values can be "large" or "small"--> 81 * <GUI> 82 * <MAIN_VIEWER/> 83 * <ANNOTATION_TYPE_DISPLAYED>Sentence</ANNOTATION_TYPE_DISPLAYED> 84 * <PARAMETER NAME="treeNodeAnnotationType" DEFAULT="SyntaxTreeNode" 85 * RUNTIME="false" OPTIONAL="true">java.lang.String 86 * </PARAMETER> 87 * <PARAMETER NAME="tokenType" DEFAULT="Token" RUNTIME="false" 88 * OPTIONAL="true">java.lang.String 89 * </PARAMETER> 90 * </GUI> 91 * </RESOURCE> 92 * </PRE> 93 * 94 * The categories that appear in the menu for manual annotation are determined 95 * from SyntaxTreeViewerSchema.xml. If you want to change the default set, 96 * you must edit this file and update your Gate jar accordingly (e.g., by 97 * recompilation. This does not affect the categories of SyntaxTreeNode 98 * annotations, which have been created automatically by some other process, 99 * e.g., a parser PR. 100 * 101 * <P> 102 * If used outside GATE, 103 * in order to have appropriate behaviour always put this component inside a 104 * scroll pane or something similar that provides scrollers. 105 * Example code: <BREAK> 106 * <PRE> 107 * JScrollPane scroller = new JScrollPane(syntaxTreeViewer1); 108 * scroller.setPreferredSize(syntaxTreeViewer1.getPreferredSize()); 109 * frame.getContentPane().add(scroller, BorderLayout.CENTER); 110 * </PRE> 111 * 112 * 113 * The default way is to pass just one annotation of type textAnnotationType 114 * which corresponds to the entire sentence or utterance to be annotated with 115 * syntax tree information. Then the viewer automatically tokenises it 116 * (by obtaining the relevant token annotations) and creates the leaves.<P> 117 * 118 * To create a new annotation, use setSpan, instead of setAnnotation. 119 * 120 * <P> In either 121 * case, you must call setTarget first, because that'll provide the viewer 122 * with the document's annotation set, from where it can obtain the token 123 * annotations. 124 * <P> If you intend to use the viewer outside GATE and do not understand 125 * the API, e-mail gate@dcs.shef.ac.uk. 126 */ 127 128 public class SyntaxTreeViewer extends AbstractVisualResource 129 implements Scrollable, ActionListener, MouseListener, 130 AnnotationVisualResource { 131 132 /** The annotation type used to encode each tree node*/ 133 public static final String TREE_NODE_ANNOTATION_TYPE = "SyntaxTreeNode"; 134 /** The name of the feature that encodes the tree node's category information */ 135 public static final String NODE_CAT_FEATURE_NAME = "cat"; 136 /** The name of the feature that encodes the subtree annotations */ 137 public static final String NODE_CONSISTS_FEATURE_NAME = "consists"; 138 139 // class members 140 // whether to use any layout or not 141 protected boolean laidOut = false; 142 143 // display all buttons x pixels apart horizontally 144 protected int horizButtonGap = 5; 145 146 // display buttons at diff layers x pixels apart vertically 147 protected int vertButtonGap = 50; 148 149 // extra width in pixels to be added to each button 150 protected int extraButtonWidth = 10; 151 152 // number of pixels to be used as increment by scroller 153 protected int maxUnitIncrement = 10; 154 155 // GUI members 156 BorderLayout borderLayout1 = new BorderLayout(); 157 JPopupMenu popup = new JPopupMenu(); //the right-click popup 158 Color buttonBackground; 159 Color selectedNodeColor = Color.red.darker(); 160 161 // the HashSet with the coordinates of the lines to draw 162 HashSet lines = new HashSet(); 163 164 // The utterance to be annotated as a sentence. It's not used if the tree 165 // is passed 166 // as annotations. 167 protected Annotation utterance; 168 protected Long utteranceStartOffset = new Long(0); 169 protected Long utteranceEndOffset = new Long(0); 170 protected AnnotationSet currentSet = null; 171 172 protected String tokenType = ANNIEConstants.TOKEN_ANNOTATION_TYPE; 173 174 // for internal use only. Set when the utterance is set. 175 protected String displayedString = ""; 176 177 // The name of the annotation type which is used to locate the 178 // stereotype with the allowed categories 179 // also when reading and creating annotations 180 protected String treeNodeAnnotationType = TREE_NODE_ANNOTATION_TYPE; 181 182 // The annotation name of the annotations used to extract the 183 // text that appears at the leaves of the tree. For now the viewer 184 // supports only one such annotation but might be an idea to extend it 185 // so that it gets its text off many token annotations, which do not 186 // need to be tokenised or off the syntax tree annotations themselves. 187 protected String textAnnotationType = ANNIEConstants.SENTENCE_ANNOTATION_TYPE; 188 189 // all leaf nodes 190 protected HashMap leaves = new HashMap(); 191 192 // all non-terminal nodes 193 protected HashMap nonTerminals = new HashMap(); 194 195 // all buttons corresponding to any node 196 protected HashMap buttons = new HashMap(); 197 198 // all selected buttons 199 protected Vector selection = new Vector(); 200 201 // all annotations to be displayed 202 protected AnnotationSet treeAnnotations; 203 204 protected Document document = null; 205 // the document to which the annotations belong 206 207 //true when a new utterance annotation has been added 208 //then if the user presses cancel, I need to delete it 209 protected boolean utteranceAdded = false; 210 211 212 public SyntaxTreeViewer() { 213 try { 214 jbInit(); 215 } 216 catch(Exception ex) { 217 ex.printStackTrace(Err.getPrintWriter()); 218 } 219 220 } 221 222 //CONSTRUCTORS 223 private SyntaxTreeViewer(String annotType) { 224 225 treeNodeAnnotationType = annotType; 226 try { 227 jbInit(); 228 } 229 catch(Exception ex) { 230 ex.printStackTrace(Err.getPrintWriter()); 231 } 232 } 233 234 //METHODS 235 private void jbInit() throws Exception { 236 237 //check if we're using a layout; preferrably not 238 if (laidOut) 239 this.setLayout(borderLayout1); 240 else 241 this.setLayout(null); 242 243 this.setPreferredSize(new Dimension (600, 400)); 244 this.setSize(600, 400); 245 this.setBounds(0, 0, 600, 400); 246 this.addComponentListener(new java.awt.event.ComponentAdapter() { 247 public void componentShown(ComponentEvent e) { 248 this_componentShown(e); 249 } 250 public void componentHidden(ComponentEvent e) { 251 this_componentHidden(e); 252 } 253 }); 254 this.addPropertyChangeListener(new java.beans.PropertyChangeListener() { 255 256 public void propertyChange(PropertyChangeEvent e) { 257 this_propertyChange(e); 258 } 259 }); 260 261 buttonBackground = Color.red; //this.getBackground(); 262 263 //get all categories from stereotype 264 fillCategoriesMenu(); 265 266 //initialise the popup menu 267 268 //add popup to container 269 this.add(popup); 270 }// private void jbInit() 271 272 // Methods required by AnnotationVisualResource 273 274 /** 275 * Called by the GUI when this viewer/editor has to initialise itself for a 276 * specific annotation or text span. 277 * @param target the object which will always be a {@link gate.AnnotationSet} 278 */ 279 280 public void setTarget(Object target) { 281 if (target == null) return; 282 currentSet = (AnnotationSet) target; 283 document = currentSet.getDocument(); 284 } 285 286 /** 287 * Used when the viewer/editor has to display/edit an existing annotation 288 * @param ann the annotation to be displayed or edited. If ann is null then 289 * the method simply returns 290 */ 291 public void setAnnotation(Annotation ann){ 292 if (ann == null) return; 293 294 utterance = ann; 295 utteranceStartOffset = utterance.getStartNode().getOffset(); 296 utteranceEndOffset = utterance.getEndNode().getOffset(); 297 textAnnotationType = ann.getType(); 298 299 clearAll(); 300 utterances2Trees(); 301 annotations2Trees(); 302 this.setVisible(true); 303 repaint(); 304 } 305 306 /** 307 * Used when the viewer has to create new annotations. 308 * @param startOffset the start offset of the span covered by the new 309 * annotation(s). If is <b>null</b> the method will simply return. 310 * @param endOffset the end offset of the span covered by the new 311 * annotation(s). If is <b>null</b> the method will simply return. 312 */ 313 public void setSpan(Long startOffset, Long endOffset, String annotType){ 314 // If one of them is null, then simply return. 315 if (startOffset == null || endOffset == null) return; 316 if (document == null) return; 317 318 try { 319 Integer newId = currentSet.add( startOffset, endOffset, annotType, 320 Factory.newFeatureMap()); 321 utterance = currentSet.get(newId); 322 utteranceAdded = true; 323 textAnnotationType = annotType; 324 setAnnotation(utterance); 325 326 } catch (InvalidOffsetException ioe) { 327 ioe.printStackTrace(Err.getPrintWriter()); 328 } 329 330 } 331 332 /** 333 * Called by the GUI when the user has pressed the "OK" button. This should 334 * trigger the saving of the newly created annotation(s) 335 */ 336 public void okAction() throws GateException{ 337 //Out.println("Visible coords" + this.getVisibleRect().toString()); 338 //Out.println("Size" + this.getBounds().toString()); 339 STreeNode.transferAnnotations(document, currentSet); 340 341 } //okAction() 342 343 /** 344 * Called by the GUI when the user has pressed the "Cancel" button. This should 345 * trigger the cleanup operation 346 */ 347 public void cancelAction() throws GateException{ 348 //if we added a new utterance but user does not want it any more... 349 if (utteranceAdded) { 350 currentSet.remove(utterance); //delete it 351 utteranceAdded = false; 352 } 353 //also cleanup the temporary annotation sets used by the viewer 354 //to cache the added and deleted tree annotations 355 STreeNode.undo(document); 356 357 } //okAction() 358 359 360 /** 361 * Checks whether this viewer/editor can handle a specific annotation type. 362 * @param annotationType represents the annotation type being questioned.If 363 * it is <b>null</b> then the method will return false. 364 * @return true if the SchemaAnnotationEditor can handle the annotationType 365 * or false otherwise. 366 */ 367 public boolean canDisplayAnnotationType(String annotationType){ 368 // Returns true only if the there is an AnnotationSchema with the same type 369 // as annotationType. 370 if (annotationType == null) return false; 371 boolean found = false; 372 373 java.util.List specificEditors = Gate.getCreoleRegister(). 374 getAnnotationVRs(annotationType); 375 Iterator editorIter = specificEditors.iterator(); 376 while(editorIter.hasNext() && !found){ 377 String editorClass = (String)editorIter.next(); 378 379 Out.println(editorClass); 380 if (editorClass.indexOf(this.getClass().getName()) > -1) { 381 textAnnotationType = annotationType; 382 found = true; 383 } 384 } 385 386 return found; 387 }// canDisplayAnnotationType(); 388 389 390 /* public static void main(String[] args) throws Exception { 391 Gate.init(); 392 // final String text = "This is a sentence. That is another one."; 393 final String text = "कल्इनكطب Калина Kalina"; 394 final Document doc = Factory.newDocument(text); 395 396 // that works too but only use if you have the test file there. 397 // final Document doc = Factory.newDocument( 398 // new URL("file:///z:/temp/weird.txt"), "UTF-8"); 399 400 401 final SyntaxTreeViewer syntaxTreeViewer1 = 402 new SyntaxTreeViewer("SyntaxTreeNode"); 403 //syntaxTreeViewer1.setUnicodeSupportEnabled(true); 404 //need to set the document here!!!! 405 406 407 JFrame frame = new JFrame(); 408 409 //INITIALISE THE FRAME, ETC. 410 frame.setEnabled(true); 411 frame.setTitle("SyntaxTree Viewer"); 412 frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 413 414 // frame.getContentPane().add(syntaxTreeViewer1, BorderLayout.CENTER); 415 // intercept the closing event to shut the application 416 frame.addWindowListener(new WindowAdapter() { 417 public void windowClosing(WindowEvent e) { 418 AnnotationSet hs = doc.getAnnotations().get("SyntaxTreeNode"); 419 if (hs != null && hs.size() > 0) { 420 int k = 0; 421 for (Iterator i = hs.iterator(); i.hasNext(); k++) { 422 Out.println("Tree Annot " + k + ": "); 423 Out.println(i.next().toString()); 424 } 425 } //if 426 Out.println("Exiting..."); 427 //System.exit(0); 428 } 429 }); 430 431 //Put the bean in a scroll pane. 432 JScrollPane scroller = new JScrollPane(syntaxTreeViewer1); 433 scroller.setPreferredSize(syntaxTreeViewer1.getPreferredSize()); 434 frame.getContentPane().add(scroller, BorderLayout.CENTER); 435 436 //DISPLAY FRAME 437 frame.pack(); 438 frame.show(); 439 440 FeatureMap attrs = Factory.newFeatureMap(); 441 attrs.put("time", new Long(0)); 442 attrs.put("text", doc.getContent().toString()); 443 */ 444 /* 445 FeatureMap attrs1 = Factory.newFeatureMap(); 446 attrs1.put("cat", "N"); 447 attrs1.put("text", "This"); 448 attrs1.put("consists", new Vector()); 449 450 FeatureMap attrs2 = Factory.newFeatureMap(); 451 attrs2.put("cat", "V"); 452 attrs2.put("text", "is"); 453 attrs2.put("consists", new Vector()); 454 */ 455 456 /* 457 doc.getAnnotations().add( new Long(0), new Long( 458 doc.getContent().toString().length()),"utterance", attrs); 459 */ 460 /* Integer id1 = doc.getAnnotations().add(new Long(0), new Long(4), 461 "SyntaxTreeNode", attrs1); 462 Integer id2 = doc.getAnnotations().add(new Long(5), new Long(7), 463 "SyntaxTreeNode", attrs2); 464 465 FeatureMap attrs3 = Factory.newFeatureMap(); 466 attrs3.put("cat", "VP"); 467 attrs3.put("text", "This is"); 468 Vector consists = new Vector(); 469 consists.add(id1); 470 consists.add(id2); 471 attrs3.put("consists", consists); 472 doc.getAnnotations().add(new Long(0), new Long(7), 473 "SyntaxTreeNode", attrs3); 474 */ 475 476 /* 477 HashSet set = new HashSet(); 478 set.add("utterance"); 479 set.add("SyntaxTreeNode"); 480 AnnotationSet annots = doc.getAnnotations().get(set); 481 syntaxTreeViewer1.setTreeAnnotations(annots); 482 483 }// public static void main 484 */ 485 486 protected void paintComponent(Graphics g) { 487 super.paintComponent( g); 488 drawLines(g); 489 }// protected void paintComponent(Graphics g) 490 491 492 private void drawLines(Graphics g) { 493 494 for (Iterator i = lines.iterator(); i.hasNext(); ) { 495 Coordinates coords = (Coordinates) i.next(); 496 497 g.drawLine( coords.getX1(), 498 coords.getY1(), 499 coords.getX2(), 500 coords.getY2()); 501 }// for 502 }// private void drawLines(Graphics g) 503 504 public Dimension getPreferredScrollableViewportSize() { 505 return getPreferredSize(); 506 }// public Dimension getPreferredScrollableViewportSize() 507 508 public int getScrollableUnitIncrement(Rectangle visibleRect, 509 int orientation, int direction) { 510 return maxUnitIncrement; 511 }// public int getScrollableUnitIncrement 512 513 public int getScrollableBlockIncrement(Rectangle visibleRect, 514 int orientation, int direction) { 515 if (orientation == SwingConstants.HORIZONTAL) 516 return visibleRect.width - maxUnitIncrement; 517 else 518 return visibleRect.height - maxUnitIncrement; 519 }// public int getScrollableBlockIncrement 520 521 public boolean getScrollableTracksViewportWidth() { 522 return false; 523 }// public boolean getScrollableTracksViewportWidth() 524 525 public boolean getScrollableTracksViewportHeight() { 526 return false; 527 } 528 529 void this_propertyChange(PropertyChangeEvent e) { 530 531 //we have a new utterance to display and annotate 532 if (e.getPropertyName().equals("utterance")) { 533 clearAll(); 534 utterances2Trees(); 535 } 536 537 } //this_propertyChange 538 539 /** 540 * Clear all buttons and tree nodes created because component is being 541 * re-initialised. Not sure it works perfectly. 542 */ 543 private void clearAll() { 544 lines.clear(); 545 this.removeAll(); 546 buttons.clear(); 547 leaves.clear(); 548 nonTerminals.clear(); 549 } 550 551 /** 552 * Converts the annotations into treeNodes 553 */ 554 private void annotations2Trees() { 555 if (document == null) return; 556 557 HashMap processed = new HashMap(); //for all processed annotations 558 559 //first get all tree nodes in this set, then restrict them by offset 560 AnnotationSet tempSet = currentSet.get(treeNodeAnnotationType); 561 if (tempSet == null || tempSet.isEmpty()) 562 return; 563 treeAnnotations = tempSet.get(utterance.getStartNode().getOffset(), 564 utterance.getEndNode().getOffset()); 565 if (treeAnnotations == null || treeAnnotations.isEmpty()) 566 return; 567 568 // sort them from left to right first 569 // Should work as 570 // annotation implements Comparable 571 java.util.List nodeAnnots = new ArrayList(treeAnnotations); 572 Collections.sort(nodeAnnots, new gate.util.OffsetComparator()); 573 574 Vector childrenButtons = new Vector(); 575 String oldParent = ""; 576 577 //find all annotations with no children 578 Iterator i = nodeAnnots.iterator(); 579 while (i.hasNext()) { 580 Annotation annot = (Annotation) i.next(); 581 582 java.util.List children = 583 (java.util.List) annot.getFeatures().get(NODE_CONSISTS_FEATURE_NAME); 584 //check if it's a leaf 585 if (children == null || 586 children.isEmpty()) 587 { 588 589 STreeNode leaf = findLeaf(annot.getStartNode(), annot.getEndNode()); 590 if (leaf == null) {//not found 591 Out.println("Can't find my leaf node for annotation: " + annot); 592 } 593 594 JButton button = (JButton) buttons.get(new Integer(leaf.getID())); 595 selection.clear(); 596 selection.add(button); 597 598 //then create the non-terminal with the category 599 STreeNode node = new STreeNode(annot); 600 node.add(leaf); 601 node.setLevel(1); 602 node.setUserObject(annot.getFeatures().get(NODE_CAT_FEATURE_NAME)); 603 nonTerminals.put(new Integer(node.getID()), node); 604 JButton parentButton = createCentralButton(node); 605 addLines(node); 606 607 //finally add to the processed annotations 608 processed.put(annot.getId(), parentButton); 609 610 } //if 611 612 } //loop through children 613 614 //loop through the rest of the nodes 615 Iterator i1 = nodeAnnots.iterator(); 616 while (i1.hasNext()) { 617 Annotation annotNode = (Annotation) i1.next(); 618 if (processed.containsKey(annotNode.getId())) 619 continue; 620 processChildrenAnnots(annotNode, processed); 621 } //process all higher nodes 622 623 selection.clear(); 624 625 this.scrollRectToVisible(new 626 Rectangle(0, (int) getHeight()- (int) getVisibleRect().getHeight(), 627 (int) getVisibleRect().getWidth(), (int) getVisibleRect().getHeight())); 628 } //annotations2Trees 629 630 private JButton processChildrenAnnots(Annotation annot, HashMap processed) { 631 selection.clear(); 632 Vector childrenButtons = new Vector(); 633 java.util.List children = 634 (java.util.List) annot.getFeatures().get(NODE_CONSISTS_FEATURE_NAME); 635 636 for (Iterator i = children.iterator(); i.hasNext(); ) { 637 Integer childId = (Integer) i.next(); 638 Annotation child = treeAnnotations.get(childId); 639 JButton childButton; 640 641 if (processed.containsKey(child.getId())) 642 childButton = (JButton) processed.get(child.getId()); 643 else 644 childButton = processChildrenAnnots(child, processed); 645 646 childrenButtons.add(childButton); 647 } 648 649 selection = (Vector) childrenButtons.clone(); 650 STreeNode parent = createParentNode( 651 (String) annot.getFeatures().get(NODE_CAT_FEATURE_NAME), 652 annot); 653 nonTerminals.put(new Integer(parent.getID()), parent); 654 JButton parentButton = createCentralButton(parent); 655 addLines(parent); 656 657 processed.put(annot.getId(), parentButton); 658 selection.clear(); 659 return parentButton; 660 }// private JButton processChildrenAnnots 661 662 private STreeNode findLeaf(Node start, Node end) { 663 for (Iterator i = leaves.values().iterator(); i.hasNext(); ) { 664 STreeNode node = (STreeNode) i.next(); 665 if (node.getStart() == start.getOffset().intValue() && 666 node.getEnd() == end.getOffset().intValue() 667 ) 668 return node; 669 } 670 671 return null; 672 }//private STreeNode findLeaf(Node start, Node end) 673 674 675 /** 676 * Converts the given utterances into a set of leaf nodes for annotation 677 */ 678 private void utterances2Trees() { 679 680 if (! utterance.getType().equals(textAnnotationType)) { 681 Out.println("Can't display annotations other than the specified type:" + 682 textAnnotationType); 683 return; 684 } 685 686 // set the utterance offset correctly. 687 // All substring calculations depend on that. 688 utteranceStartOffset = utterance.getStartNode().getOffset(); 689 utteranceEndOffset = utterance.getEndNode().getOffset(); 690 691 try { 692 displayedString = currentSet.getDocument().getContent().getContent( 693 utteranceStartOffset, utteranceEndOffset).toString(); 694 } catch (InvalidOffsetException ioe) { 695 ioe.printStackTrace(Err.getPrintWriter()); 696 } 697 698 AnnotationSet tokensAS = currentSet.get(tokenType, utteranceStartOffset, 699 utteranceEndOffset); 700 if (tokensAS == null || tokensAS.isEmpty()) { 701 Out.println("TreeViewer warning: No annotations of type " + tokenType + 702 "so cannot show or edit the text and the tree annotations."); 703 return; 704 } 705 706 Insets insets = this.getInsets(); 707 // the starting X position for the buttons 708 int buttonX = insets.left; 709 710 // the starting Y position 711 int buttonY = this.getHeight() - 20 - insets.bottom; 712 713 java.util.List tokens = new ArrayList(tokensAS); 714 //if no tokens to match, do nothing 715 if (tokens.isEmpty()) 716 return; 717 Collections.sort(tokens, new gate.util.OffsetComparator()); 718 719 //loop through the tokens 720 for (int i= 0; i< tokens.size(); i++) { 721 Annotation tokenAnnot = (Annotation) tokens.get(i); 722 Long tokenBegin = tokenAnnot.getStartNode().getOffset(); 723 Long tokenEnd = tokenAnnot.getEndNode().getOffset(); 724 725 String tokenText = ""; 726 try { 727 tokenText = document.getContent().getContent( 728 tokenBegin, tokenEnd).toString(); 729 } catch (InvalidOffsetException ioe) { 730 ioe.printStackTrace(Err.getPrintWriter()); 731 } 732 733 // create the leaf node 734 STreeNode node = 735 new STreeNode(tokenBegin.longValue(), tokenEnd.longValue()); 736 737 // make it a leaf 738 node.setAllowsChildren(false); 739 740 // set the text 741 node.setUserObject(tokenText); 742 node.setLevel(0); 743 744 // add to hash table of leaves 745 leaves.put(new Integer(node.getID()), node); 746 747 // create the corresponding button 748 buttonX = createButton4Node(node, buttonX, buttonY); 749 750 } //while 751 752 753 /* 754 //This old piece of code was used to tokenise, instead of relying on 755 // annotations. Can re-instate if someone shows me the need for it. 756 757 long currentOffset = utteranceStartOffset.longValue(); 758 759 StrTokeniser strTok = 760 new StrTokeniser(displayedString, 761 " \r\n\t"); 762 763 Insets insets = this.getInsets(); 764 // the starting X position for the buttons 765 int buttonX = insets.left; 766 767 // the starting Y position 768 int buttonY = this.getHeight() - 20 - insets.bottom; 769 770 while (strTok.hasMoreTokens()) { 771 String word = strTok.nextToken(); 772 // Out.println("To display:" + word); 773 774 // create the leaf node 775 STreeNode node = 776 new STreeNode(currentOffset, currentOffset + word.length()); 777 778 // make it a leaf 779 node.setAllowsChildren(false); 780 781 // set the text 782 node.setUserObject(word); 783 node.setLevel(0); 784 785 // add to hash table of leaves 786 leaves.put(new Integer(node.getID()), node); 787 788 // create the corresponding button 789 buttonX = createButton4Node(node, buttonX, buttonY); 790 791 currentOffset += word.length()+1; //// +1 to include the delimiter too 792 } 793 */ 794 795 this.setSize(buttonX, buttonY + 20 + insets.bottom); 796 // this.resize(buttonX, buttonY + 20 + insets.bottom); 797 this.setPreferredSize(this.getSize()); 798 799 } // utterance2Trees 800 801 /** 802 * Returns the X position where another button can start if necessary. 803 * To be used to layout only the leaf buttons. All others must be created 804 * central to their children using createCentralButton. 805 */ 806 private int createButton4Node(STreeNode node, int buttonX, int buttonY) { 807 808 JButton button = new JButton((String) node.getUserObject()); 809 button.setBorderPainted(false); 810 811 FontMetrics fm = button.getFontMetrics(button.getFont()); 812 813 int buttonWidth, 814 buttonHeight; 815 816 // Out.print 817 // ("Button width " + b1.getWidth() + "Button height " + b1.getHeight()); 818 819 buttonWidth = fm.stringWidth(button.getText()) 820 + button.getMargin().left + button.getMargin().right 821 + extraButtonWidth; 822 buttonHeight = fm.getHeight() + button.getMargin().top + 823 button.getMargin().bottom; 824 buttonY = buttonY - buttonHeight; 825 826 // Out.print("New Button X " + buttonX + 827 // "New Button Y" + buttonY); 828 829 button.setBounds(buttonX, buttonY, buttonWidth, buttonHeight); 830 button.addActionListener(this); 831 button.addMouseListener(this); 832 button.setActionCommand("" + node.getID()); 833 button.setVisible(true); 834 button.setEnabled(true); 835 836 this.add(button); 837 buttons.put(new Integer(node.getID()), button); 838 839 buttonX += buttonWidth + horizButtonGap; 840 return buttonX; 841 842 }// private int createButton4Node(STreeNode node, int buttonX, int buttonY) 843 844 private JButton createCentralButton(STreeNode newNode) { 845 846 FocusButton button = new FocusButton((String) newNode.getUserObject()); 847 button.setBorderPainted(false); 848 849 FontMetrics fm = button.getFontMetrics(button.getFont()); 850 851 int buttonWidth, 852 buttonHeight, 853 buttonX = 0, 854 buttonY =0; 855 856 // Out.print("Button width " + b1.getWidth() + "; 857 // Button height " + b1.getHeight()); 858 859 buttonWidth = fm.stringWidth(button.getText()) 860 + button.getMargin().left + button.getMargin().right 861 + extraButtonWidth; 862 buttonHeight = fm.getHeight() + button.getMargin().top + 863 button.getMargin().bottom; 864 865 int left = this.getWidth(), right =0 , top = this.getHeight(); 866 867 // determine the left, right, top 868 for (Iterator i = selection.iterator(); i.hasNext(); ) { 869 JButton childButton = (JButton) i.next(); 870 871 if (left > childButton.getX()) 872 left = childButton.getX(); 873 if (childButton.getX() + childButton.getWidth() > right) 874 right = childButton.getX() + childButton.getWidth(); 875 if (childButton.getY() < top) 876 top = childButton.getY(); 877 } 878 879 buttonX = (left + right) /2 - buttonWidth/2; 880 buttonY = top - vertButtonGap; 881 // Out.println("Button's Y is" + buttonY); 882 883 // Out.print("New Button width " + buttonWidth + "; 884 // New Button height " + buttonHeight); 885 button.setBounds(buttonX, buttonY, buttonWidth, buttonHeight); 886 button.addActionListener(this); 887 button.addMouseListener(this); 888 // button.registerKeyboardAction(this, 889 // "delete", 890 // KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), 891 // WHEN_FOCUSED); 892 893 button.setActionCommand("" + newNode.getID()); 894 895 this.add(button); 896 // add to hashmap of buttons 897 buttons.put(new Integer(newNode.getID()), button); 898 899 // check if we need to resize the panel 900 if (buttonY < 0) { 901 this.setSize(this.getWidth(), this.getHeight() + 5* (- buttonY)); 902 this.setPreferredSize(this.getSize()); 903 shiftButtonsDown(5* (-buttonY)); 904 } 905 906 return button; 907 }// private JButton createCentralButton(STreeNode newNode) 908 909 private void shiftButtonsDown(int offset) { 910 for (Iterator i = buttons.values().iterator(); i.hasNext(); ) { 911 JButton button = (JButton) i.next(); 912 button.setBounds( button.getX(), 913 button.getY() + offset, 914 button.getWidth(), 915 button.getHeight()); 916 } // for loop through buttons 917 918 for (Iterator k = lines.iterator(); k.hasNext(); ) { 919 Coordinates coords = (Coordinates) k.next(); 920 coords.setY1(coords.getY1() + offset); 921 coords.setY2(coords.getY2() + offset); 922 } 923 }// private void shiftButtonsDown(int offset) 924 925 public void actionPerformed(ActionEvent e) { 926 927 //check for the popup menu items 928 if (e.getSource() instanceof JMenuItem) { 929 JMenuItem menuItem = (JMenuItem) e.getSource(); 930 931 // check if we're annotating a leaf 932 // the popup label is set to leaves when the popup has been 933 // constructed in showRightClickPopup 934 if (popup.getLabel().equals("leaves")) { 935 Integer id = new Integer(e.getActionCommand()); 936 937 // clearSelection(); 938 JButton button = (JButton) buttons.get(id); 939 selection.add(button); 940 941 STreeNode leaf = (STreeNode) leaves.get(id); 942 943 // create parent with the same span as leaf 944 // using createParentNode here is not a good idea coz it works only 945 // for creating parents of non-terminal nodes, not leaves 946 STreeNode parent = new STreeNode(leaf.getStart(), leaf.getEnd()); 947 parent.setLevel(leaf.getLevel()+1); //levels increase from bottom to top 948 parent.add(leaf); 949 950 // set the text 951 parent.setUserObject(menuItem.getText()); 952 953 // last create the annotation; should always come last! 954 parent.createAnnotation( document, 955 treeNodeAnnotationType, 956 displayedString, 957 utteranceStartOffset.longValue()); 958 nonTerminals.put(new Integer(parent.getID()), parent); 959 960 // create new button positioned centrally above the leaf 961 createCentralButton(parent); 962 963 // add the necessary lines for drawing 964 addLines(parent); 965 966 clearSelection(); 967 968 // repaint the picture! 969 this.repaint(); 970 } // finished processing leaves 971 else if (popup.getLabel().equals("non-terminal")) { 972 // the action command is set to the id under which 973 // the button can be found 974 Integer id = new Integer(e.getActionCommand()); 975 976 //locate button from buttons hashMap and add to selection 977 JButton button = (JButton) buttons.get(id); 978 selection.add(button); 979 980 //create the new parent 981 STreeNode parent = createParentNode(menuItem.getText()); 982 983 //add to nonTerminals HashMap 984 nonTerminals.put(new Integer(parent.getID()), parent); 985 986 //create new button positioned centrally above the leaf 987 createCentralButton(parent); 988 989 //add the necessary lines for drawing 990 addLines(parent); 991 992 clearSelection(); 993 994 //repaint the picture! 995 this.repaint(); 996 997 } //check for non-terminals 998 999 } //if statement for MenuItems 1000 1001 1002 }// public void actionPerformed(ActionEvent e) 1003 1004 public void mouseClicked(MouseEvent e) { 1005 1006 if (! (e.getSource() instanceof JButton)) 1007 return; 1008 1009 JButton source = (JButton) e.getSource(); 1010 1011 //check if CTRL or Shift is pressed and if not, clear the selection 1012 if ((! (e.isControlDown() || e.isShiftDown())) 1013 && SwingUtilities.isLeftMouseButton(e)) 1014 clearSelection(); 1015 1016 //and select the current node 1017 if (SwingUtilities.isLeftMouseButton(e)) 1018 //if (e.getModifiers() == e.BUTTON1_MASK) 1019 selectNode(e); 1020 1021 1022 //only repspond to right-clicks here by displaying the popup 1023 if (SwingUtilities.isRightMouseButton(e)) { 1024 //if button not in focus, grad the focus and select it! 1025 if ( source.getBackground() != selectedNodeColor ) { 1026 source.grabFocus(); 1027 source.doClick(); 1028 selectNode(e); 1029 } 1030 //Out.println(e.getComponent().getClass() + " right-clicked!"); 1031 showRightClickPopup(e); 1032 } //end of right-click processing 1033 1034 }// public void mouseClicked(MouseEvent e) 1035 1036 public void mousePressed(MouseEvent e) { 1037 } 1038 1039 public void mouseReleased(MouseEvent e) { 1040 } 1041 1042 public void mouseEntered(MouseEvent e) { 1043 } 1044 1045 public void mouseExited(MouseEvent e) { 1046 } // createButton4Node 1047 1048 1049 private void showRightClickPopup(MouseEvent e) { 1050 1051 //that'll always work coz we checked it in MouseClicked. 1052 JButton source = (JButton) e.getSource(); 1053 Integer id = new Integer(source.getActionCommand()); 1054 1055 //check if it's a leaf and if so, offer the leaf annotation dialog 1056 Object obj = leaves.get(id); 1057 if (obj != null) { 1058 STreeNode leaf = (STreeNode) obj; 1059 //do nothing if it already has a parent 1060 if (leaf.getParent() != null) { 1061 clearSelection(); 1062 JOptionPane.showMessageDialog( 1063 this, 1064 "Node already annotated. To delete the existing annotation, " + 1065 "select it and press <DEL>.", 1066 "Syntax Tree Viewer message", 1067 JOptionPane.INFORMATION_MESSAGE); 1068 return; 1069 } 1070 1071 //reset the popup and set it's heading accordingly 1072 popup.setLabel("leaves"); 1073 setMenuCommands(popup, ""+id); 1074 1075 popup.pack(); 1076 popup.show(source, e.getX(), e.getY()); 1077 } else { //we have a non-terminal node 1078 1079 //check if it has been annotated already 1080 if ( ((STreeNode) nonTerminals.get(id)).getParent() != null) { 1081 clearSelection(); 1082 JOptionPane.showMessageDialog(this, "Node already annotated. To delete"+ 1083 " the existing annotation, select it and press <DEL>.", 1084 "Syntax Tree Viewer message", 1085 JOptionPane.INFORMATION_MESSAGE); 1086 return; //and do nothing if so! 1087 } 1088 1089 popup.setLabel("non-terminal"); 1090 setMenuCommands(popup, ""+id); 1091 1092 popup.pack(); 1093 popup.show(source, e.getX(), e.getY()); 1094 1095 } 1096 1097 } //showRightClickPopup 1098 1099 private void addLines(STreeNode newNode) { 1100 1101 JButton newButton = (JButton) buttons.get(new Integer(newNode.getID())); 1102 int nbX = newButton.getX() + newButton.getWidth()/2; 1103 int nbY = newButton.getY() + newButton.getHeight(); 1104 1105 for (Iterator i = selection.iterator(); i.hasNext(); ) { 1106 JButton selButton = (JButton) i.next(); 1107 1108 //I create it a rect but it will in fact be used as x1, y1, x2, y2 for the 1109 //draw line. see drawLines. 1110 Coordinates coords = new Coordinates( 1111 nbX, 1112 nbY, 1113 selButton.getX() + selButton.getWidth()/2, 1114 selButton.getY()); 1115 1116 lines.add(coords); 1117 } 1118 1119 } // addLines 1120 1121 private void clearSelection() { 1122 for (Enumeration enum = selection.elements(); enum.hasMoreElements(); ) { 1123 JButton selButton = (JButton) enum.nextElement(); 1124 selButton.setBackground(buttonBackground); 1125 } 1126 1127 selection.clear(); 1128 1129 } //clearSlection 1130 1131 1132 private void fillCategoriesMenu() { 1133 boolean found = false; 1134 1135 //fetch the valid categories from the stereotype 1136 CreoleRegister creoleReg = Gate.getCreoleRegister(); 1137 java.util.List currentAnnotationSchemaList = 1138 creoleReg.getLrInstances("gate.creole.AnnotationSchema"); 1139 if (currentAnnotationSchemaList.isEmpty()) return; 1140 1141 Iterator iter = currentAnnotationSchemaList.iterator(); 1142 while (iter.hasNext()){ 1143 AnnotationSchema annotSchema = (AnnotationSchema) iter.next(); 1144 //we have found the right schema 1145 if (treeNodeAnnotationType.equals(annotSchema.getAnnotationName())) { 1146 found = true; 1147 FeatureSchema categories = annotSchema.getFeatureSchema(NODE_CAT_FEATURE_NAME); 1148 //iterate through all categories 1149 for (Iterator i = 1150 categories.getPermissibleValues().iterator(); i.hasNext(); ) { 1151 1152 JMenuItem menuItem = new JMenuItem( (String) i.next() ); 1153 menuItem.addActionListener(this); 1154 popup.add(menuItem); 1155 } //for 1156 1157 } //if 1158 }// while 1159 1160 //if we don't have a schema, issue a warning 1161 if (! found) 1162 Out.println("Warning: You need to define an annotation schema for " + 1163 treeNodeAnnotationType + 1164 " in order to be able to add such annotations."); 1165 1166 } // fillCategoriesMenu 1167 1168 /** 1169 * Sets the action commands of all menu items to the specified command 1170 */ 1171 private void setMenuCommands(JPopupMenu menu, String command) { 1172 for (int i = 0; i < menu.getComponentCount() ; i++) { 1173 JMenuItem item = (JMenuItem) menu.getComponent(i); 1174 item.setActionCommand(command); 1175 } 1176 1177 } // setMenuCommands 1178 1179 /** 1180 * Create a parent node for all selected non-terminal nodes 1181 */ 1182 protected STreeNode createParentNode(String text) { 1183 STreeNode parentNode = new STreeNode(); 1184 1185 long begin = 2147483647, end = 0, level= -1; 1186 for (Iterator i = selection.iterator(); i.hasNext(); ) { 1187 JButton button = (JButton) i.next(); 1188 Integer id = new Integer(button.getActionCommand()); 1189 1190 STreeNode child = (STreeNode) nonTerminals.get(id); 1191 1192 if (begin > child.getStart()) 1193 begin = child.getStart(); 1194 if (end < child.getEnd()) 1195 end = child.getEnd(); 1196 if (level < child.getLevel()) 1197 level = child.getLevel(); 1198 1199 parentNode.add(child); 1200 1201 } //for 1202 1203 parentNode.setLevel(level+1); 1204 parentNode.setStart(begin); 1205 parentNode.setEnd(end); 1206 parentNode.setUserObject(text); 1207 parentNode.createAnnotation(document, 1208 treeNodeAnnotationType, 1209 displayedString, 1210 utteranceStartOffset.longValue()); 1211 1212 1213 return parentNode; 1214 } 1215 1216 /** 1217 * Create a parent node for all selected non-terminal nodes 1218 */ 1219 protected STreeNode createParentNode(String text, Annotation annot) { 1220 STreeNode parentNode = new STreeNode(annot); 1221 1222 long level = -1; 1223 for (Iterator i = selection.iterator(); i.hasNext(); ) { 1224 JButton button = (JButton) i.next(); 1225 Integer id = new Integer(button.getActionCommand()); 1226 1227 STreeNode child = (STreeNode) nonTerminals.get(id); 1228 1229 if (level < child.getLevel()) 1230 level = child.getLevel(); 1231 1232 parentNode.add(child); 1233 } //for 1234 1235 parentNode.setLevel(level+1); 1236 parentNode.setUserObject(text); 1237 1238 return parentNode; 1239 } 1240 1241 1242 void selectNode(MouseEvent e) { 1243 // try finding the node that's annotated, i.e., the selected button 1244 if (e.getSource() instanceof JButton) { 1245 JButton source = (JButton) e.getSource(); 1246 1247 selection.add(source); 1248 buttonBackground = source.getBackground(); 1249 source.setBackground(selectedNodeColor); 1250 } 1251 } 1252 1253 // remove that node from the syntax tree 1254 void removeNode(JButton button) { 1255 1256 Integer id = new Integer(button.getActionCommand()); 1257 STreeNode node = (STreeNode) nonTerminals.get(id); 1258 nonTerminals.remove(node); 1259 node.removeAnnotation(document); 1260 1261 //fix the STreeNodes involved 1262 resetChildren(node); 1263 removeNodesAbove(node); 1264 1265 //remove button from everywhere 1266 buttons.remove(button); 1267 button.setVisible(false); 1268 this.remove(button); 1269 1270 //recalculate all lines 1271 recalculateLines(); 1272 1273 //make sure we clear the selection 1274 selection.clear(); 1275 repaint(); 1276 } 1277 1278 //set parent node to null for all children of the given node 1279 private void resetChildren(STreeNode node) { 1280 for (Enumeration e = node.children(); e.hasMoreElements(); ) 1281 ((STreeNode) e.nextElement()).setParent(null); 1282 1283 node.disconnectChildren(); 1284 } 1285 1286 private void removeNodesAbove(STreeNode node) { 1287 STreeNode parent = (STreeNode) node.getParent(); 1288 1289 while (parent != null) { 1290 Integer id = new Integer(parent.getID()); 1291 parent.removeAnnotation(document); 1292 if (parent.isNodeChild(node)) 1293 parent.remove(node); 1294 parent.disconnectChildren(); 1295 1296 nonTerminals.remove(id); 1297 1298 JButton button = (JButton) buttons.get(id); 1299 this.remove(button); 1300 buttons.remove(id); 1301 1302 parent = (STreeNode) parent.getParent(); 1303 } 1304 } 1305 1306 private void recalculateLines() { 1307 lines.clear(); 1308 //go through all non-terminals and recalculate their lines to their children 1309 for (Iterator i = nonTerminals.values().iterator(); i.hasNext(); ) 1310 recalculateLines((STreeNode) i.next()); 1311 1312 } 1313 1314 /** 1315 * recalculates all lines from that node to all its children 1316 */ 1317 private void recalculateLines(STreeNode node) { 1318 Integer id = new Integer(node.getID()); 1319 JButton button = (JButton) buttons.get(id); 1320 1321 int bX = button.getX() + button.getWidth()/2; 1322 int bY = button.getY() + button.getHeight(); 1323 1324 for (Enumeration e = node.children(); e.hasMoreElements(); ) { 1325 STreeNode subNode = (STreeNode) e.nextElement(); 1326 Integer sid = new Integer(subNode.getID()); 1327 JButton subButton = (JButton) buttons.get(sid); 1328 1329 Coordinates coords = new Coordinates( 1330 bX, 1331 bY, 1332 subButton.getX() + subButton.getWidth()/2, 1333 subButton.getY()); 1334 1335 lines.add(coords); 1336 } 1337 1338 } 1339 1340/* 1341 // discontinued from use,done automatically instead, when the utterance is set 1342 1343 public void setTreeAnnotations(AnnotationSet newTreeAnnotations) { 1344 AnnotationSet oldTreeAnnotations = treeAnnotations; 1345 treeAnnotations = newTreeAnnotations; 1346 firePropertyChange("treeAnnotations", oldTreeAnnotations, 1347 newTreeAnnotations); 1348 } 1349*/ 1350 1351 public void setTreeNodeAnnotationType(String newTreeNodeAnnotationType) { 1352 treeNodeAnnotationType = newTreeNodeAnnotationType; 1353 } 1354 1355 public String getTreeNodeAnnotationType() { 1356 return treeNodeAnnotationType; 1357 } 1358 1359 public void setTokenType(String newTokenType) { 1360 if (newTokenType != null && ! newTokenType.equals("")) 1361 tokenType = newTokenType; 1362 } 1363 1364 public String getTokenType() { 1365 return tokenType; 1366 } 1367 1368 void this_componentShown(ComponentEvent e) { 1369 Out.println("Tree Viewer shown"); 1370 } 1371 1372 void this_componentHidden(ComponentEvent e) { 1373 Out.println("Tree Viewer closes"); 1374 } 1375 1376/* 1377 //None of this works, damn!!! 1378 1379 public void setVisible(boolean b) { 1380 if (!b && this.isVisible()) 1381 Out.println("Tree Viewer closes"); 1382 1383 super.setVisible( b); 1384 } 1385 public void hide() { 1386 Out.println("Tree Viewer closes"); 1387 super.hide(); 1388 } 1389*/ 1390 1391 1392}// class SyntaxTreeViewer 1393 1394 1395class FocusButton extends JButton { 1396 1397 public FocusButton(String text) { 1398 super(text); 1399 } 1400 1401 public FocusButton() { 1402 super(); 1403 } 1404 1405 public FocusButton(Icon icon) { 1406 super(icon); 1407 } 1408 1409 public FocusButton(String text, Icon icon) { 1410 super(text, icon); 1411 }// public FocusButton 1412 1413 public boolean isManagingFocus() { 1414 return true; 1415 }// public boolean isManagingFocus() 1416 1417 public void processComponentKeyEvent(KeyEvent e) { 1418 super.processComponentKeyEvent(e); 1419 1420 //I need that cause I get all events here, so I only want to process 1421 //when it's a release event. The reason is that for keys like <DEL> 1422 //key_typed never happens 1423 if (e.getID() != KeyEvent.KEY_RELEASED) 1424 return; 1425 1426 if (e.getKeyCode() == KeyEvent.VK_DELETE) { 1427 SyntaxTreeViewer viewer = (SyntaxTreeViewer) ((JButton) e.getSource()).getParent(); 1428 viewer.removeNode((JButton) e.getSource()); 1429 } 1430 }// public void processComponentKeyEvent(KeyEvent e) 1431 1432} // class SyntaxTreeViewer 1433 1434// $Log: SyntaxTreeViewer.java,v $ 1435// Revision 1.22 2003/01/28 10:01:16 marin 1436// [marin] bugfixes from Kali 1437// 1438// Revision 1.21 2002/03/06 17:15:46 kalina 1439// Reorganised the source code, so that it now uses constants from 1440// ANNIEConstants, GateConstants and parameter constants defined on each PR. 1441// Read e-mail to the gate list for an explanation. 1442// 1443// Revision 1.20 2001/08/08 16:14:26 kalina 1444// A minor change to the tree viewer. 1445// 1446// Revision 1.19 2001/08/08 14:39:00 kalina 1447// Made the dialog to size itself maximum as much as the screen, coz was 1448// getting too big without that. 1449// 1450// Some documentation on Tree Viewer and some small changes to utterance2trees() 1451// to make it order the tokens correctly by offset 1452// 1453// Revision 1.18 2001/08/07 19:03:05 kalina 1454// Made the tree viewer use Token annotations to break the sentence for annotation 1455// 1456// Revision 1.17 2001/08/07 17:01:32 kalina 1457// Changed the AVR implementing classes in line with the updated AVR 1458// API (cancelAction() and setSpan new parameter). 1459// 1460// Also updated the TreeViewer, so now it can be used to edit and view 1461// Sentence annotations and the SyntaxTreeNodes associated with them. 1462// So if you have trees, it'll show them, if not, it'll help you build them. 1463// 1464// Revision 1.16 2001/04/09 10:36:36 oana 1465// a few changes in the code style 1466// 1467// Revision 1.14 2000/12/04 12:29:29 valyt 1468// Done some work on the visual resources 1469// Added the smart XJTable 1470// 1471// Revision 1.13 2000/11/08 16:35:00 hamish 1472// formatting 1473// 1474// Revision 1.12 2000/10/26 10:45:26 oana 1475// Modified in the code style 1476// 1477// Revision 1.11 2000/10/24 10:10:18 valyt 1478// Fixed the deprecation warning in gate/gui/SyntaxTreeViewer.java 1479// 1480// Revision 1.10 2000/10/18 13:26:47 hamish 1481// Factory.createResource now working, with a utility method that uses reflection (via java.beans.Introspector) to set properties on a resource from the 1482// parameter list fed to createResource. 1483// resources may now have both an interface and a class; they are indexed by interface type; the class is used to instantiate them 1484// moved createResource from CR to Factory 1485// removed Transients; use Factory instead 1486// 1487// Revision 1.9 2000/10/16 16:44:32 oana 1488// Changed the comment of DEBUG variable 1489// 1490// Revision 1.8 2000/10/10 15:36:35 oana 1491// Changed System.out in Out and System.err in Err; 1492// Added the DEBUG variable seted on false; 1493// Added in the header the licence; 1494// 1495// Revision 1.7 2000/10/10 09:49:57 valyt 1496// Fixed the Annotation test 1497// 1498// Revision 1.6 2000/10/02 12:34:06 valyt 1499// Added the UnicodeEnabled switch on gate.util.Tools 1500// 1501// Revision 1.5 2000/09/28 14:26:09 kalina 1502// Added even more documentation (is this me?!) and allowed several tokens to be 1503// passed instead of a whole utterance/sentence for annotation. Needs good testing this 1504// but will do it when somebody tries using this functionality. 1505// 1506// Revision 1.4 2000/09/28 13:16:12 kalina 1507// Added some documentation 1508// 1509// Revision 1.3 2000/09/21 14:23:45 kalina 1510// Fixed some small bug in main(). To test just run the component itself. 1511// 1512// Revision 1.2 2000/09/21 14:17:27 kalina 1513// Added Unicode support 1514// 1515// Revision 1.1 2000/09/20 17:03:37 kalina 1516// Added the tree viewer from the prototype. It works now with the new annotation API. 1517
|
SyntaxTreeViewer |
|