1   /*  UnrestrictedAnnotationEditor.java
2    *
3    *  Copyright (c) 1998-2001, The University of Sheffield.
4    *
5    *  This file is part of GATE (see http://gate.ac.uk/), and is free
6    *  software, licenced under the GNU Library General Public License,
7    *  Version 2, June 1991 (in the distribution as file licence.html,
8    *  and also available at http://gate.ac.uk/gate/licence.html).
9    *
10   *  Cristian URSU,  13/July/2001
11   *
12   *  $Id: UnrestrictedAnnotationEditor.java,v 1.5 2002/02/27 17:01:24 valyt Exp $
13   *
14   */
15  
16  package gate.gui;
17  
18  import java.awt.Frame;
19  import java.awt.BorderLayout;
20  import java.awt.Component;
21  import java.awt.event.*;
22  import javax.swing.*;
23  import javax.swing.table.*;
24  
25  import java.util.*;
26  import java.lang.reflect.*;
27  import java.net.*;
28  
29  import gate.*;
30  import gate.annotation.*;
31  import gate.util.*;
32  import gate.creole.*;
33  
34  /** This class visually adds/edits features and annot type of an annotation
35    * It does this without using an {@link gate.creole.AnnotationSchema}.
36    * The user can manipulate annotation and features at his own will.
37    * It's his responsability.
38    */
39  public class UnrestrictedAnnotationEditor extends AbstractVisualResource
40                                            implements AnnotationVisualResource,
41                                                       ResizableVisualResource{
42  
43    /** Default constructor*/
44    public UnrestrictedAnnotationEditor() {}
45  
46    // Methods required by AnnotationVisualResource
47  
48    /**
49      * Called by the GUI when this viewer/editor has to initialise itself for a
50      * specific annotation or text span.
51      * @param target the object which will always be a {@link gate.AnnotationSet}
52      */
53    public void setTarget(Object target){
54      currentAnnotSet = (AnnotationSet) target;
55    }// setTarget();
56  
57    /**
58      * Used when the viewer/editor has to display/edit an existing annotation
59      * @param ann the annotation to be displayed or edited. If ann is null then
60      * the method simply returns
61      */
62    public void setAnnotation(Annotation ann){
63      // If ann is null, then simply return.
64      if (ann == null) return;
65      currentAnnot = ann;
66      currentStartOffset = currentAnnot.getStartNode().getOffset();
67      currentEndOffset = currentAnnot.getEndNode().getOffset();
68  
69      initLocalData();
70      initGuiComponents();
71  
72    }// setAnnotation();
73  
74    /**
75      * Used when the viewer has to create new annotations.
76      * @param startOffset the start offset of the span covered by the new
77      * annotation(s). If is <b>null</b> the method will simply return.
78      * @param endOffset the end offset of the span covered by the new
79      * annotation(s). If is <b>null</b> the method will simply return.
80      */
81    public void setSpan(Long startOffset, Long endOffset, String annotationType){
82      // If one of them is null, then simply return.
83      if (startOffset == null || endOffset == null) return;
84  
85      currentStartOffset = startOffset;
86      currentEndOffset = endOffset;
87      currentAnnot = null;
88  
89      initLocalData();
90      initGuiComponents();
91    }// setSpan();
92  
93    /**
94     * Called by the GUI when the user has pressed the "OK" button. This should
95     * trigger the saving of the newly created annotation(s)
96     */
97    public void okAction() throws GateException {
98      if (annotTypeTextField.getText().equals("")){
99        throw new GateException("An annotation type must be specified !");
100     }// End if
101     // This code must be uncomented if the desired behaviour for
102     // UnrestrictedAnnoatationEditor is not to allow annotation types
103     // which have a schema present in the system.
104 /*
105     CreoleRegister creoleReg = Gate.getCreoleRegister();
106     List currentAnnotationSchemaList =
107                       creoleReg.getLrInstances("gate.creole.AnnotationSchema");
108     Iterator iter = currentAnnotationSchemaList.iterator();
109     while (iter.hasNext()){
110       AnnotationSchema annotSchema = (AnnotationSchema) iter.next();
111       if (annotTypeTextField.getText().equals(annotSchema.getAnnotationName()))
112         throw new GAteException("There is a schema type for this annotation");
113     }// End while
114 */
115     data.setAnnotType(annotTypeTextField.getText());
116     if (currentAnnot == null){
117       currentAnnotSet.add( currentStartOffset,
118                            currentEndOffset,
119                            this.getAnnotType(),
120                            this.getCurrentAnnotationFeatures());
121     }else{
122       if (currentAnnot.getType().equals(this.getAnnotType())){
123         currentAnnot.setFeatures(this.getCurrentAnnotationFeatures());
124       }else{
125         currentAnnotSet.remove(currentAnnot);
126         currentAnnotSet.add( currentStartOffset,
127                              currentEndOffset,
128                              this.getAnnotType(),
129                              this.getCurrentAnnotationFeatures());
130       }// End if
131     }// End if
132   }//okAction();
133 
134 
135   public void cancelAction() throws GateException {
136     //no need to do anything, because the editor has not modified anything
137     //on the document or the annotation sets
138     //Had to be added for the tree editor, which does
139     return;
140   }
141 
142   /**
143     * Checks whether this viewer/editor can handle a specific annotation type.
144     * @param annotationType represents the annotation type being questioned.If
145     * it is <b>null</b> then the method will return false.
146     * @return true if the SchemaAnnotationEditor can handle the annotationType
147     * or false otherwise.
148     */
149   public boolean canDisplayAnnotationType(String annotationType){
150     return true;
151   }// canDisplayAnnotationType();
152 
153   // The Unrestricted Editor functionality
154   // Local data
155 
156   /** The curent annotation set used by the editor*/
157   AnnotationSet currentAnnotSet = null;
158   /** The curent annotation used by the editor*/
159   Annotation currentAnnot = null;
160   /** The start offset of the span covered by the currentAnnot*/
161   Long currentStartOffset = null;
162   /** The end offset of the span covered by the currentAnnot*/
163   Long currentEndOffset = null;
164 
165   // Local data
166   private MyCustomFeatureBearer data = null;
167 
168   // Gui Components
169   JLabel annotTypeLabel = null;
170   JTextField annotTypeTextField = null;
171 
172   JLabel featuresLabel = null;
173   FeaturesEditor  featuresEditor = null;
174 
175   /** Init local data*/
176   protected void initLocalData(){
177     data = new MyCustomFeatureBearer(currentAnnot);
178   }// initLocalData();
179 
180   /** Init GUI components with values taken from local data*/
181   protected void initGuiComponents(){
182     this.setLayout(new BoxLayout( this, BoxLayout.Y_AXIS));
183     //create the main box
184     Box componentsBox = Box.createVerticalBox();
185 
186     componentsBox.add(Box.createVerticalStrut(10));
187 
188     // Add the Annot Type
189     Box box = Box.createVerticalBox();
190     Box box1 = Box.createHorizontalBox();
191     annotTypeLabel = new JLabel("Annotation type");
192     annotTypeLabel.setToolTipText("The type of the annotation you are" +
193                                                     " creating or editing");
194     annotTypeLabel.setOpaque(true);
195 
196     box1.add(annotTypeLabel);
197     box1.add(Box.createHorizontalGlue());
198     box.add(box1);
199 
200     annotTypeTextField = new JTextField(data.getAnnotType());
201     annotTypeTextField.setColumns(80);
202     annotTypeTextField.setPreferredSize(
203                                   annotTypeTextField.getPreferredSize());
204     annotTypeTextField.setMinimumSize(
205                                   annotTypeTextField.getPreferredSize());
206     annotTypeTextField.setMaximumSize(
207                                   annotTypeTextField.getPreferredSize());
208 
209 
210     box1 = Box.createHorizontalBox();
211     box1.add(annotTypeTextField);
212     box1.add(Box.createHorizontalGlue());
213     box.add(box1);
214     box.add(Box.createVerticalStrut(10));
215 
216     componentsBox.add(box);
217     // add the features editor
218     box = Box.createVerticalBox();
219 
220     featuresLabel = new JLabel("Features");
221     featuresLabel.setToolTipText("The features of the annotation you are" +
222                                                     " creating or editing");
223     featuresLabel.setOpaque(true);
224 
225     box1 = Box.createHorizontalBox();
226     box1.add(featuresLabel);
227     box1.add(Box.createHorizontalGlue());
228     box.add(box1);
229     box.add(Box.createVerticalStrut(5));
230 
231     featuresEditor = new FeaturesEditor();
232     featuresEditor.setFeatureBearer(data);
233 
234     box.add(featuresEditor);
235     box.add(Box.createVerticalStrut(10));
236 
237     componentsBox.add(box);
238     componentsBox.add(Box.createVerticalStrut(10));
239 
240     this.add(componentsBox);
241     this.add(Box.createVerticalStrut(10));
242   }//initGuiComponents()
243 
244   /** Init all the listeners*/
245   protected void initListeners(){
246   }//initListeners()
247 
248   /** Returns annot type edited with this tool*/
249   public String getAnnotType(){ return data.getAnnotType();}
250 
251   /** Returns the features edited with this tool*/
252   protected FeatureMap getCurrentAnnotationFeatures(){ return data.getFeatures();}
253 
254   // INNER CLASS
255   /** This class implements a feature bearer. It is used as internal data.
256     * The FeatureEditor will use an object belonging to this class.
257     */
258   class MyCustomFeatureBearer extends AbstractFeatureBearer
259                                                     implements FeatureBearer{
260 
261     // Members
262     private FeatureMap features = null;
263     private String annotType = null;
264 
265     /** Constructs a custom feature bearer. If annot is null then it creates
266       * empty annotType and fetures.
267       */
268     public MyCustomFeatureBearer(Annotation anAnnot){
269       if (anAnnot != null){
270         features = Factory.newFeatureMap();
271         features.putAll(anAnnot.getFeatures());
272         annotType = new String(anAnnot.getType());
273       }else{
274         features = Factory.newFeatureMap();
275         annotType = new String("");
276       }// End if
277     }//MyCustomFeatureBearer
278 
279     // Mutators and accesors
280     public void setFeatures(FeatureMap aFeatureMap){
281       features = aFeatureMap;
282     }// setFeatures();
283 
284     public FeatureMap getFeatures(){
285       return features;
286     }// getFeatures()
287 
288     public void setAnnotType(String anAnnotType){
289       annotType = anAnnotType;
290     }// setAnnotType();
291 
292     public String getAnnotType(){
293       return annotType;
294     }//getAnnotType()
295   }// End class MyCustomFeatureBearer
296 }// End class UnrestrictedAnnotationEditor