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 (600, 400));
0237 this.setSize(600, 400);
0238 this.setBounds(0, 0, 600, 400);
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 == null) return;
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 == null) return 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.paintComponent( g);
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 = (Coordinates) i.next();
0488
0489 g.drawLine( coords.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 == null) return;
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 = (Annotation) i.next();
0573
0574 java.util.List children =
0575 (java.util.List) annot.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 = (JButton) buttons.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 = (Annotation) i1.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, (int) getHeight()- (int) getVisibleRect().getHeight(),
0619 (int) getVisibleRect().getWidth(), (int) getVisibleRect().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.List) annot.getFeatures().get(NODE_CONSISTS_FEATURE_NAME);
0627
0628 for (Iterator i = children.iterator(); i.hasNext(); ) {
0629 Integer childId = (Integer) i.next();
0630 Annotation child = treeAnnotations.get(childId);
0631 JButton childButton;
0632
0633 if (processed.containsKey(child.getId()))
0634 childButton = (JButton) processed.get(child.getId());
0635 else
0636 childButton = processChildrenAnnots(child, processed);
0637
0638 childrenButtons.add(childButton);
0639 }
0640
0641 selection = (Vector) childrenButtons.clone();
0642 STreeNode parent = createParentNode(
0643 (String) annot.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 = (STreeNode) i.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 = (Annotation) tokens.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((String) node.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((String) newNode.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 =0 , top = this.getHeight();
0874
0875 // determine the left, right, top
0876 for (Iterator i = selection.iterator(); i.hasNext(); ) {
0877 JButton childButton = (JButton) i.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) /2 - 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 = (JButton) i.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 = (Coordinates) k.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 = (JMenuItem) e.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 = (JButton) buttons.get(id);
0947 selection.add(button);
0948
0949 STreeNode leaf = (STreeNode) leaves.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 = (JButton) buttons.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 = (JButton) e.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 = (JButton) e.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 = (STreeNode) obj;
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 ( ((STreeNode) nonTerminals.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 = (JButton) buttons.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 = (JButton) i.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 = (JButton) enumeration.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 = (AnnotationSchema) iter.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( (String) i.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 = (JMenuItem) menu.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 = (JButton) i.next();
1196 Integer id = new Integer(button.getActionCommand());
1197
1198 STreeNode child = (STreeNode) nonTerminals.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 = (JButton) i.next();
1233 Integer id = new Integer(button.getActionCommand());
1234
1235 STreeNode child = (STreeNode) nonTerminals.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 = (JButton) e.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 = (STreeNode) nonTerminals.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 ((STreeNode) e.nextElement()).setParent(null);
1290
1291 node.disconnectChildren();
1292 }
1293
1294 private void removeNodesAbove(STreeNode node) {
1295 STreeNode parent = (STreeNode) node.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 = (JButton) buttons.get(id);
1307 this.remove(button);
1308 buttons.remove(id);
1309
1310 parent = (STreeNode) parent.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((STreeNode) i.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 = (JButton) buttons.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 = (STreeNode) e.nextElement();
1334 Integer sid = new Integer(subNode.getID());
1335 JButton subButton = (JButton) buttons.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) ((JButton) e.getSource()).getParent();
1432 viewer.removeNode((JButton) e.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.
|