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