SyntaxTreeViewer.java
0001 /*
0002  *  SyntaxTreeViewer.java
0003  *
0004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
0005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
0006  *
0007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
0008  *  software, licenced under the GNU Library General Public License,
0009  *  Version 2, June 1991 (in the distribution as file licence.html,
0010  *  and also available at http://gate.ac.uk/gate/licence.html).
0011  *
0012  *  Kalina Bontcheva, 20/09/2000
0013  *
0014  *  $Id: SyntaxTreeViewer.java 12006 2009-12-01 17:24:28Z thomas_heitz $
0015  */
0016 
0017 package gate.gui;
0018 
0019 //java imports
0020 import java.awt.*;
0021 import java.awt.event.*;
0022 import java.beans.PropertyChangeEvent;
0023 import java.util.*;
0024 
0025 import javax.swing.*;
0026 
0027 import gate.*;
0028 import gate.creole.*;
0029 import gate.util.*;
0030 
0031 
0032 /**
0033   * The SyntaxTreeViewer is capable of showing and editing utterances (fancy
0034   * name for sentences) and the
0035   * attached syntax trees. It works by taking an utterance and all Token
0036   * annotations and constructs the text. Then it also gets all SyntaxTreeNode
0037   * annotations and builds and shows the syntac tree for that utterance. The
0038   * leaves of the tree are the tokens, which constitute the utterance.<P>
0039   *
0040   * It is possible to configure the annotation types that are used by the
0041   * viewer. The textAnnotationType property specifies the type
0042   * of annotation which is used to denote the utterance (sentence).
0043   * In GATE, the value of this property is not set directly, but is derived
0044   * from the VR configuration information from creole.xml (explained below).
0045   *
0046   * The treeNodeAnnotationType is the name of the
0047   * annotations which encode the SyntaxTreeNodes; default - SyntaxTreeNode.
0048   * To change when part of GATE, modify the <PARAMETER> setting of the
0049   * TreeViewer entry in creole.xml. Similarly, one can change which annotation
0050   * is used for chunking the utterance. By default, it is Token, which is also
0051   * specified in creole.xml as a parameter in the treeviewer entry.
0052   *
0053   * The component assumes that the annotations of type treeNodeAnnotationType have
0054   * features called: cat with a value String; consists which is a List either
0055   * empty or with annotation ids of the node's children; and optionally
0056   * text which contains
0057   * the text covered by this annotation. The component will work fine even
0058   * without the last feature. Still when it creates annotations,
0059   * these will have this feature added. <P>
0060   *
0061   *
0062   * Newly added tree nodes to the tree are added to the document
0063   * as annotations and deleted nodes are automatically deleted from the document
0064   * only after OK is chosen in the dialog. Cancel does not make any changes
0065   * permanent. <P>
0066   *
0067   * Configuring the viewer in GATE<P>
0068   * The viewer is configured in creole.xml. The default entry is:
0069   <PRE>
0070   *   <RESOURCE>
0071   *     <NAME>Syntax tree viewer</NAME>
0072   *     <CLASS>gate.gui.SyntaxTreeViewer</CLASS>
0073   *     <!-- type values can be  "large" or "small"-->
0074   *     <GUI>
0075   *       <MAIN_VIEWER/>
0076   *       <ANNOTATION_TYPE_DISPLAYED>Sentence</ANNOTATION_TYPE_DISPLAYED>
0077   *       <PARAMETER NAME="treeNodeAnnotationType" DEFAULT="SyntaxTreeNode"
0078   *                  RUNTIME="false" OPTIONAL="true">java.lang.String
0079   *       </PARAMETER>
0080   *       <PARAMETER NAME="tokenType" DEFAULT="Token" RUNTIME="false"
0081   *                  OPTIONAL="true">java.lang.String
0082   *       </PARAMETER>
0083   *     </GUI>
0084   *   </RESOURCE>
0085   </PRE>
0086   *
0087   * The categories that appear in the menu for manual annotation are determined
0088   * from SyntaxTreeViewerSchema.xml. If you want to change the default set,
0089   * you must edit this file and update your Gate jar accordingly (e.g., by
0090   * recompilation. This does not affect the categories of SyntaxTreeNode
0091   * annotations, which have been created automatically by some other process,
0092   * e.g., a parser PR.
0093   *
0094   <P>
0095   * If used outside GATE,
0096   * in order to have appropriate behaviour always put this component inside a
0097   * scroll pane or something similar that provides scrollers.
0098   * Example code: <BREAK>
0099   <PRE>
0100   *  JScrollPane scroller = new JScrollPane(syntaxTreeViewer1);
0101   *  scroller.setPreferredSize(syntaxTreeViewer1.getPreferredSize());
0102   *  frame.getContentPane().add(scroller, BorderLayout.CENTER);
0103   </PRE>
0104   *
0105   *
0106   * The default way is to pass just one annotation of type textAnnotationType
0107   * which corresponds to the entire sentence or utterance to be annotated with
0108   * syntax tree information. Then the viewer automatically tokenises it
0109   * (by obtaining the relevant token annotations) and creates the leaves.<P>
0110   *
0111   * To create a new annotation, use setSpan, instead of setAnnotation.
0112   *
0113   <P> In either
0114   * case, you must call setTarget first, because that'll provide the viewer
0115   * with the document's annotation set, from where it can obtain the token
0116   * annotations.
0117   <P> If you intend to use the viewer outside GATE and do not understand
0118   * the API, e-mail gate@dcs.shef.ac.uk.
0119   */
0120 
0121 public class SyntaxTreeViewer extends AbstractVisualResource
0122     implements  Scrollable, ActionListener, MouseListener,
0123                 AnnotationVisualResource {
0124 
0125   /** The annotation type used to encode each tree node*/
0126   public static final String TREE_NODE_ANNOTATION_TYPE = "SyntaxTreeNode";
0127   /** The name of the feature that encodes the tree node's category information */
0128   public static final String NODE_CAT_FEATURE_NAME = "cat";
0129   /** The name of the feature that encodes the subtree annotations */
0130   public static final String NODE_CONSISTS_FEATURE_NAME = "consists";
0131 
0132   // class members
0133   // whether to use any layout or not
0134   protected boolean laidOut = false;
0135 
0136   // display all buttons x pixels apart horizontally
0137   protected int horizButtonGap = 5;
0138 
0139   // display buttons at diff layers x pixels apart vertically
0140   protected int vertButtonGap = 50;
0141 
0142   // extra width in pixels to be added to each button
0143   protected int extraButtonWidth = 10;
0144 
0145   // number of pixels to be used as increment by scroller
0146   protected int maxUnitIncrement = 10;
0147 
0148   // GUI members
0149   BorderLayout borderLayout1 = new BorderLayout();
0150   JPopupMenu popup = new JPopupMenu()//the right-click popup
0151   Color buttonBackground;
0152   Color selectedNodeColor = Color.red.darker();
0153 
0154   // the HashSet with the coordinates of the lines to draw
0155   HashSet lines = new HashSet();
0156 
0157   // The utterance to be annotated as a sentence. It's not used if the tree
0158   // is passed
0159   // as annotations.
0160   protected Annotation utterance;
0161   protected Long utteranceStartOffset = new Long(0);
0162   protected Long utteranceEndOffset = new Long(0);
0163   protected AnnotationSet currentSet = null;
0164 
0165   protected String tokenType = ANNIEConstants.TOKEN_ANNOTATION_TYPE;
0166 
0167   // for internal use only. Set when the utterance is set.
0168   protected String displayedString = "";
0169 
0170   // The name of the annotation type which is used to locate the
0171   // stereotype with the allowed categories
0172   // also when reading and creating annotations
0173   protected String treeNodeAnnotationType = TREE_NODE_ANNOTATION_TYPE;
0174 
0175   // The annotation name of the annotations used to extract the
0176   // text that appears at the leaves of the tree. For now the viewer
0177   // supports only one such annotation but might be an idea to extend it
0178   // so that it gets its text off many token annotations, which do not
0179   // need to be tokenised or off the syntax tree annotations themselves.
0180   protected String textAnnotationType = ANNIEConstants.SENTENCE_ANNOTATION_TYPE;
0181 
0182   // all leaf nodes
0183   protected HashMap leaves = new HashMap();
0184 
0185   // all non-terminal nodes
0186   protected HashMap nonTerminals = new HashMap();
0187 
0188   // all buttons corresponding to any node
0189   protected HashMap buttons = new HashMap();
0190 
0191   // all selected buttons
0192   protected Vector selection = new Vector();
0193 
0194   // all annotations to be displayed
0195   protected AnnotationSet treeAnnotations;
0196 
0197   protected Document document = null;
0198   // the document to which the annotations belong
0199 
0200   //true when a new utterance annotation has been added
0201   //then if the user presses cancel, I need to delete it
0202   protected boolean utteranceAdded = false;
0203 
0204 
0205   public SyntaxTreeViewer() {
0206     try  {
0207       jbInit();
0208     }
0209     catch(Exception ex) {
0210       ex.printStackTrace(Err.getPrintWriter());
0211     }
0212 
0213   }
0214 
0215   //CONSTRUCTORS
0216   private SyntaxTreeViewer(String annotType) {
0217 
0218     treeNodeAnnotationType = annotType;
0219     try  {
0220       jbInit();
0221     }
0222     catch(Exception ex) {
0223       ex.printStackTrace(Err.getPrintWriter());
0224     }
0225   }
0226 
0227   //METHODS
0228   private void jbInit() throws Exception {
0229 
0230     //check if we're using a layout; preferrably not
0231     if (laidOut)
0232       this.setLayout(borderLayout1);
0233     else
0234       this.setLayout(null);
0235 
0236     this.setPreferredSize(new Dimension (600400));
0237     this.setSize(600400);
0238     this.setBounds(00600400);
0239     this.addComponentListener(new java.awt.event.ComponentAdapter() {
0240       public void componentShown(ComponentEvent e) {
0241         this_componentShown(e);
0242       }
0243       public void componentHidden(ComponentEvent e) {
0244         this_componentHidden(e);
0245       }
0246     });
0247     this.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
0248 
0249       public void propertyChange(PropertyChangeEvent e) {
0250         this_propertyChange(e);
0251       }
0252     });
0253 
0254     buttonBackground = Color.red; //this.getBackground();
0255 
0256     //get all categories from stereotype
0257     fillCategoriesMenu();
0258 
0259     //initialise the popup menu
0260 
0261     //add popup to container
0262     this.add(popup);
0263   }// private void jbInit()
0264 
0265   // Methods required by AnnotationVisualResource
0266 
0267   /**
0268     * Used when the viewer/editor has to display/edit an existing annotation
0269     @param ann the annotation to be displayed or edited. If ann is null then
0270     * the method simply returns
0271     */
0272   public void editAnnotation(Annotation ann, AnnotationSet set){
0273     if (ann == null || set == nullreturn;
0274 
0275     utterance = ann;
0276     currentSet = set;
0277     document = set.getDocument();
0278     utteranceStartOffset = utterance.getStartNode().getOffset();
0279     utteranceEndOffset = utterance.getEndNode().getOffset();
0280     textAnnotationType = ann.getType();
0281 
0282     clearAll();
0283     utterances2Trees();
0284     annotations2Trees();
0285     this.setVisible(true);
0286     repaint();
0287   }
0288 
0289   /**
0290    * Called by the GUI when the user has pressed the "OK" button. This should
0291    * trigger the saving of the newly created annotation(s)
0292    */
0293   public void okAction() throws GateException{
0294     //Out.println("Visible coords" + this.getVisibleRect().toString());
0295     //Out.println("Size" + this.getBounds().toString());
0296     STreeNode.transferAnnotations(document, currentSet);
0297 
0298   //okAction()
0299 
0300   /**
0301    * Called by the GUI when the user has pressed the "Cancel" button. This should
0302    * trigger the cleanup operation
0303    */
0304   public void cancelAction() throws GateException{
0305     //if we added a new utterance but user does not want it any more...
0306     if (utteranceAdded) {
0307       currentSet.remove(utterance)//delete it
0308       utteranceAdded = false;
0309     }
0310     //also cleanup the temporary annotation sets used by the viewer
0311     //to cache the added and deleted tree annotations
0312     STreeNode.undo(document);
0313 
0314   //cancelAction()
0315 
0316   /**
0317    * Returns <tt>true</tt>.
0318    */
0319   public boolean supportsCancel() {
0320     return true;
0321   }
0322 
0323   
0324   /**
0325    * Returns <tt>true</tt>
0326    */
0327   public boolean editingFinished() {
0328     return true;
0329   }
0330 
0331   /* (non-Javadoc)
0332    * @see gate.creole.AnnotationVisualResource#getAnnotationCurrentlyEdited()
0333    */
0334   public Annotation getAnnotationCurrentlyEdited() {
0335     return utterance;
0336   }
0337 
0338   /* (non-Javadoc)
0339    * @see gate.creole.AnnotationVisualResource#getAnnotationSetCurrentlyEdited()
0340    */
0341   public AnnotationSet getAnnotationSetCurrentlyEdited() {
0342     return currentSet;
0343   }
0344 
0345   /* (non-Javadoc)
0346    * @see gate.creole.AnnotationVisualResource#isActive()
0347    */
0348   public boolean isActive() {
0349     return isVisible();
0350   }
0351 
0352   /**
0353     * Checks whether this viewer/editor can handle a specific annotation type.
0354     @param annotationType represents the annotation type being questioned.If
0355     * it is <b>null</b> then the method will return false.
0356     @return true if the SchemaAnnotationEditor can handle the annotationType
0357     * or false otherwise.
0358     */
0359   public boolean canDisplayAnnotationType(String annotationType){
0360     // Returns true only if the there is an AnnotationSchema with the same type
0361     // as annotationType.
0362     if (annotationType == nullreturn false;
0363     boolean found = false;
0364 
0365     java.util.List<String> specificEditors = Gate.getCreoleRegister().
0366                                      getAnnotationVRs(annotationType);
0367     Iterator<String> editorIter = specificEditors.iterator();
0368     while(editorIter.hasNext() && !found){
0369       String editorClass = (String)editorIter.next();
0370 
0371 //      Out.println(editorClass);
0372       if (editorClass.equals(this.getClass().getCanonicalName())) {
0373         textAnnotationType = annotationType;
0374         found = true;
0375       }
0376     }
0377 
0378     return found;
0379   }// canDisplayAnnotationType();
0380 
0381 
0382 /*  public static void main(String[] args) throws Exception {
0383     Gate.init();
0384     // final String text = "This is a sentence. That is another one.";
0385     final String text = "\u0915\u0932\u094d\u0907\u0928\u0643\u0637\u0628 \u041a\u0430\u043b\u0438\u043d\u0430 Kalina";
0386     final Document doc = Factory.newDocument(text);
0387 
0388     // that works too but only use if you have the test file there.
0389     // final Document doc = Factory.newDocument(
0390     //                        new URL("file:///z:/temp/weird.txt"), "UTF-8");
0391 
0392 
0393     final SyntaxTreeViewer syntaxTreeViewer1 =
0394       new SyntaxTreeViewer("SyntaxTreeNode");
0395     //syntaxTreeViewer1.setUnicodeSupportEnabled(true);
0396     //need to set the document here!!!!
0397 
0398 
0399     JFrame frame = new JFrame();
0400 
0401     //INITIALISE THE FRAME, ETC.
0402     frame.setEnabled(true);
0403     frame.setTitle("SyntaxTree Viewer");
0404     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
0405 
0406     // frame.getContentPane().add(syntaxTreeViewer1, BorderLayout.CENTER);
0407     // intercept the closing event to shut the application
0408     frame.addWindowListener(new WindowAdapter() {
0409       public void windowClosing(WindowEvent e) {
0410         AnnotationSet hs = doc.getAnnotations().get("SyntaxTreeNode");
0411         if (hs != null && hs.size() > 0) {
0412           int k = 0;
0413           for (Iterator i = hs.iterator(); i.hasNext(); k++) {
0414             Out.println("Tree Annot " + k + ": ");
0415             Out.println(i.next().toString());
0416           }
0417         } //if
0418         Out.println("Exiting...");
0419         //System.exit(0);
0420       }
0421     });
0422 
0423     //Put the bean in a scroll pane.
0424     JScrollPane scroller = new JScrollPane(syntaxTreeViewer1);
0425     scroller.setPreferredSize(syntaxTreeViewer1.getPreferredSize());
0426     frame.getContentPane().add(scroller, BorderLayout.CENTER);
0427 
0428     //DISPLAY FRAME
0429     frame.pack();
0430     frame.show();
0431 
0432     FeatureMap attrs = Factory.newFeatureMap();
0433     attrs.put("time", new Long(0));
0434     attrs.put("text", doc.getContent().toString());
0435 */
0436     /*
0437     FeatureMap attrs1 = Factory.newFeatureMap();
0438     attrs1.put("cat", "N");
0439     attrs1.put("text", "This");
0440     attrs1.put("consists", new Vector());
0441 
0442     FeatureMap attrs2 = Factory.newFeatureMap();
0443     attrs2.put("cat", "V");
0444     attrs2.put("text", "is");
0445     attrs2.put("consists", new Vector());
0446     */
0447 
0448 /*
0449     doc.getAnnotations().add( new Long(0), new Long(
0450                       doc.getContent().toString().length()),"utterance", attrs);
0451 */
0452     /* Integer id1 = doc.getAnnotations().add(new Long(0), new Long(4),
0453                               "SyntaxTreeNode", attrs1);
0454     Integer id2 = doc.getAnnotations().add(new Long(5), new Long(7),
0455                               "SyntaxTreeNode", attrs2);
0456 
0457     FeatureMap attrs3 = Factory.newFeatureMap();
0458     attrs3.put("cat", "VP");
0459     attrs3.put("text", "This is");
0460     Vector consists = new Vector();
0461     consists.add(id1);
0462     consists.add(id2);
0463     attrs3.put("consists", consists);
0464     doc.getAnnotations().add(new Long(0), new Long(7),
0465                                                   "SyntaxTreeNode", attrs3);
0466     */
0467 
0468 /*
0469     HashSet set = new HashSet();
0470     set.add("utterance");
0471     set.add("SyntaxTreeNode");
0472     AnnotationSet annots = doc.getAnnotations().get(set);
0473     syntaxTreeViewer1.setTreeAnnotations(annots);
0474 
0475   }// public static void main
0476 */
0477 
0478   protected void paintComponent(Graphics g) {
0479     super.paintComponentg);
0480     drawLines(g);
0481   }// protected void paintComponent(Graphics g)
0482 
0483 
0484   private void drawLines(Graphics g) {
0485 
0486     for (Iterator i = lines.iterator(); i.hasNext()) {
0487       Coordinates coords = (Coordinatesi.next();
0488 
0489       g.drawLinecoords.getX1(),
0490                   coords.getY1(),
0491                   coords.getX2(),
0492                   coords.getY2());
0493     }// for
0494   }// private void drawLines(Graphics g)
0495 
0496   public Dimension getPreferredScrollableViewportSize() {
0497         return getPreferredSize();
0498   }// public Dimension getPreferredScrollableViewportSize()
0499 
0500   public int getScrollableUnitIncrement(Rectangle visibleRect,
0501                                               int orientation, int direction) {
0502     return maxUnitIncrement;
0503   }// public int getScrollableUnitIncrement
0504 
0505   public int getScrollableBlockIncrement(Rectangle visibleRect,
0506                                               int orientation, int direction) {
0507     if (orientation == SwingConstants.HORIZONTAL)
0508         return visibleRect.width - maxUnitIncrement;
0509     else
0510         return visibleRect.height - maxUnitIncrement;
0511   }// public int getScrollableBlockIncrement
0512 
0513   public boolean getScrollableTracksViewportWidth() {
0514     return false;
0515   }// public boolean getScrollableTracksViewportWidth()
0516 
0517   public boolean getScrollableTracksViewportHeight() {
0518     return false;
0519   }
0520 
0521   void this_propertyChange(PropertyChangeEvent e) {
0522 
0523     //we have a new utterance to display and annotate
0524     if (e.getPropertyName().equals("utterance")) {
0525       clearAll();
0526       utterances2Trees();
0527     }
0528 
0529   //this_propertyChange
0530 
0531   /**
0532     * Clear all buttons and tree nodes created because component is being
0533     * re-initialised. Not sure it works perfectly.
0534     */
0535   private void clearAll() {
0536     lines.clear();
0537     this.removeAll();
0538     buttons.clear();
0539     leaves.clear();
0540     nonTerminals.clear();
0541   }
0542 
0543   /**
0544     * Converts the annotations into treeNodes
0545     */
0546   private void annotations2Trees() {
0547     if (document == nullreturn;
0548 
0549     HashMap processed = new HashMap()//for all processed annotations
0550 
0551     //first get all tree nodes in this set, then restrict them by offset
0552     AnnotationSet tempSet = currentSet.get(treeNodeAnnotationType);
0553     if (tempSet == null || tempSet.isEmpty())
0554       return;
0555     treeAnnotations = tempSet.get(utterance.getStartNode().getOffset(),
0556                                   utterance.getEndNode().getOffset());
0557     if (treeAnnotations == null || treeAnnotations.isEmpty())
0558       return;
0559 
0560     // sort them from left to right first
0561     // Should work as
0562     // annotation implements Comparable
0563     java.util.List nodeAnnots = new ArrayList(treeAnnotations);
0564     Collections.sort(nodeAnnots, new gate.util.OffsetComparator());
0565 
0566     Vector childrenButtons = new Vector();
0567     String oldParent = "";
0568 
0569     //find all annotations with no children
0570     Iterator i = nodeAnnots.iterator();
0571     while (i.hasNext()) {
0572       Annotation annot = (Annotationi.next();
0573 
0574       java.util.List children =
0575         (java.util.Listannot.getFeatures().get(NODE_CONSISTS_FEATURE_NAME);
0576       //check if it's a leaf
0577       if (children == null ||
0578           children.isEmpty())
0579         {
0580 
0581         STreeNode leaf = findLeaf(annot.getStartNode(), annot.getEndNode());
0582         if (leaf == null) {//not found
0583           Out.println("Can't find my leaf node for annotation: " + annot);
0584         }
0585 
0586         JButton button = (JButtonbuttons.get(new Integer(leaf.getID()));
0587         selection.clear();
0588         selection.add(button);
0589 
0590         //then create the non-terminal with the category
0591         STreeNode node = new STreeNode(annot);
0592         node.add(leaf);
0593         node.setLevel(1);
0594         node.setUserObject(annot.getFeatures().get(NODE_CAT_FEATURE_NAME));
0595         nonTerminals.put(new Integer(node.getID()), node);
0596         JButton parentButton = createCentralButton(node);
0597         addLines(node);
0598 
0599         //finally add to the processed annotations
0600         processed.put(annot.getId(), parentButton);
0601 
0602       //if
0603 
0604     //loop through children
0605 
0606     //loop through the rest of the nodes
0607     Iterator i1 = nodeAnnots.iterator();
0608     while (i1.hasNext()) {
0609       Annotation annotNode = (Annotationi1.next();
0610       if (processed.containsKey(annotNode.getId()))
0611         continue;
0612       processChildrenAnnots(annotNode, processed);
0613     //process all higher nodes
0614 
0615     selection.clear();
0616 
0617     this.scrollRectToVisible(new
0618       Rectangle(0(intgetHeight()(intgetVisibleRect().getHeight(),
0619         (intgetVisibleRect().getWidth()(intgetVisibleRect().getHeight()));
0620   //annotations2Trees
0621 
0622   private JButton processChildrenAnnots(Annotation annot, HashMap processed) {
0623     selection.clear();
0624     Vector childrenButtons = new Vector();
0625     java.util.List children =
0626       (java.util.Listannot.getFeatures().get(NODE_CONSISTS_FEATURE_NAME);
0627 
0628     for (Iterator i = children.iterator(); i.hasNext()) {
0629       Integer childId = (Integeri.next();
0630       Annotation child = treeAnnotations.get(childId);
0631       JButton childButton;
0632 
0633       if (processed.containsKey(child.getId()))
0634         childButton = (JButtonprocessed.get(child.getId());
0635       else
0636         childButton = processChildrenAnnots(child, processed);
0637 
0638       childrenButtons.add(childButton);
0639     }
0640 
0641     selection = (VectorchildrenButtons.clone();
0642     STreeNode parent = createParentNode(
0643                           (Stringannot.getFeatures().get(NODE_CAT_FEATURE_NAME),
0644                           annot);
0645     nonTerminals.put(new Integer(parent.getID()), parent);
0646     JButton parentButton = createCentralButton(parent);
0647     addLines(parent);
0648 
0649     processed.put(annot.getId(), parentButton);
0650     selection.clear();
0651     return parentButton;
0652   }// private JButton processChildrenAnnots
0653 
0654   private STreeNode findLeaf(Node start, Node end) {
0655     for (Iterator i = leaves.values().iterator(); i.hasNext()) {
0656       STreeNode node = (STreeNodei.next();
0657       if (node.getStart() == start.getOffset().intValue() &&
0658           node.getEnd() == end.getOffset().intValue()
0659          )
0660         return node;
0661     }
0662 
0663     return null;
0664   }//private STreeNode findLeaf(Node start, Node end)
0665 
0666 
0667   /**
0668     * Converts the given utterances into a set of leaf nodes for annotation
0669     */
0670   private void utterances2Trees() {
0671 
0672     if (! utterance.getType().equals(textAnnotationType)) {
0673       Out.println("Can't display annotations other than the specified type:" +
0674                                                             textAnnotationType);
0675       return;
0676     }
0677 
0678     // set the utterance offset correctly.
0679     // All substring calculations depend on that.
0680     utteranceStartOffset = utterance.getStartNode().getOffset();
0681     utteranceEndOffset = utterance.getEndNode().getOffset();
0682 
0683     try {
0684       displayedString = currentSet.getDocument().getContent().getContent(
0685                         utteranceStartOffset, utteranceEndOffset).toString();
0686     catch (InvalidOffsetException ioe) {
0687       ioe.printStackTrace(Err.getPrintWriter());
0688     }
0689 
0690     AnnotationSet tokensAS = currentSet.get(tokenType, utteranceStartOffset,
0691                                           utteranceEndOffset);
0692     if (tokensAS == null || tokensAS.isEmpty()) {
0693       Out.println("TreeViewer warning: No annotations of type " + tokenType +
0694                   "so cannot show or edit the text and the tree annotations.");
0695       return;
0696     }
0697 
0698     Insets insets = this.getInsets();
0699     // the starting X position for the buttons
0700     int buttonX = insets.left;
0701 
0702     // the starting Y position
0703     int buttonY = this.getHeight() 20 - insets.bottom;
0704 
0705     java.util.List tokens = new ArrayList(tokensAS);
0706     //if no tokens to match, do nothing
0707     if (tokens.isEmpty())
0708        return;
0709     Collections.sort(tokens, new gate.util.OffsetComparator());
0710 
0711     //loop through the tokens
0712     for (int i= 0; i< tokens.size(); i++) {
0713       Annotation tokenAnnot = (Annotationtokens.get(i);
0714       Long tokenBegin = tokenAnnot.getStartNode().getOffset();
0715       Long tokenEnd = tokenAnnot.getEndNode().getOffset();
0716 
0717       String tokenText = "";
0718       try {
0719         tokenText = document.getContent().getContent(
0720                         tokenBegin, tokenEnd).toString();
0721       catch (InvalidOffsetException ioe) {
0722         ioe.printStackTrace(Err.getPrintWriter());
0723       }
0724 
0725       // create the leaf node
0726       STreeNode node =
0727         new STreeNode(tokenBegin.longValue(), tokenEnd.longValue());
0728 
0729       // make it a leaf
0730       node.setAllowsChildren(false);
0731 
0732       // set the text
0733       node.setUserObject(tokenText);
0734       node.setLevel(0);
0735 
0736       // add to hash table of leaves
0737       leaves.put(new Integer(node.getID()), node);
0738 
0739       // create the corresponding button
0740       buttonX = createButton4Node(node, buttonX, buttonY);
0741 
0742     //while
0743 
0744 
0745 /*
0746     //This old piece of code was used to tokenise, instead of relying on
0747     // annotations. Can re-instate if someone shows me the need for it.
0748 
0749     long currentOffset = utteranceStartOffset.longValue();
0750 
0751     StrTokeniser strTok =
0752         new StrTokeniser(displayedString,
0753                         " \r\n\t");
0754 
0755     Insets insets = this.getInsets();
0756     // the starting X position for the buttons
0757     int buttonX = insets.left;
0758 
0759     // the starting Y position
0760     int buttonY = this.getHeight() - 20 - insets.bottom;
0761 
0762     while (strTok.hasMoreTokens()) {
0763       String word = strTok.nextToken();
0764 //      Out.println("To display:" + word);
0765 
0766       // create the leaf node
0767       STreeNode node =
0768         new STreeNode(currentOffset, currentOffset + word.length());
0769 
0770       // make it a leaf
0771       node.setAllowsChildren(false);
0772 
0773       // set the text
0774       node.setUserObject(word);
0775       node.setLevel(0);
0776 
0777       // add to hash table of leaves
0778       leaves.put(new Integer(node.getID()), node);
0779 
0780       // create the corresponding button
0781       buttonX = createButton4Node(node, buttonX, buttonY);
0782 
0783       currentOffset += word.length()+1;  //// +1 to include the delimiter too
0784     }
0785 */
0786 
0787     this.setSize(buttonX, buttonY + 20 + insets.bottom);
0788     // this.resize(buttonX, buttonY + 20 + insets.bottom);
0789     this.setPreferredSize(this.getSize());
0790 
0791   // utterance2Trees
0792 
0793   /**
0794     * Returns the X position where another button can start if necessary.
0795     * To be used to layout only the leaf buttons. All others must be created
0796     * central to their children using createCentralButton.
0797     */
0798   private int createButton4Node(STreeNode node, int buttonX, int buttonY) {
0799 
0800     JButton button = new JButton((Stringnode.getUserObject());
0801     button.setBorderPainted(false);
0802     button.setMargin(new Insets(0,0,0,0));
0803 
0804 //    FontMetrics fm = button.getFontMetrics(button.getFont());
0805 
0806     
0807 //    int buttonWidth,
0808 //        buttonHeight;
0809 
0810     // Out.print
0811     //  ("Button width " + b1.getWidth() + "Button height " + b1.getHeight());
0812 
0813 //    buttonWidth = fm.stringWidth(button.getText())
0814 //                  + button.getMargin().left + button.getMargin().right
0815 //                  + extraButtonWidth;
0816 //    buttonHeight = fm.getHeight() + button.getMargin().top +
0817 //                      button.getMargin().bottom;
0818     
0819 //    buttonWidth = buttonSize.width;
0820 //    buttonHeight = buttonSize.height;
0821     
0822 //    buttonY = buttonY - buttonHeight;
0823 
0824 //     Out.print("New Button X " + buttonX +
0825 //        "New Button Y" + buttonY);
0826 
0827 //    button.setBounds(buttonX, buttonY, buttonWidth, buttonHeight);
0828     
0829     Dimension buttonSize = button.getPreferredSize();
0830     button.setSize(buttonSize);
0831     buttonY = buttonY - buttonSize.height;
0832     button.setLocation(buttonX, buttonY);
0833     button.addActionListener(this);
0834     button.addMouseListener(this);
0835     button.setActionCommand("" + node.getID());
0836     button.setVisible(true);
0837     button.setEnabled(true);
0838 
0839     this.add(button);
0840     buttons.put(new Integer(node.getID()), button);
0841 
0842     buttonX +=  buttonSize.width + horizButtonGap;
0843     return buttonX;
0844 
0845   }// private int createButton4Node(STreeNode node, int buttonX, int buttonY)
0846 
0847   private JButton createCentralButton(STreeNode newNode) {
0848 
0849     FocusButton button = new FocusButton((StringnewNode.getUserObject());
0850     button.setBorderPainted(false);
0851 
0852 //    FontMetrics fm = button.getFontMetrics(button.getFont());
0853 
0854     int buttonWidth,
0855         buttonHeight,
0856         buttonX = 0,
0857         buttonY =0;
0858 
0859     // Out.print("Button width " + b1.getWidth() + ";
0860     //    Button height " + b1.getHeight());
0861 
0862     Dimension buttonSize = button.getPreferredSize();
0863     
0864 //    buttonWidth = fm.stringWidth(button.getText())
0865 //                  + button.getMargin().left + button.getMargin().right
0866 //                  + extraButtonWidth;
0867 //    buttonHeight = fm.getHeight() + button.getMargin().top +
0868 //                      button.getMargin().bottom;
0869 
0870     buttonWidth = buttonSize.width;
0871     buttonHeight = buttonSize.height;
0872     
0873     int left = this.getWidth(), right =, top = this.getHeight();
0874 
0875     // determine the left, right, top
0876     for (Iterator i = selection.iterator(); i.hasNext()) {
0877       JButton childButton = (JButtoni.next();
0878 
0879       if (left > childButton.getX())
0880         left = childButton.getX();
0881       if (childButton.getX() + childButton.getWidth() > right)
0882         right = childButton.getX() + childButton.getWidth();
0883       if (childButton.getY() < top)
0884         top = childButton.getY();
0885     }
0886 
0887     buttonX = (left + right/- buttonWidth/2;
0888     buttonY = top - vertButtonGap;
0889     // Out.println("Button's Y is" + buttonY);
0890 
0891     // Out.print("New Button width " + buttonWidth + ";
0892     //    New Button height " + buttonHeight);
0893     button.setBounds(buttonX, buttonY, buttonWidth, buttonHeight);
0894     button.addActionListener(this);
0895     button.addMouseListener(this);
0896     // button.registerKeyboardAction(this,
0897     //                          "delete",
0898     //                           KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
0899     //                           WHEN_FOCUSED);
0900 
0901     button.setActionCommand("" + newNode.getID());
0902 
0903     this.add(button);
0904     // add to hashmap of buttons
0905     buttons.put(new Integer(newNode.getID()), button);
0906 
0907     // check if we need to resize the panel
0908     if (buttonY < 0) {
0909       this.setSize(this.getWidth()this.getHeight() 5(- buttonY));
0910       this.setPreferredSize(this.getSize());
0911       shiftButtonsDown(5(-buttonY));
0912     }
0913 
0914     return button;
0915   }// private JButton createCentralButton(STreeNode newNode)
0916 
0917   private void shiftButtonsDown(int offset) {
0918     for (Iterator i = buttons.values().iterator(); i.hasNext()) {
0919       JButton button = (JButtoni.next();
0920       button.setBounds(    button.getX(),
0921                           button.getY() + offset,
0922                           button.getWidth(),
0923                           button.getHeight());
0924     // for loop through buttons
0925 
0926     for (Iterator k = lines.iterator(); k.hasNext()) {
0927       Coordinates coords = (Coordinatesk.next();
0928       coords.setY1(coords.getY1() + offset);
0929       coords.setY2(coords.getY2() + offset);
0930     }
0931   }// private void shiftButtonsDown(int offset)
0932 
0933   public void actionPerformed(ActionEvent e) {
0934 
0935     //check for the popup menu items
0936     if (e.getSource() instanceof JMenuItem) {
0937       JMenuItem menuItem = (JMenuIteme.getSource();
0938 
0939       // check if we're annotating a leaf
0940       // the popup label is set to leaves when the popup has been
0941       // constructed in showRightClickPopup
0942       if (popup.getLabel().equals("leaves")) {
0943         Integer id = new Integer(e.getActionCommand());
0944 
0945 //        clearSelection();
0946         JButton button = (JButtonbuttons.get(id);
0947         selection.add(button);
0948 
0949         STreeNode leaf = (STreeNodeleaves.get(id);
0950 
0951         // create parent with the same span as leaf
0952         // using createParentNode here is not a good idea coz it works only
0953         // for creating parents of non-terminal nodes, not leaves
0954         STreeNode parent = new STreeNode(leaf.getStart(), leaf.getEnd());
0955         parent.setLevel(leaf.getLevel()+1)//levels increase from bottom to top
0956         parent.add(leaf);
0957 
0958         // set the text
0959         parent.setUserObject(menuItem.getText());
0960 
0961         // last create the annotation; should always come last!
0962         parent.createAnnotation(  document,
0963                                   treeNodeAnnotationType,
0964                                   displayedString,
0965                                   utteranceStartOffset.longValue());
0966         nonTerminals.put(new Integer(parent.getID()), parent);
0967 
0968         // create new button positioned centrally above the leaf
0969         createCentralButton(parent);
0970 
0971         // add the necessary lines for drawing
0972         addLines(parent);
0973 
0974         clearSelection();
0975 
0976         // repaint the picture!
0977         this.repaint();
0978       // finished processing leaves
0979       else if (popup.getLabel().equals("non-terminal")) {
0980         // the action command is set to the id under which
0981         // the button can be found
0982         Integer id = new Integer(e.getActionCommand());
0983 
0984         //locate button from buttons hashMap and add to selection
0985         JButton button = (JButtonbuttons.get(id);
0986         selection.add(button);
0987 
0988         //create the new parent
0989         STreeNode parent = createParentNode(menuItem.getText());
0990 
0991         //add to nonTerminals HashMap
0992         nonTerminals.put(new Integer(parent.getID()), parent);
0993 
0994         //create new button positioned centrally above the leaf
0995         createCentralButton(parent);
0996 
0997         //add the necessary lines for drawing
0998         addLines(parent);
0999 
1000         clearSelection();
1001 
1002         //repaint the picture!
1003         this.repaint();
1004 
1005       //check for non-terminals
1006 
1007     //if statement for MenuItems
1008 
1009 
1010   }// public void actionPerformed(ActionEvent e)
1011 
1012   public void mouseClicked(MouseEvent e) {
1013 
1014     if ((e.getSource() instanceof JButton))
1015       return;
1016 
1017     JButton source = (JButtone.getSource();
1018 
1019     //check if CTRL or Shift is pressed and if not, clear the selection
1020     if (((e.isControlDown() || e.isShiftDown()))
1021          && SwingUtilities.isLeftMouseButton(e))
1022       clearSelection();
1023 
1024     //and select the current node
1025     if (SwingUtilities.isLeftMouseButton(e))
1026     //if (e.getModifiers() == e.BUTTON1_MASK)
1027       selectNode(e);
1028 
1029 
1030     //only repspond to right-clicks here by displaying the popup
1031     if (SwingUtilities.isRightMouseButton(e)) {
1032       //if button not in focus, grad the focus and select it!
1033       if source.getBackground() != selectedNodeColor ) {
1034         source.grabFocus();
1035         source.doClick();
1036         selectNode(e);
1037       }
1038       //Out.println(e.getComponent().getClass() + " right-clicked!");
1039       showRightClickPopup(e);
1040     //end of right-click processing
1041 
1042   }// public void mouseClicked(MouseEvent e)
1043 
1044   public void mousePressed(MouseEvent e) {
1045   }
1046 
1047   public void mouseReleased(MouseEvent e) {
1048   }
1049 
1050   public void mouseEntered(MouseEvent e) {
1051   }
1052 
1053   public void mouseExited(MouseEvent e) {
1054   // createButton4Node
1055 
1056 
1057   private void showRightClickPopup(MouseEvent e) {
1058 
1059     //that'll always work coz we checked it in MouseClicked.
1060     JButton source = (JButtone.getSource();
1061     Integer id = new Integer(source.getActionCommand());
1062 
1063     //check if it's a leaf and if so, offer the leaf annotation dialog
1064     Object obj = leaves.get(id);
1065     if (obj != null) {
1066       STreeNode leaf = (STreeNodeobj;
1067       //do nothing if it already has a parent
1068       if (leaf.getParent() != null) {
1069         clearSelection();
1070         JOptionPane.showMessageDialog(
1071           this,
1072           "Node already annotated. To delete the existing annotation, " +
1073           "select it and press <DEL>.",
1074           "Syntax Tree Viewer message",
1075           JOptionPane.INFORMATION_MESSAGE);
1076         return;
1077       }
1078 
1079       //reset the popup and set it's heading accordingly
1080       popup.setLabel("leaves");
1081       setMenuCommands(popup, ""+id);
1082 
1083       popup.pack();
1084       popup.show(source, e.getX(), e.getY());
1085     else //we have a non-terminal node
1086 
1087       //check if it has been annotated already
1088       if ( ((STreeNodenonTerminals.get(id)).getParent() != null) {
1089         clearSelection();
1090         JOptionPane.showMessageDialog(this, "Node already annotated. To delete"+
1091                           " the existing annotation, select it and press <DEL>.",
1092                           "Syntax Tree Viewer message",
1093                           JOptionPane.INFORMATION_MESSAGE);
1094         return;  //and do nothing if so!
1095       }
1096 
1097       popup.setLabel("non-terminal");
1098       setMenuCommands(popup, ""+id);
1099 
1100       popup.pack();
1101       popup.show(source, e.getX(), e.getY());
1102 
1103     }
1104 
1105   //showRightClickPopup
1106 
1107   private void addLines(STreeNode newNode) {
1108 
1109     JButton newButton = (JButtonbuttons.get(new Integer(newNode.getID()));
1110     int nbX = newButton.getX() + newButton.getWidth()/2;
1111     int nbY = newButton.getY() + newButton.getHeight();
1112 
1113     for (Iterator i = selection.iterator(); i.hasNext()) {
1114       JButton selButton = (JButtoni.next();
1115 
1116       //I create it a rect but it will in fact be used as x1, y1, x2, y2 for the
1117       //draw line. see drawLines.
1118       Coordinates coords = new Coordinates(
1119                                 nbX,
1120                                 nbY,
1121                                 selButton.getX() + selButton.getWidth()/2,
1122                                 selButton.getY());
1123 
1124       lines.add(coords);
1125     }
1126 
1127   // addLines
1128 
1129   private void clearSelection() {
1130     for (Enumeration enumeration = selection.elements(); enumeration.hasMoreElements()) {
1131       JButton selButton = (JButtonenumeration.nextElement();
1132       selButton.setBackground(buttonBackground);
1133     }
1134 
1135     selection.clear();
1136 
1137   //clearSlection
1138 
1139 
1140   private void fillCategoriesMenu() {
1141     boolean found = false;
1142 
1143     //fetch the valid categories from the stereotype
1144     CreoleRegister creoleReg = Gate.getCreoleRegister();
1145     java.util.List currentAnnotationSchemaList =
1146                       creoleReg.getLrInstances("gate.creole.AnnotationSchema");
1147     if (currentAnnotationSchemaList.isEmpty()) return;
1148 
1149     Iterator iter = currentAnnotationSchemaList.iterator();
1150     while (iter.hasNext()){
1151       AnnotationSchema annotSchema = (AnnotationSchemaiter.next();
1152       //we have found the right schema
1153       if (treeNodeAnnotationType.equals(annotSchema.getAnnotationName())) {
1154         found = true;
1155         FeatureSchema categories = annotSchema.getFeatureSchema(NODE_CAT_FEATURE_NAME);
1156         //iterate through all categories
1157         for (Iterator i =
1158                 categories.getPermittedValues().iterator(); i.hasNext()) {
1159 
1160           JMenuItem menuItem = new JMenuItem( (Stringi.next() );
1161           menuItem.addActionListener(this);
1162           popup.add(menuItem);
1163         //for
1164 
1165       //if
1166     }// while
1167 
1168     //if we don't have a schema, issue a warning
1169     if (! found)
1170       Out.println("Warning: You need to define an annotation schema for " +
1171                   treeNodeAnnotationType +
1172                   " in order to be able to add such annotations.");
1173 
1174   // fillCategoriesMenu
1175 
1176   /**
1177     * Sets the action commands of all menu items to the specified command
1178     */
1179   private void setMenuCommands(JPopupMenu menu, String command) {
1180     for (int i = 0; i < menu.getComponentCount() ; i++) {
1181       JMenuItem item = (JMenuItemmenu.getComponent(i);
1182       item.setActionCommand(command);
1183     }
1184 
1185   // setMenuCommands
1186 
1187   /**
1188     * Create a parent node for all selected non-terminal nodes
1189     */
1190   protected STreeNode createParentNode(String text) {
1191     STreeNode  parentNode = new STreeNode();
1192 
1193     long begin =  2147483647, end = 0, level= -1;
1194     for (Iterator i = selection.iterator(); i.hasNext()) {
1195       JButton button = (JButtoni.next();
1196       Integer id = new Integer(button.getActionCommand());
1197 
1198       STreeNode child = (STreeNodenonTerminals.get(id);
1199 
1200       if (begin > child.getStart())
1201         begin = child.getStart();
1202       if (end < child.getEnd())
1203         end = child.getEnd();
1204       if (level < child.getLevel())
1205         level = child.getLevel();
1206 
1207       parentNode.add(child);
1208 
1209     //for
1210 
1211     parentNode.setLevel(level+1);
1212     parentNode.setStart(begin);
1213     parentNode.setEnd(end);
1214     parentNode.setUserObject(text);
1215     parentNode.createAnnotation(document,
1216                                 treeNodeAnnotationType,
1217                                 displayedString,
1218                                 utteranceStartOffset.longValue());
1219 
1220 
1221     return parentNode;
1222   }
1223 
1224   /**
1225     * Create a parent node for all selected non-terminal nodes
1226     */
1227   protected STreeNode createParentNode(String text, Annotation annot) {
1228     STreeNode  parentNode = new STreeNode(annot);
1229 
1230     long level = -1;
1231     for (Iterator i = selection.iterator(); i.hasNext()) {
1232       JButton button = (JButtoni.next();
1233       Integer id = new Integer(button.getActionCommand());
1234 
1235       STreeNode child = (STreeNodenonTerminals.get(id);
1236 
1237       if (level < child.getLevel())
1238         level = child.getLevel();
1239 
1240       parentNode.add(child);
1241     //for
1242 
1243     parentNode.setLevel(level+1);
1244     parentNode.setUserObject(text);
1245 
1246     return parentNode;
1247   }
1248 
1249 
1250   void selectNode(MouseEvent e) {
1251     // try finding the node that's annotated, i.e., the selected button
1252     if (e.getSource() instanceof JButton) {
1253       JButton source = (JButtone.getSource();
1254 
1255         selection.add(source);
1256         buttonBackground = source.getBackground();
1257         source.setBackground(selectedNodeColor);
1258     }
1259   }
1260 
1261   // remove that node from the syntax tree
1262   void removeNode(JButton button) {
1263 
1264     Integer id = new Integer(button.getActionCommand());
1265     STreeNode node = (STreeNodenonTerminals.get(id);
1266     nonTerminals.remove(node);
1267     node.removeAnnotation(document);
1268 
1269     //fix the STreeNodes involved
1270     resetChildren(node);
1271     removeNodesAbove(node);
1272 
1273     //remove button from everywhere
1274     buttons.remove(button);
1275     button.setVisible(false);
1276     this.remove(button);
1277 
1278     //recalculate all lines
1279     recalculateLines();
1280 
1281     //make sure we clear the selection
1282     selection.clear();
1283     repaint();
1284   }
1285 
1286   //set parent node to null for all children of the given node
1287   private void resetChildren(STreeNode node) {
1288     for (Enumeration e = node.children(); e.hasMoreElements())
1289       ((STreeNodee.nextElement()).setParent(null);
1290 
1291     node.disconnectChildren();
1292   }
1293 
1294   private void removeNodesAbove(STreeNode node) {
1295     STreeNode parent = (STreeNodenode.getParent();
1296 
1297     while (parent != null) {
1298       Integer id = new Integer(parent.getID());
1299       parent.removeAnnotation(document);
1300       if (parent.isNodeChild(node))
1301         parent.remove(node);
1302       parent.disconnectChildren();
1303 
1304       nonTerminals.remove(id);
1305 
1306       JButton button = (JButtonbuttons.get(id);
1307       this.remove(button);
1308       buttons.remove(id);
1309 
1310       parent = (STreeNodeparent.getParent();
1311     }
1312   }
1313 
1314   private void recalculateLines() {
1315     lines.clear();
1316     //go through all non-terminals and recalculate their lines to their children
1317     for (Iterator i = nonTerminals.values().iterator(); i.hasNext())
1318       recalculateLines((STreeNodei.next());
1319 
1320   }
1321 
1322   /**
1323     * recalculates all lines from that node to all its children
1324     */
1325   private void recalculateLines(STreeNode node) {
1326     Integer id = new Integer(node.getID());
1327     JButton button = (JButtonbuttons.get(id);
1328 
1329     int bX = button.getX() + button.getWidth()/2;
1330     int bY = button.getY() + button.getHeight();
1331 
1332     for (Enumeration e = node.children(); e.hasMoreElements()) {
1333       STreeNode subNode = (STreeNodee.nextElement();
1334       Integer sid = new Integer(subNode.getID());
1335       JButton subButton = (JButtonbuttons.get(sid);
1336 
1337       Coordinates coords = new Coordinates(
1338                                 bX,
1339                                 bY,
1340                                 subButton.getX() + subButton.getWidth()/2,
1341                                 subButton.getY());
1342 
1343       lines.add(coords);
1344     }
1345 
1346   }
1347 
1348 /*
1349   // discontinued from use,done automatically instead, when the utterance is set
1350 
1351   public void setTreeAnnotations(AnnotationSet newTreeAnnotations) {
1352     AnnotationSet  oldTreeAnnotations = treeAnnotations;
1353     treeAnnotations = newTreeAnnotations;
1354     firePropertyChange("treeAnnotations", oldTreeAnnotations,
1355                           newTreeAnnotations);
1356   }
1357 */
1358 
1359   public void setTreeNodeAnnotationType(String newTreeNodeAnnotationType) {
1360     treeNodeAnnotationType = newTreeNodeAnnotationType;
1361   }
1362 
1363   public String getTreeNodeAnnotationType() {
1364     return treeNodeAnnotationType;
1365   }
1366 
1367   public void setTokenType(String newTokenType) {
1368     if (newTokenType != null && ! newTokenType.equals(""))
1369       tokenType = newTokenType;
1370   }
1371 
1372   public String getTokenType() {
1373     return tokenType;
1374   }
1375 
1376   void this_componentShown(ComponentEvent e) {
1377     Out.println("Tree Viewer shown");
1378   }
1379 
1380   void this_componentHidden(ComponentEvent e) {
1381     Out.println("Tree Viewer closes");
1382   }
1383 
1384 /*
1385   //None of this works, damn!!!
1386 
1387   public void setVisible(boolean b) {
1388     if (!b && this.isVisible())
1389       Out.println("Tree Viewer closes");
1390 
1391     super.setVisible( b);
1392   }
1393   public void hide() {
1394     Out.println("Tree Viewer closes");
1395     super.hide();
1396   }
1397 */
1398 
1399   private static class FocusButton extends JButton {
1400   
1401     public FocusButton(String text) {
1402       super(text);
1403     }
1404   
1405     public FocusButton() {
1406       super();
1407     }
1408   
1409     public FocusButton(Icon icon) {
1410       super(icon);
1411     }
1412   
1413     public FocusButton(String text, Icon icon) {
1414       super(text, icon);
1415     }// public FocusButton
1416     
1417   //  public boolean isManagingFocus() {
1418   //    return true;
1419   //  }// public boolean isManagingFocus()
1420   
1421     public void processComponentKeyEvent(KeyEvent e) {
1422       super.processComponentKeyEvent(e);
1423   
1424       //I need that cause I get all events here, so I only want to process
1425       //when it's a release event. The reason is that for keys like <DEL>
1426       //key_typed never happens
1427       if (e.getID() != KeyEvent.KEY_RELEASED)
1428         return;
1429   
1430       if (e.getKeyCode() == KeyEvent.VK_DELETE) {
1431         SyntaxTreeViewer viewer = (SyntaxTreeViewer) ((JButtone.getSource()).getParent();
1432         viewer.removeNode((JButtone.getSource());
1433       }
1434     }// public void processComponentKeyEvent(KeyEvent e)
1435   
1436   }
1437 }// class SyntaxTreeViewer
1438 
1439 
1440 
1441 // $Log$
1442 // Revision 1.28  2005/10/10 10:47:08  valyt
1443 // Converted FocusButton from a phantom class to a static innner class (to make the dependency checker's life easier)
1444 //
1445 // Revision 1.27  2005/01/11 13:51:34  ian
1446 // Updating copyrights to 1998-2005 in preparation for v3.0
1447 //
1448 // Revision 1.26  2004/07/26 14:59:32  valyt
1449 // "Made in Sheffield" sources are now JDK 1.5 safe (by renaming enum to enumeration).
1450 // There are still problems with Java sources generated by JavaCC
1451 //
1452 // Revision 1.25  2004/07/21 17:10:07  akshay
1453 // Changed copyright from 1998-2001 to 1998-2004
1454 //
1455 // Revision 1.24  2004/03/25 13:01:05  valyt
1456 // Imports optimisation throughout the Java sources
1457 // (to get rid of annoying warnings in Eclipse)
1458 //
1459 // Revision 1.23  2003/08/27 15:53:03  valyt
1460 //
1461 // removed deprecation warning
1462 //
1463 // Revision 1.22  2003/01/28 10:01:16  marin
1464 // [marin] bugfixes from Kali
1465 //
1466 // Revision 1.21  2002/03/06 17:15:46  kalina
1467 // Reorganised the source code, so that it now uses constants from
1468 // ANNIEConstants, GateConstants and parameter constants defined on each PR.
1469 // Read e-mail to the gate list for an explanation.
1470 //
1471 // Revision 1.20  2001/08/08 16:14:26  kalina
1472 // A minor change to the tree viewer.
1473 //
1474 // Revision 1.19  2001/08/08 14:39:00  kalina
1475 // Made the dialog to size itself maximum as much as the screen, coz was
1476 // getting too big without that.
1477 //
1478 // Some documentation on Tree Viewer and some small changes to utterance2trees()
1479 // to make it order the tokens correctly by offset
1480 //
1481 // Revision 1.18  2001/08/07 19:03:05  kalina
1482 // Made the tree viewer use Token annotations to break the sentence for annotation
1483 //
1484 // Revision 1.17  2001/08/07 17:01:32  kalina
1485 // Changed the AVR implementing classes in line with the updated AVR
1486 // API (cancelAction() and setSpan new parameter).
1487 //
1488 // Also updated the TreeViewer, so now it can be used to edit and view
1489 // Sentence annotations and the SyntaxTreeNodes associated with them.
1490 // So if you have trees, it'll show them, if not, it'll help you build them.
1491 //
1492 // Revision 1.16  2001/04/09 10:36:36  oana
1493 // a few changes in the code style
1494 //
1495 // Revision 1.14  2000/12/04 12:29:29  valyt
1496 // Done some work on the visual resources
1497 // Added the smart XJTable
1498 //
1499 // Revision 1.13  2000/11/08 16:35:00  hamish
1500 // formatting
1501 //
1502 // Revision 1.12  2000/10/26 10:45:26  oana
1503 // Modified in the code style
1504 //
1505 // Revision 1.11  2000/10/24 10:10:18  valyt
1506 // Fixed the deprecation warning in gate/gui/SyntaxTreeViewer.java
1507 //
1508 // Revision 1.10  2000/10/18 13:26:47  hamish
1509 // Factory.createResource now working, with a utility method that uses reflection (via java.beans.Introspector) to set properties on a resource from the
1510 //     parameter list fed to createResource.
1511 //     resources may now have both an interface and a class; they are indexed by interface type; the class is used to instantiate them
1512 //     moved createResource from CR to Factory
1513 //     removed Transients; use Factory instead
1514 //
1515 // Revision 1.9  2000/10/16 16:44:32  oana
1516 // Changed the comment of DEBUG variable
1517 //
1518 // Revision 1.8  2000/10/10 15:36:35  oana
1519 // Changed System.out in Out and System.err in Err;
1520 // Added the DEBUG variable seted on false;
1521 // Added in the header the licence;
1522 //
1523 // Revision 1.7  2000/10/10 09:49:57  valyt
1524 // Fixed the Annotation test
1525 //
1526 // Revision 1.6  2000/10/02 12:34:06  valyt
1527 // Added the UnicodeEnabled switch on gate.util.Tools
1528 //
1529 // Revision 1.5  2000/09/28 14:26:09  kalina
1530 // Added even more documentation (is this me?!) and allowed several tokens to be
1531 // passed instead of a whole utterance/sentence for annotation. Needs good testing this
1532 // but will do it when somebody tries using this functionality.
1533 //
1534 // Revision 1.4  2000/09/28 13:16:12  kalina
1535 // Added some documentation
1536 //
1537 // Revision 1.3  2000/09/21 14:23:45  kalina
1538 // Fixed some small bug in main(). To test just run the component itself.
1539 //
1540 // Revision 1.2  2000/09/21 14:17:27  kalina
1541 // Added Unicode support
1542 //
1543 // Revision 1.1  2000/09/20 17:03:37  kalina
1544 // Added the tree viewer from the prototype. It works now with the new annotation API.