|
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.21 2002/03/06 17:15:46 kalina 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 LinkedList nodeAnnots = new LinkedList(treeAnnotations); 572 Collections.sort(nodeAnnots); 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 allTokens = currentSet.get(utteranceStartOffset, 699 utteranceEndOffset); 700 if (allTokens == null || allTokens.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 AnnotationSet tokens = allTokens.get(tokenType); 707 708 //if no tokens return 709 //needs improving maybe, just show one solid utterance 710 if (tokens == null || tokens.isEmpty()){ 711 Out.println("TreeViewer warning: No annotations of type " + tokenType + 712 "so cannot show or edit the text and the tree annotations."); 713 return; 714 } 715 716 Insets insets = this.getInsets(); 717 // the starting X position for the buttons 718 int buttonX = insets.left; 719 720 // the starting Y position 721 int buttonY = this.getHeight() - 20 - insets.bottom; 722 723 //We need to go through the nodes this way and get the f***ing tokens 724 //coz there is no way to sort them by startOffset. The compareTo method 725 //only uses the Ids, highly useful! 726 Node startNode = tokens.firstNode(); 727 Node endNode = tokens.nextNode(startNode); 728 729 //loop through the tokens 730 while (startNode != null && endNode != null) { 731 AnnotationSet nextTokenSet = tokens.get(startNode.getOffset()); 732 733 if (nextTokenSet == null || nextTokenSet.isEmpty()) 734 break; 735 736 Annotation tokenAnnot = (Annotation) nextTokenSet.iterator().next(); 737 Long tokenBegin = tokenAnnot.getStartNode().getOffset(); 738 Long tokenEnd = tokenAnnot.getEndNode().getOffset(); 739 740 String tokenText = ""; 741 try { 742 tokenText = document.getContent().getContent( 743 tokenBegin, tokenEnd).toString(); 744 } catch (InvalidOffsetException ioe) { 745 ioe.printStackTrace(Err.getPrintWriter()); 746 } 747 748 // create the leaf node 749 STreeNode node = 750 new STreeNode(tokenBegin.longValue(), tokenEnd.longValue()); 751 752 // make it a leaf 753 node.setAllowsChildren(false); 754 755 // set the text 756 node.setUserObject(tokenText); 757 node.setLevel(0); 758 759 // add to hash table of leaves 760 leaves.put(new Integer(node.getID()), node); 761 762 // create the corresponding button 763 buttonX = createButton4Node(node, buttonX, buttonY); 764 765 //advance to the next node 766 startNode = tokenAnnot.getEndNode(); 767 endNode = tokens.nextNode(startNode); 768 } //while 769 770 771 /* 772 //This old piece of code was used to tokenise, instead of relying on 773 // annotations. Can re-instate if someone shows me the need for it. 774 775 long currentOffset = utteranceStartOffset.longValue(); 776 777 StrTokeniser strTok = 778 new StrTokeniser(displayedString, 779 " \r\n\t"); 780 781 Insets insets = this.getInsets(); 782 // the starting X position for the buttons 783 int buttonX = insets.left; 784 785 // the starting Y position 786 int buttonY = this.getHeight() - 20 - insets.bottom; 787 788 while (strTok.hasMoreTokens()) { 789 String word = strTok.nextToken(); 790 // Out.println("To display:" + word); 791 792 // create the leaf node 793 STreeNode node = 794 new STreeNode(currentOffset, currentOffset + word.length()); 795 796 // make it a leaf 797 node.setAllowsChildren(false); 798 799 // set the text 800 node.setUserObject(word); 801 node.setLevel(0); 802 803 // add to hash table of leaves 804 leaves.put(new Integer(node.getID()), node); 805 806 // create the corresponding button 807 buttonX = createButton4Node(node, buttonX, buttonY); 808 809 currentOffset += word.length()+1; //// +1 to include the delimiter too 810 } 811 */ 812 813 this.setSize(buttonX, buttonY + 20 + insets.bottom); 814 // this.resize(buttonX, buttonY + 20 + insets.bottom); 815 this.setPreferredSize(this.getSize()); 816 817 } // utterance2Trees 818 819 /** 820 * Returns the X position where another button can start if necessary. 821 * To be used to layout only the leaf buttons. All others must be created 822 * central to their children using createCentralButton. 823 */ 824 private int createButton4Node(STreeNode node, int buttonX, int buttonY) { 825 826 JButton button = new JButton((String) node.getUserObject()); 827 button.setBorderPainted(false); 828 829 FontMetrics fm = button.getFontMetrics(button.getFont()); 830 831 int buttonWidth, 832 buttonHeight; 833 834 // Out.print 835 // ("Button width " + b1.getWidth() + "Button height " + b1.getHeight()); 836 837 buttonWidth = fm.stringWidth(button.getText()) 838 + button.getMargin().left + button.getMargin().right 839 + extraButtonWidth; 840 buttonHeight = fm.getHeight() + button.getMargin().top + 841 button.getMargin().bottom; 842 buttonY = buttonY - buttonHeight; 843 844 // Out.print("New Button X " + buttonX + 845 // "New Button Y" + buttonY); 846 847 button.setBounds(buttonX, buttonY, buttonWidth, buttonHeight); 848 button.addActionListener(this); 849 button.addMouseListener(this); 850 button.setActionCommand("" + node.getID()); 851 button.setVisible(true); 852 button.enable(); 853 854 this.add(button); 855 buttons.put(new Integer(node.getID()), button); 856 857 buttonX += buttonWidth + horizButtonGap; 858 return buttonX; 859 860 }// private int createButton4Node(STreeNode node, int buttonX, int buttonY) 861 862 private JButton createCentralButton(STreeNode newNode) { 863 864 FocusButton button = new FocusButton((String) newNode.getUserObject()); 865 button.setBorderPainted(false); 866 867 FontMetrics fm = button.getFontMetrics(button.getFont()); 868 869 int buttonWidth, 870 buttonHeight, 871 buttonX = 0, 872 buttonY =0; 873 874 // Out.print("Button width " + b1.getWidth() + "; 875 // Button height " + b1.getHeight()); 876 877 buttonWidth = fm.stringWidth(button.getText()) 878 + button.getMargin().left + button.getMargin().right 879 + extraButtonWidth; 880 buttonHeight = fm.getHeight() + button.getMargin().top + 881 button.getMargin().bottom; 882 883 int left = this.getWidth(), right =0 , top = this.getHeight(); 884 885 // determine the left, right, top 886 for (Iterator i = selection.iterator(); i.hasNext(); ) { 887 JButton childButton = (JButton) i.next(); 888 889 if (left > childButton.getX()) 890 left = childButton.getX(); 891 if (childButton.getX() + childButton.getWidth() > right) 892 right = childButton.getX() + childButton.getWidth(); 893 if (childButton.getY() < top) 894 top = childButton.getY(); 895 } 896 897 buttonX = (left + right) /2 - buttonWidth/2; 898 buttonY = top - vertButtonGap; 899 // Out.println("Button's Y is" + buttonY); 900 901 // Out.print("New Button width " + buttonWidth + "; 902 // New Button height " + buttonHeight); 903 button.setBounds(buttonX, buttonY, buttonWidth, buttonHeight); 904 button.addActionListener(this); 905 button.addMouseListener(this); 906 // button.registerKeyboardAction(this, 907 // "delete", 908 // KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), 909 // WHEN_FOCUSED); 910 911 button.setActionCommand("" + newNode.getID()); 912 913 this.add(button); 914 // add to hashmap of buttons 915 buttons.put(new Integer(newNode.getID()), button); 916 917 // check if we need to resize the panel 918 if (buttonY < 0) { 919 this.setSize(this.getWidth(), this.getHeight() + 5* (- buttonY)); 920 this.setPreferredSize(this.getSize()); 921 shiftButtonsDown(5* (-buttonY)); 922 } 923 924 return button; 925 }// private JButton createCentralButton(STreeNode newNode) 926 927 private void shiftButtonsDown(int offset) { 928 for (Iterator i = buttons.values().iterator(); i.hasNext(); ) { 929 JButton button = (JButton) i.next(); 930 button.setBounds( button.getX(), 931 button.getY() + offset, 932 button.getWidth(), 933 button.getHeight()); 934 } // for loop through buttons 935 936 for (Iterator k = lines.iterator(); k.hasNext(); ) { 937 Coordinates coords = (Coordinates) k.next(); 938 coords.setY1(coords.getY1() + offset); 939 coords.setY2(coords.getY2() + offset); 940 } 941 }// private void shiftButtonsDown(int offset) 942 943 public void actionPerformed(ActionEvent e) { 944 945 //check for the popup menu items 946 if (e.getSource() instanceof JMenuItem) { 947 JMenuItem menuItem = (JMenuItem) e.getSource(); 948 949 // check if we're annotating a leaf 950 // the popup label is set to leaves when the popup has been 951 // constructed in showRightClickPopup 952 if (popup.getLabel().equals("leaves")) { 953 Integer id = new Integer(e.getActionCommand()); 954 955 clearSelection(); 956 JButton button = (JButton) buttons.get(id); 957 selection.add(button); 958 959 STreeNode leaf = (STreeNode) leaves.get(id); 960 961 // create parent with the same span as leaf 962 // using createParentNode here is not a good idea coz it works only 963 // for creating parents of non-terminal nodes, not leaves 964 STreeNode parent = new STreeNode(leaf.getStart(), leaf.getEnd()); 965 parent.setLevel(leaf.getLevel()+1); //levels increase from bottom to top 966 parent.add(leaf); 967 968 // set the text 969 parent.setUserObject(menuItem.getText()); 970 971 // last create the annotation; should always come last! 972 parent.createAnnotation( document, 973 treeNodeAnnotationType, 974 displayedString, 975 utteranceStartOffset.longValue()); 976 nonTerminals.put(new Integer(parent.getID()), parent); 977 978 // create new button positioned centrally above the leaf 979 createCentralButton(parent); 980 981 // add the necessary lines for drawing 982 addLines(parent); 983 984 selection.clear(); 985 986 // repaint the picture! 987 this.repaint(); 988 } // finished processing leaves 989 else if (popup.getLabel().equals("non-terminal")) { 990 // the action command is set to the id under which 991 // the button can be found 992 Integer id = new Integer(e.getActionCommand()); 993 994 //locate button from buttons hashMap and add to selection 995 JButton button = (JButton) buttons.get(id); 996 selection.add(button); 997 998 //create the new parent 999 STreeNode parent = createParentNode(menuItem.getText()); 1000 1001 //add to nonTerminals HashMap 1002 nonTerminals.put(new Integer(parent.getID()), parent); 1003 1004 //create new button positioned centrally above the leaf 1005 createCentralButton(parent); 1006 1007 //add the necessary lines for drawing 1008 addLines(parent); 1009 1010 clearSelection(); 1011 1012 //repaint the picture! 1013 this.repaint(); 1014 1015 } //check for non-terminals 1016 1017 } //if statement for MenuItems 1018 1019 1020 }// public void actionPerformed(ActionEvent e) 1021 1022 public void mouseClicked(MouseEvent e) { 1023 1024 if (! (e.getSource() instanceof JButton)) 1025 return; 1026 1027 JButton source = (JButton) e.getSource(); 1028 1029 //check if CTRL or Shift is pressed and if not, clear the selection 1030 if ((! (e.isControlDown() || e.isShiftDown())) 1031 && SwingUtilities.isLeftMouseButton(e)) 1032 clearSelection(); 1033 1034 //and select the current node 1035 if (SwingUtilities.isLeftMouseButton(e)) 1036 //if (e.getModifiers() == e.BUTTON1_MASK) 1037 selectNode(e); 1038 1039 1040 //only repspond to right-clicks here by displaying the popup 1041 if (SwingUtilities.isRightMouseButton(e)) { 1042 //if button not in focus, grad the focus and select it! 1043 if ( source.getBackground() != selectedNodeColor ) { 1044 source.grabFocus(); 1045 source.doClick(); 1046 selectNode(e); 1047 } 1048 //Out.println(e.getComponent().getClass() + " right-clicked!"); 1049 showRightClickPopup(e); 1050 } //end of right-click processing 1051 1052 }// public void mouseClicked(MouseEvent e) 1053 1054 public void mousePressed(MouseEvent e) { 1055 } 1056 1057 public void mouseReleased(MouseEvent e) { 1058 } 1059 1060 public void mouseEntered(MouseEvent e) { 1061 } 1062 1063 public void mouseExited(MouseEvent e) { 1064 } // createButton4Node 1065 1066 1067 private void showRightClickPopup(MouseEvent e) { 1068 1069 //that'll always work coz we checked it in MouseClicked. 1070 JButton source = (JButton) e.getSource(); 1071 Integer id = new Integer(source.getActionCommand()); 1072 1073 //check if it's a leaf and if so, offer the leaf annotation dialog 1074 Object obj = leaves.get(id); 1075 if (obj != null) { 1076 STreeNode leaf = (STreeNode) obj; 1077 //do nothing if it already has a parent 1078 if (leaf.getParent() != null) { 1079 clearSelection(); 1080 JOptionPane.showMessageDialog( 1081 this, 1082 "Node already annotated. To delete the existing annotation, " + 1083 "select it and press <DEL>.", 1084 "Syntax Tree Viewer message", 1085 JOptionPane.INFORMATION_MESSAGE); 1086 return; 1087 } 1088 1089 //reset the popup and set it's heading accordingly 1090 popup.setLabel("leaves"); 1091 setMenuCommands(popup, ""+id); 1092 1093 popup.pack(); 1094 popup.show(source, e.getX(), e.getY()); 1095 } else { //we have a non-terminal node 1096 1097 //check if it has been annotated already 1098 if ( ((STreeNode) nonTerminals.get(id)).getParent() != null) { 1099 clearSelection(); 1100 JOptionPane.showMessageDialog(this, "Node already annotated. To delete"+ 1101 " the existing annotation, select it and press <DEL>.", 1102 "Syntax Tree Viewer message", 1103 JOptionPane.INFORMATION_MESSAGE); 1104 return; //and do nothing if so! 1105 } 1106 1107 popup.setLabel("non-terminal"); 1108 setMenuCommands(popup, ""+id); 1109 1110 popup.pack(); 1111 popup.show(source, e.getX(), e.getY()); 1112 1113 } 1114 1115 } //showRightClickPopup 1116 1117 private void addLines(STreeNode newNode) { 1118 1119 JButton newButton = (JButton) buttons.get(new Integer(newNode.getID())); 1120 int nbX = newButton.getX() + newButton.getWidth()/2; 1121 int nbY = newButton.getY() + newButton.getHeight(); 1122 1123 for (Iterator i = selection.iterator(); i.hasNext(); ) { 1124 JButton selButton = (JButton) i.next(); 1125 1126 //I create it a rect but it will in fact be used as x1, y1, x2, y2 for the 1127 //draw line. see drawLines. 1128 Coordinates coords = new Coordinates( 1129 nbX, 1130 nbY, 1131 selButton.getX() + selButton.getWidth()/2, 1132 selButton.getY()); 1133 1134 lines.add(coords); 1135 } 1136 1137 } // addLines 1138 1139 private void clearSelection() { 1140 for (Enumeration enum = selection.elements(); enum.hasMoreElements(); ) { 1141 JButton selButton = (JButton) enum.nextElement(); 1142 selButton.setBackground(buttonBackground); 1143 } 1144 1145 selection.clear(); 1146 1147 } //clearSlection 1148 1149 1150 private void fillCategoriesMenu() { 1151 boolean found = false; 1152 1153 //fetch the valid categories from the stereotype 1154 CreoleRegister creoleReg = Gate.getCreoleRegister(); 1155 java.util.List currentAnnotationSchemaList = 1156 creoleReg.getLrInstances("gate.creole.AnnotationSchema"); 1157 if (currentAnnotationSchemaList.isEmpty()) return; 1158 1159 Iterator iter = currentAnnotationSchemaList.iterator(); 1160 while (iter.hasNext()){ 1161 AnnotationSchema annotSchema = (AnnotationSchema) iter.next(); 1162 //we have found the right schema 1163 if (treeNodeAnnotationType.equals(annotSchema.getAnnotationName())) { 1164 found = true; 1165 FeatureSchema categories = annotSchema.getFeatureSchema(NODE_CAT_FEATURE_NAME); 1166 //iterate through all categories 1167 for (Iterator i = 1168 categories.getPermissibleValues().iterator(); i.hasNext(); ) { 1169 1170 JMenuItem menuItem = new JMenuItem( (String) i.next() ); 1171 menuItem.addActionListener(this); 1172 popup.add(menuItem); 1173 } //for 1174 1175 } //if 1176 }// while 1177 1178 //if we don't have a schema, issue a warning 1179 if (! found) 1180 Out.println("Warning: You need to define an annotation schema for " + 1181 treeNodeAnnotationType + 1182 " in order to be able to add such annotations."); 1183 1184 } // fillCategoriesMenu 1185 1186 /** 1187 * Sets the action commands of all menu items to the specified command 1188 */ 1189 private void setMenuCommands(JPopupMenu menu, String command) { 1190 for (int i = 0; i < menu.getComponentCount() ; i++) { 1191 JMenuItem item = (JMenuItem) menu.getComponent(i); 1192 item.setActionCommand(command); 1193 } 1194 1195 } // setMenuCommands 1196 1197 /** 1198 * Create a parent node for all selected non-terminal nodes 1199 */ 1200 protected STreeNode createParentNode(String text) { 1201 STreeNode parentNode = new STreeNode(); 1202 1203 long begin = 2147483647, end = 0, level= -1; 1204 for (Iterator i = selection.iterator(); i.hasNext(); ) { 1205 JButton button = (JButton) i.next(); 1206 Integer id = new Integer(button.getActionCommand()); 1207 1208 STreeNode child = (STreeNode) nonTerminals.get(id); 1209 1210 if (begin > child.getStart()) 1211 begin = child.getStart(); 1212 if (end < child.getEnd()) 1213 end = child.getEnd(); 1214 if (level < child.getLevel()) 1215 level = child.getLevel(); 1216 1217 parentNode.add(child); 1218 1219 } //for 1220 1221 parentNode.setLevel(level+1); 1222 parentNode.setStart(begin); 1223 parentNode.setEnd(end); 1224 parentNode.setUserObject(text); 1225 parentNode.createAnnotation(document, 1226 treeNodeAnnotationType, 1227 displayedString, 1228 utteranceStartOffset.longValue()); 1229 1230 1231 return parentNode; 1232 } 1233 1234 /** 1235 * Create a parent node for all selected non-terminal nodes 1236 */ 1237 protected STreeNode createParentNode(String text, Annotation annot) { 1238 STreeNode parentNode = new STreeNode(annot); 1239 1240 long level = -1; 1241 for (Iterator i = selection.iterator(); i.hasNext(); ) { 1242 JButton button = (JButton) i.next(); 1243 Integer id = new Integer(button.getActionCommand()); 1244 1245 STreeNode child = (STreeNode) nonTerminals.get(id); 1246 1247 if (level < child.getLevel()) 1248 level = child.getLevel(); 1249 1250 parentNode.add(child); 1251 } //for 1252 1253 parentNode.setLevel(level+1); 1254 parentNode.setUserObject(text); 1255 1256 return parentNode; 1257 } 1258 1259 1260 void selectNode(MouseEvent e) { 1261 // try finding the node that's annotated, i.e., the selected button 1262 if (e.getSource() instanceof JButton) { 1263 JButton source = (JButton) e.getSource(); 1264 1265 selection.add(source); 1266 buttonBackground = source.getBackground(); 1267 source.setBackground(selectedNodeColor); 1268 } 1269 } 1270 1271 // remove that node from the syntax tree 1272 void removeNode(JButton button) { 1273 1274 Integer id = new Integer(button.getActionCommand()); 1275 STreeNode node = (STreeNode) nonTerminals.get(id); 1276 nonTerminals.remove(node); 1277 node.removeAnnotation(document); 1278 1279 //fix the STreeNodes involved 1280 resetChildren(node); 1281 removeNodesAbove(node); 1282 1283 //remove button from everywhere 1284 buttons.remove(button); 1285 button.setVisible(false); 1286 this.remove(button); 1287 1288 //recalculate all lines 1289 recalculateLines(); 1290 1291 //make sure we clear the selection 1292 selection.clear(); 1293 repaint(); 1294 } 1295 1296 //set parent node to null for all children of the given node 1297 private void resetChildren(STreeNode node) { 1298 for (Enumeration e = node.children(); e.hasMoreElements(); ) 1299 ((STreeNode) e.nextElement()).setParent(null); 1300 1301 node.disconnectChildren(); 1302 } 1303 1304 private void removeNodesAbove(STreeNode node) { 1305 STreeNode parent = (STreeNode) node.getParent(); 1306 1307 while (parent != null) { 1308 Integer id = new Integer(parent.getID()); 1309 parent.removeAnnotation(document); 1310 if (parent.isNodeChild(node)) 1311 parent.remove(node); 1312 parent.disconnectChildren(); 1313 1314 nonTerminals.remove(id); 1315 1316 JButton button = (JButton) buttons.get(id); 1317 this.remove(button); 1318 buttons.remove(id); 1319 1320 parent = (STreeNode) parent.getParent(); 1321 } 1322 } 1323 1324 private void recalculateLines() { 1325 lines.clear(); 1326 //go through all non-terminals and recalculate their lines to their children 1327 for (Iterator i = nonTerminals.values().iterator(); i.hasNext(); ) 1328 recalculateLines((STreeNode) i.next()); 1329 1330 } 1331 1332 /** 1333 * recalculates all lines from that node to all its children 1334 */ 1335 private void recalculateLines(STreeNode node) { 1336 Integer id = new Integer(node.getID()); 1337 JButton button = (JButton) buttons.get(id); 1338 1339 int bX = button.getX() + button.getWidth()/2; 1340 int bY = button.getY() + button.getHeight(); 1341 1342 for (Enumeration e = node.children(); e.hasMoreElements(); ) { 1343 STreeNode subNode = (STreeNode) e.nextElement(); 1344 Integer sid = new Integer(subNode.getID()); 1345 JButton subButton = (JButton) buttons.get(sid); 1346 1347 Coordinates coords = new Coordinates( 1348 bX, 1349 bY, 1350 subButton.getX() + subButton.getWidth()/2, 1351 subButton.getY()); 1352 1353 lines.add(coords); 1354 } 1355 1356 } 1357 1358/* 1359 // discontinued from use,done automatically instead, when the utterance is set 1360 1361 public void setTreeAnnotations(AnnotationSet newTreeAnnotations) { 1362 AnnotationSet oldTreeAnnotations = treeAnnotations; 1363 treeAnnotations = newTreeAnnotations; 1364 firePropertyChange("treeAnnotations", oldTreeAnnotations, 1365 newTreeAnnotations); 1366 } 1367*/ 1368 1369 public void setTreeNodeAnnotationType(String newTreeNodeAnnotationType) { 1370 treeNodeAnnotationType = newTreeNodeAnnotationType; 1371 } 1372 1373 public void setTokenType(String newTokenType) { 1374 if (newTokenType != null && ! newTokenType.equals("")) 1375 tokenType = newTokenType; 1376 } 1377 1378 public String getTokenType() { 1379 return tokenType; 1380 } 1381 1382 void this_componentShown(ComponentEvent e) { 1383 Out.println("Tree Viewer shown"); 1384 } 1385 1386 void this_componentHidden(ComponentEvent e) { 1387 Out.println("Tree Viewer closes"); 1388 } 1389 1390/* 1391 //None of this works, damn!!! 1392 1393 public void setVisible(boolean b) { 1394 if (!b && this.isVisible()) 1395 Out.println("Tree Viewer closes"); 1396 1397 super.setVisible( b); 1398 } 1399 public void hide() { 1400 Out.println("Tree Viewer closes"); 1401 super.hide(); 1402 } 1403*/ 1404 1405 1406}// class SyntaxTreeViewer 1407 1408 1409class FocusButton extends JButton { 1410 1411 public FocusButton(String text) { 1412 super(text); 1413 } 1414 1415 public FocusButton() { 1416 super(); 1417 } 1418 1419 public FocusButton(Icon icon) { 1420 super(icon); 1421 } 1422 1423 public FocusButton(String text, Icon icon) { 1424 super(text, icon); 1425 }// public FocusButton 1426 1427 public boolean isManagingFocus() { 1428 return true; 1429 }// public boolean isManagingFocus() 1430 1431 public void processComponentKeyEvent(KeyEvent e) { 1432 super.processComponentKeyEvent(e); 1433 1434 //I need that cause I get all events here, so I only want to process 1435 //when it's a release event. The reason is that for keys like <DEL> 1436 //key_typed never happens 1437 if (e.getID() != KeyEvent.KEY_RELEASED) 1438 return; 1439 1440 if (e.getKeyCode() == KeyEvent.VK_DELETE) { 1441 SyntaxTreeViewer viewer = (SyntaxTreeViewer) ((JButton) e.getSource()).getParent(); 1442 viewer.removeNode((JButton) e.getSource()); 1443 } 1444 }// public void processComponentKeyEvent(KeyEvent e) 1445 1446} // class SyntaxTreeViewer 1447 1448// $Log: SyntaxTreeViewer.java,v $ 1449// Revision 1.21 2002/03/06 17:15:46 kalina 1450// Reorganised the source code, so that it now uses constants from 1451// ANNIEConstants, GateConstants and parameter constants defined on each PR. 1452// Read e-mail to the gate list for an explanation. 1453// 1454// Revision 1.20 2001/08/08 16:14:26 kalina 1455// A minor change to the tree viewer. 1456// 1457// Revision 1.19 2001/08/08 14:39:00 kalina 1458// Made the dialog to size itself maximum as much as the screen, coz was 1459// getting too big without that. 1460// 1461// Some documentation on Tree Viewer and some small changes to utterance2trees() 1462// to make it order the tokens correctly by offset 1463// 1464// Revision 1.18 2001/08/07 19:03:05 kalina 1465// Made the tree viewer use Token annotations to break the sentence for annotation 1466// 1467// Revision 1.17 2001/08/07 17:01:32 kalina 1468// Changed the AVR implementing classes in line with the updated AVR 1469// API (cancelAction() and setSpan new parameter). 1470// 1471// Also updated the TreeViewer, so now it can be used to edit and view 1472// Sentence annotations and the SyntaxTreeNodes associated with them. 1473// So if you have trees, it'll show them, if not, it'll help you build them. 1474// 1475// Revision 1.16 2001/04/09 10:36:36 oana 1476// a few changes in the code style 1477// 1478// Revision 1.14 2000/12/04 12:29:29 valyt 1479// Done some work on the visual resources 1480// Added the smart XJTable 1481// 1482// Revision 1.13 2000/11/08 16:35:00 hamish 1483// formatting 1484// 1485// Revision 1.12 2000/10/26 10:45:26 oana 1486// Modified in the code style 1487// 1488// Revision 1.11 2000/10/24 10:10:18 valyt 1489// Fixed the deprecation warning in gate/gui/SyntaxTreeViewer.java 1490// 1491// Revision 1.10 2000/10/18 13:26:47 hamish 1492// Factory.createResource now working, with a utility method that uses reflection (via java.beans.Introspector) to set properties on a resource from the 1493// parameter list fed to createResource. 1494// resources may now have both an interface and a class; they are indexed by interface type; the class is used to instantiate them 1495// moved createResource from CR to Factory 1496// removed Transients; use Factory instead 1497// 1498// Revision 1.9 2000/10/16 16:44:32 oana 1499// Changed the comment of DEBUG variable 1500// 1501// Revision 1.8 2000/10/10 15:36:35 oana 1502// Changed System.out in Out and System.err in Err; 1503// Added the DEBUG variable seted on false; 1504// Added in the header the licence; 1505// 1506// Revision 1.7 2000/10/10 09:49:57 valyt 1507// Fixed the Annotation test 1508// 1509// Revision 1.6 2000/10/02 12:34:06 valyt 1510// Added the UnicodeEnabled switch on gate.util.Tools 1511// 1512// Revision 1.5 2000/09/28 14:26:09 kalina 1513// Added even more documentation (is this me?!) and allowed several tokens to be 1514// passed instead of a whole utterance/sentence for annotation. Needs good testing this 1515// but will do it when somebody tries using this functionality. 1516// 1517// Revision 1.4 2000/09/28 13:16:12 kalina 1518// Added some documentation 1519// 1520// Revision 1.3 2000/09/21 14:23:45 kalina 1521// Fixed some small bug in main(). To test just run the component itself. 1522// 1523// Revision 1.2 2000/09/21 14:17:27 kalina 1524// Added Unicode support 1525// 1526// Revision 1.1 2000/09/20 17:03:37 kalina 1527// Added the tree viewer from the prototype. It works now with the new annotation API. 1528
|
SyntaxTreeViewer |
|