1   /*
2    * Created on Mar 23, 2004
3    *
4    * To change the template for this generated file go to
5    * Window - Preferences - Java - Code Generation - Code and Comments
6    */
7   package gate.gui.docview;
8   
9   import java.awt.*;
10  import java.awt.Color;
11  import java.awt.Component;
12  import java.awt.event.*;
13  import java.awt.event.ActionEvent;
14  import java.awt.event.ActionListener;
15  import java.io.*;
16  import java.util.*;
17  import java.util.List;
18  import java.util.prefs.Preferences;
19  
20  import javax.swing.*;
21  import javax.swing.JScrollPane;
22  import javax.swing.JTable;
23  import javax.swing.border.Border;
24  import javax.swing.event.*;
25  import javax.swing.event.MouseInputListener;
26  import javax.swing.event.PopupMenuListener;
27  import javax.swing.table.*;
28  import javax.swing.table.AbstractTableModel;
29  import javax.swing.table.TableCellRenderer;
30  import javax.swing.text.*;
31  import javax.swing.text.BadLocationException;
32  
33  import gate.*;
34  import gate.Annotation;
35  import gate.AnnotationSet;
36  import gate.event.*;
37  import gate.event.AnnotationSetEvent;
38  import gate.event.AnnotationSetListener;
39  import gate.event.DocumentEvent;
40  import gate.event.DocumentListener;
41  import gate.gui.*;
42  import gate.gui.MainFrame;
43  import gate.swing.ColorGenerator;
44  import gate.swing.XJTable;
45  import gate.util.*;
46  import gate.util.GateRuntimeException;
47  import gate.util.InvalidOffsetException;
48  
49  /**
50   * @author valyt
51   *
52   * To change the template for this generated type comment go to
53   * Window - Preferences - Java - Code Generation - Code and Comments
54   */
55  public class AnnotationSetsView extends AbstractDocumentView 
56                              implements DocumentListener,
57                                         AnnotationSetListener{
58  
59    
60    public AnnotationSetsView(){
61      setHandlers = new ArrayList();
62      tableRows = new ArrayList();
63      colourGenerator = new ColorGenerator();
64      actions = new ArrayList();
65      actions.add(new SavePreserveFormatAction());
66    }
67    
68    public List getActions() {
69      return actions;
70    }  
71  
72    /* (non-Javadoc)
73     * @see gate.gui.docview.DocumentView#getType()
74     */
75    public int getType() {
76      return VERTICAL;
77    }
78    
79    protected void initGUI() {
80      //get a pointer to the textual view used for highlights
81      Iterator centralViewsIter = owner.getCentralViews().iterator();
82      while(textView == null && centralViewsIter.hasNext()){
83        DocumentView aView = (DocumentView)centralViewsIter.next();
84        if(aView instanceof TextualDocumentView) 
85          textView = (TextualDocumentView)aView;
86      }
87      textPane = (JEditorPane)((JScrollPane)textView.getGUI())
88              .getViewport().getView();
89      
90      //get a pointer to the list view
91      Iterator horizontalViewsIter = owner.getHorizontalViews().iterator();
92      while(listView == null && horizontalViewsIter.hasNext()){
93        DocumentView aView = (DocumentView)horizontalViewsIter.next();
94        if(aView instanceof AnnotationListView) 
95          listView = (AnnotationListView)aView;
96      }
97      
98      
99      setHandlers.add(new SetHandler(document.getAnnotations()));
100     List setNames = document.getNamedAnnotationSets() == null ?
101             new ArrayList() :
102             new ArrayList(document.getNamedAnnotationSets().keySet());
103     Collections.sort(setNames);
104     Iterator setsIter = setNames.iterator();
105     while(setsIter.hasNext()){
106       setHandlers.add(new SetHandler(document.
107               getAnnotations((String)setsIter.next())));
108     }
109     tableRows.addAll(setHandlers);
110     mainTable = new XJTable();
111     tableModel = new SetsTableModel();
112     ((XJTable)mainTable).setSortable(false);
113     mainTable.setModel(tableModel);
114 //    mainTable.setRowMargin(0);
115 //    mainTable.getColumnModel().setColumnMargin(0);
116     SetsTableCellRenderer cellRenderer = new SetsTableCellRenderer();
117     mainTable.getColumnModel().getColumn(NAME_COL).setCellRenderer(cellRenderer);
118     mainTable.getColumnModel().getColumn(SELECTED_COL).setCellRenderer(cellRenderer);
119     SetsTableCellEditor cellEditor = new SetsTableCellEditor();
120     mainTable.getColumnModel().getColumn(SELECTED_COL).setCellEditor(cellEditor);
121     mainTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
122     mainTable.setColumnSelectionAllowed(false);
123     mainTable.setRowSelectionAllowed(true);
124     
125     mainTable.setTableHeader(null);
126     mainTable.setShowGrid(false);
127     mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
128     
129     scroller = new JScrollPane(mainTable);
130     scroller.getViewport().setOpaque(true);
131     scroller.getViewport().setBackground(mainTable.getBackground());
132     
133     annotationEditor = new AnnotationEditor(textView, this);
134     
135     mainPanel = new JPanel();
136     mainPanel.setLayout(new GridBagLayout());
137     GridBagConstraints constraints = new GridBagConstraints();
138     
139     constraints.gridy = 0;
140     constraints.gridx = GridBagConstraints.RELATIVE;
141     constraints.gridwidth = 2;
142     constraints.weighty = 1;
143     constraints.weightx = 1;
144     constraints.fill = GridBagConstraints.BOTH;
145     mainPanel.add(scroller, constraints);
146     
147     constraints.gridy = 1;
148     constraints.gridwidth = 1;
149     constraints.weighty = 0;
150     newSetNameTextField = new JTextField();
151     mainPanel.add(newSetNameTextField, constraints);
152     constraints.weightx = 0;
153     newSetAction = new NewAnnotationSetAction();
154     mainPanel.add(new JButton(newSetAction), constraints);
155     initListeners();
156   }
157   
158   public Component getGUI(){
159     return mainPanel;
160   }
161 
162   protected Color getColor(String annotationType){
163     Preferences prefRoot = Preferences.userNodeForPackage(getClass());
164     int rgba = prefRoot.getInt(annotationType, -1);
165     Color colour;
166     if(rgba == -1){
167       //initialise and save
168       float components[] = colourGenerator.getNextColor().getComponents(null);
169       colour = new Color(components[0],
170                          components[1],
171                          components[2],
172                          0.5f);
173       int rgb = colour.getRGB();
174       int alpha = colour.getAlpha();
175       rgba = rgb | (alpha << 24);
176       prefRoot.putInt(annotationType, rgba);
177     }else{
178       colour = new Color(rgba, true);
179     }
180     return colour;
181   }
182   
183   protected void saveColor(String annotationType, Color colour){
184     Preferences prefRoot = Preferences.userNodeForPackage(getClass());
185     int rgb = colour.getRGB();
186     int alpha = colour.getAlpha();
187     int rgba = rgb | (alpha << 24);
188     prefRoot.putInt(annotationType, rgba);
189   }
190   
191   /**
192    * This method will be called whenever the view becomes active. Implementers 
193    * should use this to add hooks (such as mouse listeners) to the other views
194    * as required by their functionality. 
195    */
196   protected void registerHooks(){
197     textPane.addMouseListener(textMouseListener);
198     textPane.addMouseMotionListener(textMouseListener);
199     textPane.addAncestorListener(textAncestorListener);
200   }
201 
202   /**
203    * This method will be called whenever this view becomes inactive. 
204    * Implementers should use it to unregister whatever hooks they registered
205    * in {@link #registerHooks()}.
206    *
207    */
208   protected void unregisterHooks(){
209     textPane.removeMouseListener(textMouseListener);
210     textPane.removeMouseMotionListener(textMouseListener);
211     textPane.removeAncestorListener(textAncestorListener);
212   }
213   
214   
215   protected void initListeners(){
216     document.addDocumentListener(this);
217     mainTable.addComponentListener(new ComponentAdapter(){
218       public void componentResized(ComponentEvent e){
219         //trigger a resize for the columns
220         mainTable.adjustSizes();
221 //        tableModel.fireTableRowsUpdated(0, 0);
222       }
223     });
224     
225     mainTable.addMouseListener(new MouseAdapter(){
226       public void mouseClicked(MouseEvent evt){
227         int row =  mainTable.rowAtPoint(evt.getPoint());
228         int column = mainTable.columnAtPoint(evt.getPoint());
229         if(row >= 0 && column == NAME_COL){
230           Object handler = tableRows.get(row);
231           if(handler instanceof TypeHandler){
232             TypeHandler tHandler = (TypeHandler)handler;
233             if(evt.getClickCount() >= 2){
234               //double click
235               tHandler.changeColourAction.actionPerformed(null);
236             }
237           }
238         }
239       }
240       public void mousePressed(MouseEvent evt){
241         int row =  mainTable.rowAtPoint(evt.getPoint());
242         int column = mainTable.columnAtPoint(evt.getPoint());
243         if(row >= 0 && column == NAME_COL){
244           Object handler = tableRows.get(row);
245           if(handler instanceof TypeHandler){
246             TypeHandler tHandler = (TypeHandler)handler;
247             if(evt.isPopupTrigger()){
248               //show popup
249               JPopupMenu popup = new JPopupMenu();
250               popup.add(tHandler.changeColourAction);
251               popup.show(mainTable, evt.getX(), evt.getY());
252             }
253           }
254         }
255       }
256       
257       public void mouseReleased(MouseEvent evt){
258         int row =  mainTable.rowAtPoint(evt.getPoint());
259         int column = mainTable.columnAtPoint(evt.getPoint());
260         if(row >= 0 && column == NAME_COL){
261           Object handler = tableRows.get(row);
262           if(handler instanceof TypeHandler){
263             TypeHandler tHandler = (TypeHandler)handler;
264             if(evt.isPopupTrigger()){
265               //show popup
266               JPopupMenu popup = new JPopupMenu();
267               popup.add(tHandler.changeColourAction);
268               popup.show(mainTable, evt.getX(), evt.getY());
269             }
270           }
271         }
272       }
273     });
274     
275     
276     mouseStoppedMovingAction = new MouseStoppedMovingAction();
277     mouseMovementTimer = new javax.swing.Timer(MOUSE_MOVEMENT_TIMER_DELAY, 
278             mouseStoppedMovingAction);
279     mouseMovementTimer.setRepeats(false);
280     textMouseListener = new TextMouseListener();
281     textAncestorListener = new AncestorListener(){
282       public void ancestorAdded(AncestorEvent event){
283         if(wasShowing) annotationEditor.show(false);
284         wasShowing = false;
285       }
286       
287       public void ancestorRemoved(AncestorEvent event){
288         if(annotationEditor.isShowing()){
289           wasShowing = true;
290           annotationEditor.hide();
291         }
292       }
293       
294       public void ancestorMoved(AncestorEvent event){
295         
296       }
297       private boolean wasShowing = false; 
298     };
299     
300     mainTable.getInputMap().put(
301             KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "deleteAll");
302     mainTable.getActionMap().put("deleteAll", 
303             new DeleteSelectedAnnotationGroupAction());
304     newSetNameTextField.getInputMap().put(
305             KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "newSet");
306     newSetNameTextField.getActionMap().put("newSet", newSetAction);
307   }
308     
309   
310   /* (non-Javadoc)
311    * @see gate.Resource#cleanup()
312    */
313   public void cleanup() {
314     document.removeDocumentListener(this);
315     super.cleanup();
316   }
317   
318   public void annotationSetAdded(DocumentEvent e) {
319     String newSetName = e.getAnnotationSetName();
320     SetHandler sHandler = new SetHandler(document.getAnnotations(newSetName));
321     //find the right location for the new set
322     //this is a named set and the first one is always the default one
323     int i = 1;
324     for(;
325         i < setHandlers.size() && 
326         ((SetHandler)setHandlers.get(i)).set.
327           getName().compareTo(newSetName) <= 0;
328         i++);
329     setHandlers.add(i, sHandler);
330     //update the tableRows list
331     SetHandler previousHandler = (SetHandler)setHandlers.get(i -1);
332     //find the index for the previous handler - which is guaranteed to exist
333     int j = 0;
334     for(;
335       tableRows.get(j) != previousHandler;
336       j++);
337     if(previousHandler.isExpanded()){
338       j += previousHandler.typeHandlers.size();
339     }
340     j++;
341     tableRows.add(j, sHandler);
342     //update the table view
343     tableModel.fireTableRowsInserted(j, j);
344   }//public void annotationSetAdded(DocumentEvent e) 
345   
346   public void annotationSetRemoved(DocumentEvent e) {
347     String setName = e.getAnnotationSetName();
348     //find the handler and remove it from the list of handlers
349 //    Iterator shIter = setHandlers.iterator();
350     SetHandler sHandler = getSetHandler(setName);
351     if(sHandler != null){
352       //remove highlights if any
353       Iterator typeIter = sHandler.typeHandlers.iterator();
354       while(typeIter.hasNext()){
355         TypeHandler tHandler = (TypeHandler)typeIter.next();
356         tHandler.setSelected(false);
357       }
358       setHandlers.remove(sHandler);
359       //remove the set from the table
360       int row = tableRows.indexOf(sHandler);
361       tableRows.remove(row);
362       int removed = 1;
363       //remove the type rows as well
364       if(sHandler.isExpanded())
365         for(int i = 0; i < sHandler.typeHandlers.size(); i++){ 
366           tableRows.remove(row);
367           removed++;
368         }
369       tableModel.fireTableRowsDeleted(row, row + removed -1);
370       sHandler.cleanup();
371     }
372   }//public void annotationSetRemoved(DocumentEvent e) 
373   
374   /**Called when the content of the document has changed through an edit 
375    * operation.
376    */
377   public void contentEdited(DocumentEvent e){
378     //go through all the type handlers and propagate the event
379     Iterator setIter = setHandlers.iterator();
380     while(setIter.hasNext()){
381       SetHandler sHandler = (SetHandler)setIter.next();
382       Iterator typeIter = sHandler.typeHandlers.iterator();
383       while(typeIter.hasNext()){
384         TypeHandler tHandler = (TypeHandler)typeIter.next();
385         if(tHandler.isSelected()) 
386           tHandler.repairHighlights(e.getEditStart().intValue(), 
387                   e.getEditEnd().intValue());
388       }
389     }
390   }
391   
392   
393   public void annotationAdded(AnnotationSetEvent e) {
394     AnnotationSet set = (AnnotationSet)e.getSource();
395     Annotation ann = e.getAnnotation();
396     TypeHandler tHandler = getTypeHandler(set.getName(), ann.getType());
397     if(tHandler == null){
398       //new type for this set
399       SetHandler sHandler = getSetHandler(set.getName());
400       tHandler = sHandler.newType(ann.getType());
401     }
402     tHandler.annotationAdded(ann);
403   }
404   
405   public void annotationRemoved(AnnotationSetEvent e) {
406     AnnotationSet set = (AnnotationSet)e.getSource();
407     Annotation ann = e.getAnnotation();
408     TypeHandler tHandler = getTypeHandler(set.getName(), ann.getType());
409     tHandler.annotationRemoved(ann);
410   }
411   
412   protected SetHandler getSetHandler(String name){
413     Iterator shIter = setHandlers.iterator();
414     while(shIter.hasNext()){
415       SetHandler sHandler = (SetHandler)shIter.next();
416       if(name == null){
417         if(sHandler.set.getName() == null) return sHandler;
418       }else{
419         if(name.equals(sHandler.set.getName())) return sHandler;
420       }
421     }
422     return null;
423   }
424   
425   protected TypeHandler getTypeHandler(String set, String type){
426     SetHandler sHandler = getSetHandler(set);
427     TypeHandler tHandler = null;
428     Iterator typeIter = sHandler.typeHandlers.iterator();
429     while(tHandler == null && typeIter.hasNext()){
430       TypeHandler aHandler = (TypeHandler)typeIter.next();
431       if(aHandler.name.equals(type)) tHandler = aHandler;
432     }
433     return tHandler;
434   }
435   
436   public void setTypeSelected(final String setName, 
437                               final String typeName, 
438                               final boolean selected){
439     
440     SwingUtilities.invokeLater(new Runnable(){
441       public void run(){
442         TypeHandler tHandler = getTypeHandler(setName, typeName);
443         tHandler.setSelected(selected);
444         int row = tableRows.indexOf(tHandler);
445         tableModel.fireTableRowsUpdated(row, row);
446         mainTable.getSelectionModel().setSelectionInterval(row, row);
447       }
448     });
449   }
450   
451   /**
452    * Sets the last annotation type created (which will be used as a default
453    * for creating new annotations).
454    * @param annType the type of annotation.
455    */
456   void setLastAnnotationType(String annType){
457     this.lastAnnotationType = annType;
458   }
459   
460   protected class SetsTableModel extends AbstractTableModel{
461     public int getRowCount(){
462       return tableRows.size();
463 //      //we have at least one row per set
464 //      int rows = setHandlers.size();
465 //      //expanded sets add rows
466 //      for(int i =0; i < setHandlers.size(); i++){
467 //        SetHandler sHandler = (SetHandler)setHandlers.get(i);
468 //        rows += sHandler.expanded ? sHandler.set.getAllTypes().size() : 0;
469 //      }
470 //      return rows;
471     }
472     
473     public int getColumnCount(){
474       return 2;
475     }
476     
477     public Object getValueAt(int row, int column){
478       Object value = tableRows.get(row);
479       switch(column){
480         case NAME_COL:
481           return value;
482         case SELECTED_COL:
483           if(value instanceof SetHandler)
484             return new Boolean(((SetHandler)value).isExpanded());
485           if(value instanceof TypeHandler) 
486             return new Boolean(((TypeHandler)value).isSelected());
487         default:
488           return null;
489       }
490 //      
491 //      int currentRow = 0;
492 //      Iterator handlerIter = setHandlers.iterator();
493 //      SetHandler sHandler = (SetHandler)handlerIter.next();
494 //      
495 //      while(currentRow < row){
496 //        if(sHandler.expanded){
497 //          if(sHandler.typeHandlers.size() + currentRow >= row){
498 //            //we want a row in current set
499 //             return sHandler.typeHandlers.get(row - currentRow);
500 //          }else{
501 //            currentRow += sHandler.typeHandlers.size();
502 //            sHandler = (SetHandler)handlerIter.next();
503 //          }
504 //        }else{
505 //          //just go to next handler
506 //          currentRow++;
507 //          sHandler = (SetHandler)handlerIter.next();
508 //        }
509 //        if(currentRow == row) return sHandler;
510 //      }
511 //      if(currentRow == row) return sHandler;
512 //System.out.println("BUG! row: " + row + " col: " + column);      
513 //      return null;
514     }
515     
516     public boolean isCellEditable(int rowIndex, int columnIndex){
517       Object value = tableRows.get(rowIndex);
518       switch(columnIndex){
519         case NAME_COL: return false;
520         case SELECTED_COL:
521           if(value instanceof SetHandler)
522             return ((SetHandler)value).typeHandlers.size() > 0;
523           if(value instanceof TypeHandler) return true; 
524       }
525       return columnIndex == SELECTED_COL;
526     }
527     
528     public void setValueAt(Object aValue, int rowIndex, int columnIndex){
529       Object receiver = tableRows.get(rowIndex);
530       switch(columnIndex){
531         case SELECTED_COL:
532           if(receiver instanceof SetHandler){
533             ((SetHandler)receiver).setExpanded(((Boolean)aValue).booleanValue());
534           }else if(receiver instanceof TypeHandler){
535             ((TypeHandler)receiver).setSelected(((Boolean)aValue).booleanValue());
536           }
537           
538           break;
539         default:
540           break;
541       }
542     }
543   }//public Object getValueAt(int row, int column)
544   
545   protected class SetsTableCellRenderer implements TableCellRenderer{
546     public SetsTableCellRenderer(){
547       typeLabel = new JLabel(){
548         public void repaint(long tm, int x, int y, int width, int height){}
549         public void repaint(Rectangle r){}
550         public void validate(){}
551         public void revalidate(){}
552         protected void firePropertyChange(String propertyName,
553                                           Object oldValue,
554                                           Object newValue){}
555       };
556       typeLabel.setOpaque(true);
557       typeLabel.setBorder(BorderFactory.createCompoundBorder(
558               BorderFactory.createMatteBorder(0, 5, 0, 0,
559                       mainTable.getBackground()),
560               BorderFactory.createEmptyBorder(0, 5, 0, 5)));
561 //      typeLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
562 
563       
564       setLabel = new JLabel(){
565         public void repaint(long tm, int x, int y, int width, int height){}
566         public void repaint(Rectangle r){}
567         public void validate(){}
568         public void revalidate(){}
569         protected void firePropertyChange(String propertyName,
570                                           Object oldValue,
571                                           Object newValue){}
572       };
573       setLabel.setOpaque(true);
574       setLabel.setFont(setLabel.getFont().deriveFont(Font.BOLD));
575       setLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
576       
577 
578       typeChk = new JCheckBox(){
579         public void repaint(long tm, int x, int y, int width, int height){}
580         public void repaint(Rectangle r){}
581         public void validate(){}
582         public void revalidate(){}
583         protected void firePropertyChange(String propertyName,
584                                           Object oldValue,
585                                           Object newValue){}
586       };
587       typeChk.setOpaque(true);
588 //      typeChk.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0));
589 
590       setChk = new JCheckBox(){
591         public void repaint(long tm, int x, int y, int width, int height){}
592         public void repaint(Rectangle r){}
593         public void validate(){}
594         public void revalidate(){}
595         protected void firePropertyChange(String propertyName,
596                                           Object oldValue,
597                                           Object newValue){}
598       };
599       setChk.setSelectedIcon(MainFrame.getIcon("expanded.gif"));
600       setChk.setIcon(MainFrame.getIcon("closed.gif"));
601       setChk.setMaximumSize(setChk.getMinimumSize());
602       setChk.setOpaque(true);
603       
604       normalBorder = BorderFactory.createLineBorder(
605               mainTable.getBackground(), 2);
606       selectedBorder = BorderFactory.createLineBorder(
607               mainTable.getSelectionBackground(), 2);
608     }
609     
610     public Component getTableCellRendererComponent(JTable table,
611                                                    Object value,
612                                                    boolean isSelected,
613                                                    boolean hasFocus,
614                                                    int row,
615                                                    int column){
616       
617       value = tableRows.get(row);
618       if(value instanceof SetHandler){
619         SetHandler sHandler = (SetHandler)value;
620         switch(column){
621           case NAME_COL:
622             setLabel.setText(sHandler.set.getName());
623             setLabel.setBackground(isSelected ?
624                                    table.getSelectionBackground() :
625                                    table.getBackground());
626             return setLabel;
627           case SELECTED_COL:
628             setChk.setSelected(sHandler.isExpanded());
629             setChk.setEnabled(sHandler.typeHandlers.size() > 0);
630             setChk.setBackground(isSelected ?
631                                  table.getSelectionBackground() :
632                                  table.getBackground());
633             return setChk;
634         }
635       }else if(value instanceof TypeHandler){
636         TypeHandler tHandler = (TypeHandler)value;
637         switch(column){
638           case NAME_COL:
639             typeLabel.setBackground(tHandler.colour);
640             typeLabel.setText(tHandler.name);
641             typeLabel.setBorder(isSelected ? selectedBorder : normalBorder);
642             return typeLabel;
643           case SELECTED_COL:
644             typeChk.setBackground(isSelected ?
645                    table.getSelectionBackground() :
646                    table.getBackground());
647             typeChk.setSelected(tHandler.isSelected());
648             return typeChk;
649         }
650       }
651       typeLabel.setText("?");
652       return typeLabel;
653       //bugcheck!
654     }
655     
656     protected JLabel typeLabel;
657     protected JLabel setLabel;
658     protected JCheckBox setChk;
659     protected JCheckBox typeChk;
660     protected Border selectedBorder;
661     protected Border normalBorder;
662   }
663   
664   protected class SetsTableCellEditor extends AbstractCellEditor
665                                       implements TableCellEditor{
666     public SetsTableCellEditor(){
667       setChk = new JCheckBox();
668       setChk.setSelectedIcon(MainFrame.getIcon("expanded.gif"));
669       setChk.setIcon(MainFrame.getIcon("closed.gif"));
670 //      setChk.setMaximumSize(setChk.getMinimumSize());
671       setChk.setOpaque(true);
672       setChk.addActionListener(new ActionListener(){
673         public void actionPerformed(ActionEvent evt){
674           fireEditingStopped();
675         }
676       });
677       typeChk = new JCheckBox();
678       typeChk.setOpaque(false);
679 //      typeChk.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0));
680       typeChk.addActionListener(new ActionListener(){
681         public void actionPerformed(ActionEvent evt){
682           fireEditingStopped();
683         }
684       });
685     }
686     
687     public Component getTableCellEditorComponent(JTable table,
688                                                  Object value,
689                                                  boolean isSelected,
690                                                  int row,
691                                                  int column){
692       value = tableRows.get(row);
693       if(value instanceof SetHandler){
694         SetHandler sHandler = (SetHandler)value;
695         switch(column){
696           case NAME_COL: return null;
697           case SELECTED_COL:
698             setChk.setSelected(sHandler.isExpanded());
699             setChk.setEnabled(sHandler.typeHandlers.size() > 0);
700             setChk.setBackground(isSelected ?
701                                  table.getSelectionBackground() :
702                                  table.getBackground());
703             currentChk = setChk;
704             return setChk;
705         }
706       }else if(value instanceof TypeHandler){
707         TypeHandler tHandler = (TypeHandler)value;
708         switch(column){
709           case NAME_COL: return null;
710           case SELECTED_COL:
711 //            typeChk.setBackground(tHandler.colour);
712             typeChk.setSelected(tHandler.isSelected());
713             currentChk = typeChk;
714             return typeChk;
715         }
716       }
717       return null;
718     }
719     
720     public boolean stopCellEditing(){
721       return true;
722     }
723     
724     public Object getCellEditorValue(){
725       return new Boolean(currentChk.isSelected());
726     }
727     
728     public boolean shouldSelectCell(EventObject anEvent){
729       return true;
730     }
731     
732     public boolean isCellEditable(EventObject anEvent){
733       return true;
734     }
735     
736     JCheckBox currentChk;
737     JCheckBox setChk;
738     JCheckBox typeChk;
739   }
740   
741   
742   /**
743    * Stores the data related to an annotation set
744    */
745   protected class SetHandler{
746     SetHandler(AnnotationSet set){
747       this.set = set;
748       typeHandlers = new ArrayList();
749       typeHandlersByType = new HashMap();
750       List typeNames = new ArrayList(set.getAllTypes());
751       Collections.sort(typeNames);
752       Iterator typIter = typeNames.iterator();
753       while(typIter.hasNext()){
754         String name = (String)typIter.next();
755         TypeHandler tHandler = new TypeHandler(this, name); 
756         typeHandlers.add(tHandler);
757         typeHandlersByType.put(name, tHandler);
758       }
759       set.addAnnotationSetListener(AnnotationSetsView.this);
760     }
761     
762     public void cleanup(){
763       set.removeAnnotationSetListener(AnnotationSetsView.this);
764       typeHandlers.clear();
765     }
766     
767     /**
768      * Notifies this set handler that anew type of annotations has been created
769      * @param type the new type of annotations
770      * @return the new TypeHandler created as a result
771      */
772     public TypeHandler newType(String type){
773       //create a new TypeHandler
774       TypeHandler tHandler = new TypeHandler(this, type);
775       //add it to the list at the right position
776       int pos = 0;
777       for(;
778           pos < typeHandlers.size() &&
779           ((TypeHandler)typeHandlers.get(pos)).name.compareTo(type) <= 0;
780           pos++);
781       typeHandlers.add(pos, tHandler);
782       typeHandlersByType.put(type, tHandler);
783       //preserve table selection
784       int row = mainTable.getSelectedRow();
785       int setRow = tableRows.indexOf(this);
786       if(typeHandlers.size() == 1) 
787         tableModel.fireTableRowsUpdated(setRow, setRow);
788       if(expanded){
789         tableRows.add(setRow + pos + 1, tHandler);
790         tableModel.fireTableRowsInserted(setRow + pos + 1,
791               setRow + pos + 1);
792       }
793       //restore selection if any
794       if(row != -1) mainTable.getSelectionModel().setSelectionInterval(row, row);
795       return tHandler;
796     }
797     
798     public void removeType(TypeHandler tHandler){
799       int setRow = tableRows.indexOf(this);
800       int pos = typeHandlers.indexOf(tHandler);
801       typeHandlers.remove(pos);
802       typeHandlersByType.remove(tHandler.name);
803       //preserve table selection
804       int row = mainTable.getSelectedRow();
805       if(expanded){
806         tableRows.remove(setRow + pos + 1);
807         tableModel.fireTableRowsDeleted(setRow + pos + 1, setRow + pos + 1);
808         if(row >= (setRow + pos + 1)) row--;
809       }
810       if(typeHandlers.isEmpty()){
811         //the set has no more handlers
812         setExpanded(false);
813         tableModel.fireTableRowsUpdated(setRow, setRow);
814       }
815       //restore selection if any
816       if(row != -1) mainTable.getSelectionModel().setSelectionInterval(row, row);
817     }
818     
819     public void removeType(String type){
820       removeType((TypeHandler)typeHandlersByType.get(type));
821     }
822 
823     public TypeHandler getTypeHandler(String type){
824       return (TypeHandler)typeHandlersByType.get(type);
825     }
826     
827     public void setExpanded(boolean expanded){
828       if(this.expanded == expanded) return;
829       this.expanded = expanded;
830       int myPosition = tableRows.indexOf(this);
831       if(expanded){
832         //expand
833         tableRows.addAll(myPosition + 1, typeHandlers);
834         tableModel.fireTableRowsInserted(myPosition + 1, 
835                                          myPosition + 1 + typeHandlers.size());
836       }else{
837         //collapse
838         for(int i = 0; i < typeHandlers.size(); i++){
839           tableRows.remove(myPosition + 1);
840         }
841         tableModel.fireTableRowsDeleted(myPosition + 1, 
842                                         myPosition + 1 + typeHandlers.size());
843       }
844       tableModel.fireTableRowsUpdated(myPosition, myPosition);
845     }
846     
847     public boolean isExpanded(){
848       return expanded;
849     }
850     
851     
852     AnnotationSet set;
853     List typeHandlers;
854     Map typeHandlersByType;
855     private boolean expanded = false;
856   }
857   
858   protected class TypeHandler{
859     TypeHandler (SetHandler setHandler, String name){
860       this.setHandler = setHandler;
861       this.name = name;
862       colour = getColor(name);
863       hghltTagsForAnn = new HashMap();
864       changeColourAction = new ChangeColourAction();
865     }
866     
867     public void setColour(Color colour){
868       if(this.colour.equals(colour)) return;
869       this.colour = colour;
870       saveColor(name, colour);
871       if(isSelected()){
872         //redraw the highlights
873         Runnable runnable = new Runnable(){
874           public void run(){
875             //hide highlights
876             textView.removeHighlights(hghltTagsForAnn.values());
877             hghltTagsForAnn.clear();
878             //show highlights
879             List annots = new ArrayList(setHandler.set.get(name));
880             List tags = textView.addHighlights(annots, setHandler.set, 
881                     TypeHandler.this.colour);
882             for(int i = 0; i < annots.size(); i++){
883               hghltTagsForAnn.put(((Annotation)annots.get(i)).getId(), tags.get(i));
884             }
885           }
886         };
887         Thread thread = new Thread(runnable);
888         thread.setPriority(Thread.MIN_PRIORITY);
889         thread.start();
890       }
891       //update the table display
892       SwingUtilities.invokeLater(new Runnable(){
893         public void run(){
894           int row = tableRows.indexOf(this);
895           if(row >= 0) tableModel.fireTableRowsUpdated(row, row);
896         }
897       });
898     }
899     
900     public void setSelected(boolean selected){
901       if(this.selected == selected) return;
902       this.selected = selected;
903       final List annots = new ArrayList(setHandler.set.get(name));
904       if(selected){
905         //make sure set is expanded
906         setHandler.setExpanded(true);
907         //show highlights
908         hghltTagsForAnn.clear();
909         Iterator annIter = annots.iterator();
910         //we're doing a lot of operations so let's get out of the UI thread
911         Runnable runnable = new Runnable(){
912           public void run(){
913             //do all operations in one go
914             List tags = textView.addHighlights(annots, setHandler.set, colour);
915             for(int i = 0; i < annots.size(); i++){
916               hghltTagsForAnn.put(((Annotation)annots.get(i)).getId(), tags.get(i));
917             }
918           }
919         };
920         Thread thread = new Thread(runnable);
921         thread.setPriority(Thread.MIN_PRIORITY);
922         thread.start();
923       }else{
924         //hide highlights
925         Runnable runnable = new Runnable(){
926           public void run(){
927             //do all operations in one go
928             textView.removeHighlights(hghltTagsForAnn.values());
929             hghltTagsForAnn.clear();
930           }
931         };
932         Thread thread = new Thread(runnable);
933         thread.setPriority(Thread.MIN_PRIORITY);
934         thread.start();
935       }
936       //update the table display
937       int row = tableRows.indexOf(this);
938       tableModel.fireTableRowsUpdated(row, row);
939     }
940     
941     public boolean isSelected(){
942       return selected;
943     }
944     
945     /**
946      * Notifies this type handler that a new annotation was created of the 
947      * right type
948      * @param ann
949      */
950     public void annotationAdded(Annotation ann){
951       //if selected, add new highlight
952       if(selected) hghltTagsForAnn.put(ann.getId(), 
953               textView.addHighlight(ann, setHandler.set, colour));
954     }
955     
956     /**
957      * Notifies this type handler that an annotation has been removed
958      * @param ann the removed annotation
959      */
960     public void annotationRemoved(Annotation ann){
961       if(selected){
962         Object tag = hghltTagsForAnn.remove(ann.getId());
963         textView.removeHighlight(tag);
964       }
965       //if this was the last annotation of this type then the handler is no
966       //longer required
967       Set remainingAnns = setHandler.set.get(name); 
968       if(remainingAnns == null || remainingAnns.isEmpty()){
969         setHandler.removeType(this);
970       }
971     }
972     
973     protected void repairHighlights(int start, int end){
974       //map from tag to annotation
975       List tags = new ArrayList(hghltTagsForAnn.size());
976       List annots = new ArrayList(hghltTagsForAnn.size());
977       Iterator annIter = hghltTagsForAnn.keySet().iterator();
978       while(annIter.hasNext()){
979         Annotation ann = setHandler.set.get((Integer)annIter.next());
980         int annStart = ann.getStartNode().getOffset().intValue();
981         int annEnd = ann.getEndNode().getOffset().intValue();
982         if((annStart <= start && start <= annEnd) ||
983            (start <= annStart && annStart <= end)){
984           if(!hghltTagsForAnn.containsKey(ann.getId())){
985             System.out.println("Error!!!");
986           }
987           tags.add(hghltTagsForAnn.get(ann.getId()));
988           annots.add(ann);
989         }
990       }
991       for(int i = 0; i < tags.size(); i++){
992         Object tag = tags.get(i);
993         Annotation ann = (Annotation)annots.get(i);
994         try{
995           textView.moveHighlight(tag, 
996                   ann.getStartNode().getOffset().intValue(), 
997                   ann.getEndNode().getOffset().intValue());
998         }catch(BadLocationException ble){
999           //this should never happen as the offsets come from an annotation
1000        }
1001      }
1002    }
1003    
1004    
1005    protected class ChangeColourAction extends AbstractAction{
1006      public ChangeColourAction(){
1007        super("Change colour");
1008      }
1009      
1010      public void actionPerformed(ActionEvent evt){
1011        Color col = JColorChooser.showDialog(mainTable, 
1012                "Select colour for \"" + name + "\"",
1013                colour);
1014        if(col != null){
1015          Color colAlpha = new Color(col.getRed(), col.getGreen(),
1016                  col.getBlue(), 128);
1017          setColour(colAlpha);
1018        }
1019      }
1020    }
1021    
1022    ChangeColourAction changeColourAction;
1023    boolean selected;
1024    //Map from annotation ID (which is imuttable) to tag
1025    Map hghltTagsForAnn;
1026    String name;
1027    SetHandler setHandler;
1028    Color colour;
1029  }
1030  
1031  protected static class AnnotationHandler{
1032    public AnnotationHandler(AnnotationSet set, Annotation ann){
1033      this.ann = ann;
1034      this.set = set;
1035    }
1036    Annotation ann;
1037    AnnotationSet set;
1038  }
1039  
1040  /**
1041   * A mouse listener used for events in the text view. 
1042   */
1043  protected class TextMouseListener implements MouseInputListener{    
1044    public void mouseDragged(MouseEvent e){
1045      //do not create annotations while dragging
1046      mouseMovementTimer.stop();
1047    }
1048    
1049    public void mouseMoved(MouseEvent e){
1050      //this triggers select annotation leading to edit annotation or new 
1051      //annotation actions
1052      //ignore movement if CTRL pressed or dragging
1053      int modEx = e.getModifiersEx();
1054      if((modEx & MouseEvent.CTRL_DOWN_MASK) != 0){
1055        mouseMovementTimer.stop();
1056        return;
1057      }
1058      if((modEx & MouseEvent.BUTTON1_DOWN_MASK) != 0){
1059        mouseMovementTimer.stop();
1060        return;
1061      }
1062      mouseStoppedMovingAction.setTextLocation(textPane.viewToModel(e.getPoint()));
1063      mouseMovementTimer.restart();
1064    }
1065    
1066    public void mouseClicked(MouseEvent e){
1067    }
1068    
1069    public void mousePressed(MouseEvent e){
1070      
1071    }
1072    public void mouseReleased(MouseEvent e){
1073      
1074    }
1075    
1076    public void mouseEntered(MouseEvent e){
1077      
1078    }
1079    
1080    public void mouseExited(MouseEvent e){
1081      mouseMovementTimer.stop();
1082    }
1083  }//protected class TextMouseListener implements MouseInputListener
1084  
1085    
1086  protected class NewAnnotationSetAction extends AbstractAction{
1087    public NewAnnotationSetAction(){
1088      super("New");
1089      putValue(SHORT_DESCRIPTION, "Creates a new annotation set");
1090    }
1091    
1092    public void actionPerformed(ActionEvent evt){
1093      String name = newSetNameTextField.getText();
1094      newSetNameTextField.setText("");
1095      if(name != null && name.length() > 0){
1096        AnnotationSet set = document.getAnnotations(name);
1097        //select the newly added set
1098        Iterator rowsIter = tableRows.iterator();
1099        int row = -1;
1100        for(int i = 0; i < tableRows.size() && row < 0; i++){
1101          if(tableRows.get(i) instanceof SetHandler &&
1102             ((SetHandler)tableRows.get(i)).set == set) row = i;
1103        }
1104        if(row >= 0) mainTable.getSelectionModel().setSelectionInterval(row, row);
1105      }
1106    }
1107  }
1108
1109  protected class NewAnnotationAction extends AbstractAction{
1110    public void actionPerformed(ActionEvent evt){
1111      int start = textPane.getSelectionStart();
1112      int end = textPane.getSelectionEnd();
1113      if(start != end){
1114        textPane.setSelectionStart(start);
1115        textPane.setSelectionEnd(start);
1116        //create a new annotation
1117        //find the selected set
1118        int row = mainTable.getSelectedRow();
1119        //select the default annotation set if none selected
1120        if(row < 0) row = 0;
1121        //find the set handler
1122        while(!(tableRows.get(row) instanceof SetHandler)) row --;
1123        AnnotationSet set = ((SetHandler)tableRows.get(row)).set;
1124        try{
1125          Integer annId =  set.add(new Long(start), new Long(end), 
1126                  lastAnnotationType, Factory.newFeatureMap());
1127          Annotation ann = set.get(annId);
1128          //make sure new annotaion is visible
1129          setTypeSelected(set.getName(), ann.getType(), true);
1130          //show the editor
1131          annotationEditor.setAnnotation(ann, set);
1132          annotationEditor.show(true);
1133        }catch(InvalidOffsetException ioe){
1134          //this should never happen
1135          throw new GateRuntimeException(ioe);
1136        }
1137      }
1138    }
1139  }
1140  
1141  protected class SavePreserveFormatAction extends AbstractAction{
1142    public SavePreserveFormatAction(){
1143      super("Save preserving document format");
1144    }
1145    
1146    public void actionPerformed(ActionEvent evt){
1147      Runnable runableAction = new Runnable(){
1148        public void run(){
1149          JFileChooser fileChooser = MainFrame.getFileChooser();
1150          File selectedFile = null;
1151
1152          fileChooser.setMultiSelectionEnabled(false);
1153          fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1154          fileChooser.setDialogTitle("Select document to save ...");
1155          fileChooser.setSelectedFiles(null);
1156
1157          int res = fileChooser.showDialog(owner, "Save");
1158          if(res == JFileChooser.APPROVE_OPTION){
1159            selectedFile = fileChooser.getSelectedFile();
1160            fileChooser.setCurrentDirectory(fileChooser.getCurrentDirectory());
1161            if(selectedFile == null) return;
1162            StatusListener sListener = (StatusListener)MainFrame.getListeners().
1163              get("gate.event.StatusListener");
1164            if (sListener != null) 
1165              sListener.statusChanged("Please wait while dumping annotations"+
1166              "in the original format to " + selectedFile.toString() + " ...");
1167            // This method construct a set with all annotations that need to be
1168            // dupmped as Xml. If the set is null then only the original markups
1169            // are dumped.
1170            Set annotationsToDump = new HashSet();
1171            Iterator setIter = setHandlers.iterator();
1172            while(setIter.hasNext()){
1173              SetHandler sHandler = (SetHandler)setIter.next();
1174              Iterator typeIter = sHandler.typeHandlers.iterator();
1175              while(typeIter.hasNext()){
1176                TypeHandler tHandler = (TypeHandler)typeIter.next();
1177                if(tHandler.isSelected()){
1178                  annotationsToDump.addAll(sHandler.set.get(tHandler.name));
1179                }
1180              }
1181            }
1182            
1183            try{
1184              // Prepare to write into the xmlFile using the original encoding
1185              String encoding = ((TextualDocument)document).getEncoding();
1186
1187              OutputStreamWriter writer = new OutputStreamWriter(
1188                                            new FileOutputStream(selectedFile),
1189                                            encoding);
1190
1191              //determine if the features need to be saved first
1192              Boolean featuresSaved =
1193                  Gate.getUserConfig().getBoolean(
1194                    GateConstants.SAVE_FEATURES_WHEN_PRESERVING_FORMAT);
1195              boolean saveFeatures = true;
1196              if (featuresSaved != null)
1197                saveFeatures = featuresSaved.booleanValue();
1198              // Write with the toXml() method
1199              writer.write(
1200                document.toXml(annotationsToDump, saveFeatures));
1201              writer.flush();
1202              writer.close();
1203            } catch (Exception ex){
1204              ex.printStackTrace(Out.getPrintWriter());
1205            }// End try
1206            if (sListener != null)
1207              sListener.statusChanged("Finished dumping into the "+
1208              "file : " + selectedFile.toString());
1209          }// End if
1210        }// End run()
1211      };// End Runnable
1212      Thread thread = new Thread(runableAction, "");
1213      thread.setPriority(Thread.MIN_PRIORITY);
1214      thread.start();
1215    }
1216  }
1217  
1218  /**
1219   * Used to select an annotation for editing.
1220   *
1221   */
1222  protected class MouseStoppedMovingAction extends AbstractAction{
1223    
1224    public void actionPerformed(ActionEvent evt){
1225      //first check for selection hovering
1226      //if inside selection, add new annotation.
1227      if(textPane.getSelectionStart() <= textLocation &&
1228         textPane.getSelectionEnd() >= textLocation){
1229        new NewAnnotationAction().actionPerformed(evt);
1230      }else{
1231        //now check for annotations at location
1232        List annotsAtPoint = new ArrayList();
1233        Iterator shIter = setHandlers.iterator();
1234        while(shIter.hasNext()){
1235          SetHandler sHandler = (SetHandler)shIter.next();
1236          Iterator annIter = sHandler.set.get(new Long(textLocation),
1237                                              new Long(textLocation)).iterator();
1238          while(annIter.hasNext()){
1239            Annotation ann = (Annotation)annIter.next();
1240            if(sHandler.getTypeHandler(ann.getType()).isSelected()){
1241              annotsAtPoint.add(new AnnotationHandler(sHandler.set, ann));
1242            }
1243          }
1244        }
1245        if(annotsAtPoint.size() > 0){
1246          if(annotsAtPoint.size() > 1){
1247            JPopupMenu popup = new JPopupMenu();
1248            Iterator annIter = annotsAtPoint.iterator();
1249            while(annIter.hasNext()){
1250              AnnotationHandler aHandler = (AnnotationHandler)annIter.next();
1251              popup.add(new HighlightMenuItem(
1252                      new EditAnnotationAction(aHandler),
1253                      aHandler.ann.getStartNode().getOffset().intValue(),
1254                      aHandler.ann.getEndNode().getOffset().intValue(),
1255                      popup));
1256            }
1257            try{
1258              Rectangle rect =  textPane.modelToView(textLocation);
1259              popup.show(textPane, rect.x + 10, rect.y);
1260            }catch(BadLocationException ble){
1261              throw new GateRuntimeException(ble);
1262            }
1263          }else{
1264            //only one annotation: start the editing directly
1265            new EditAnnotationAction((AnnotationHandler)annotsAtPoint.get(0)).
1266              actionPerformed(null);
1267          }
1268        }
1269      }
1270    }
1271    
1272    public void setTextLocation(int textLocation){
1273      this.textLocation = textLocation;
1274    }
1275    int textLocation;
1276  }//protected class SelectAnnotationAction extends AbstractAction{
1277  
1278  
1279  /**
1280   * The popup menu items used to select annotations
1281   * Apart from the normal {@link javax.swing.JMenuItem} behaviour, this menu
1282   * item also highlights the annotation which it would select if pressed.
1283   */
1284  protected class HighlightMenuItem extends JMenuItem {
1285    public HighlightMenuItem(Action action, int startOffset, int endOffset, 
1286            JPopupMenu popup) {
1287      super(action);
1288      this.start = startOffset;
1289      this.end = endOffset;
1290      this.addMouseListener(new MouseAdapter() {
1291        public void mouseEntered(MouseEvent e) {
1292          showHighlight();
1293        }
1294
1295        public void mouseExited(MouseEvent e) {
1296          removeHighlight();
1297        }
1298      });
1299      popup.addPopupMenuListener(new PopupMenuListener(){
1300        public void popupMenuWillBecomeVisible(PopupMenuEvent e){
1301          
1302        }
1303        public void popupMenuCanceled(PopupMenuEvent e){
1304          removeHighlight();
1305        }
1306        public void popupMenuWillBecomeInvisible(PopupMenuEvent e){
1307          removeHighlight();
1308        }
1309        
1310        
1311      });
1312    }
1313    
1314    protected void showHighlight(){
1315      try {
1316        highlight = textPane.getHighlighter().addHighlight(start, end,
1317                                        DefaultHighlighter.DefaultPainter);
1318      }catch(BadLocationException ble){
1319        throw new GateRuntimeException(ble.toString());
1320      }
1321
1322    }
1323    
1324    protected void removeHighlight(){
1325      if(highlight != null){
1326        textPane.getHighlighter().removeHighlight(highlight);
1327        highlight = null;
1328      }
1329      
1330    }
1331
1332    int start;
1333    int end;
1334    Action action;
1335    Object highlight;
1336  }
1337  
1338  
1339  
1340  protected class EditAnnotationAction extends AbstractAction{
1341    public EditAnnotationAction(AnnotationHandler aHandler){
1342      super(aHandler.ann.getType() + " [" + 
1343              (aHandler.set.getName() == null ? "  " : 
1344                aHandler.set.getName()) +
1345              "]");
1346      putValue(SHORT_DESCRIPTION, aHandler.ann.getFeatures().toString());
1347      this.aHandler = aHandler;
1348    }
1349    
1350    public void actionPerformed(ActionEvent evt){
1351      annotationEditor.setAnnotation(aHandler.ann, aHandler.set);
1352      
1353      //select the annotation being edited in the tabular view
1354      if(listView != null && listView.isActive() &&
1355              listView.getGUI().isVisible()){
1356        TypeHandler tHandler = getTypeHandler(aHandler.set.getName(), 
1357                aHandler.ann.getType());
1358        if(tHandler != null){
1359          Object tag = tHandler.hghltTagsForAnn.get(aHandler.ann.getId());
1360          listView.selectAnnotationForTag(tag);
1361        }
1362      }
1363      annotationEditor.show(true);
1364    }
1365    
1366    AnnotationHandler aHandler;
1367  }
1368  
1369  protected class DeleteSelectedAnnotationGroupAction extends AbstractAction{
1370    public DeleteSelectedAnnotationGroupAction(){
1371    }
1372    public void actionPerformed(ActionEvent evt){
1373      int row = mainTable.getSelectedRow();
1374      if(row >= 0){
1375        Object handler = tableRows.get(row);
1376        if(handler instanceof TypeHandler){
1377          TypeHandler tHandler = (TypeHandler)handler;
1378          AnnotationSet set = tHandler.setHandler.set;
1379          AnnotationSet toDeleteAS = set.get(tHandler.name);
1380          if(toDeleteAS != null){
1381            List toDelete = new ArrayList(toDeleteAS);
1382            set.removeAll(toDelete);
1383          }
1384        }else if(handler instanceof SetHandler){
1385          SetHandler sHandler = (SetHandler)handler;
1386          if(sHandler.set == document.getAnnotations()){
1387            //the default annotation set - clear
1388            sHandler.set.clear();
1389          }else{
1390            document.removeAnnotationSet(sHandler.set.getName());
1391          }
1392        }
1393      }
1394    }
1395  }  
1396  
1397  List setHandlers;
1398  List tableRows; 
1399  XJTable mainTable;
1400  SetsTableModel tableModel;
1401  JScrollPane scroller;
1402  JPanel mainPanel;
1403  JTextField newSetNameTextField;
1404  
1405  TextualDocumentView textView;
1406  AnnotationListView listView;
1407  JEditorPane textPane;
1408  AnnotationEditor annotationEditor;
1409  NewAnnotationSetAction newSetAction;
1410  
1411  /**
1412   * The listener for mouse and mouse motion events in the text view.
1413   */
1414  protected TextMouseListener textMouseListener;
1415  
1416  protected javax.swing.Timer mouseMovementTimer;
1417  private static final int MOUSE_MOVEMENT_TIMER_DELAY = 500;
1418  protected AncestorListener textAncestorListener; 
1419  protected MouseStoppedMovingAction mouseStoppedMovingAction;
1420  
1421  protected String lastAnnotationType = "_New_";
1422  
1423  protected List actions;
1424  
1425  protected ColorGenerator colourGenerator;
1426  private static final int NAME_COL = 1;
1427  private static final int SELECTED_COL = 0;
1428  
1429}
1430