1
15
16 package gate.gui.docview;
17
18 import gate.*;
19 import gate.Annotation;
20 import gate.AnnotationSet;
21 import gate.creole.*;
22 import gate.creole.AnnotationVisualResource;
23 import gate.event.AnnotationEvent;
24 import gate.event.AnnotationListener;
25 import gate.gui.ResizableVisualResource;
26 import gate.swing.XJTable;
27 import gate.util.*;
28 import gate.util.Err;
29 import gate.util.GateRuntimeException;
30 import java.awt.*;
31 import java.awt.Component;
32 import java.awt.GridBagLayout;
33 import java.awt.event.*;
34 import java.util.*;
35 import java.util.List;
36 import java.util.Map;
37 import javax.swing.*;
38 import javax.swing.JScrollPane;
39 import javax.swing.SwingUtilities;
40 import javax.swing.event.*;
41 import javax.swing.event.TableModelEvent;
42 import javax.swing.event.TableModelListener;
43 import javax.swing.table.AbstractTableModel;
44
45
50 public class AnnotationListView extends AbstractDocumentView
51 implements AnnotationListener{
52 public AnnotationListView(){
53 tagList = new ArrayList();
54 annotationHandlerByTag = new HashMap();
55 }
56
57
60 protected void initGUI() {
61 editorsCache = new HashMap();
62 tableModel = new AnnotationTableModel();
63 table = new XJTable(tableModel);
64 table.setAutoResizeMode(XJTable.AUTO_RESIZE_OFF);
65 table.setSortable(true);
66 table.setSortedColumn(START_COL);
67 table.setIntercellSpacing(new Dimension(2, 0));
68 scroller = new JScrollPane(table);
69
70 mainPanel = new JPanel();
71 mainPanel.setLayout(new GridBagLayout());
72 GridBagConstraints constraints = new GridBagConstraints();
73
74 constraints.gridx = 0;
75 constraints.gridy = 0;
76 constraints.weightx = 1;
77 constraints.weighty = 1;
78 constraints.fill= GridBagConstraints.BOTH;
79 mainPanel.add(scroller, constraints);
80
81 constraints.gridy = 1;
82 constraints.weightx = 0;
83 constraints.weighty = 0;
84 constraints.fill= GridBagConstraints.NONE;
85 constraints.anchor = GridBagConstraints.WEST;
86 statusLabel = new JLabel();
87 mainPanel.add(statusLabel, constraints);
88
89 Iterator centralViewsIter = owner.getCentralViews().iterator();
92 while(textView == null && centralViewsIter.hasNext()){
93 DocumentView aView = (DocumentView)centralViewsIter.next();
94 if(aView instanceof TextualDocumentView)
95 textView = (TextualDocumentView)aView;
96 }
97
98 initListeners();
99 }
100
101 public Component getGUI(){
102 return mainPanel;
103 }
104 protected void initListeners(){
105
112 tableModel.addTableModelListener(new TableModelListener(){
113 public void tableChanged(TableModelEvent e){
114 statusLabel.setText(
115 Integer.toString(tableModel.getRowCount()) +
116 " Annotations (" +
117 Integer.toString(table.getSelectedRowCount()) +
118 " selected)");
119 }
120 });
121
122
123 table.getSelectionModel().
124 addListSelectionListener(new ListSelectionListener(){
125 public void valueChanged(ListSelectionEvent e){
126 statusLabel.setText(
127 Integer.toString(tableModel.getRowCount()) +
128 " Annotations (" +
129 Integer.toString(table.getSelectedRowCount()) +
130 "selected)");
131 textView.removeAllBlinkingHighlights();
133 int[] rows = table.getSelectedRows();
134 for(int i = 0; i < rows.length; i++){
135 Object tag = tagList.get(table.rowViewToModel(rows[i]));
136 AnnotationHandler aHandler = (AnnotationHandler)
137 annotationHandlerByTag.get(tag);
138 textView.addBlinkingHighlight(aHandler.ann);
139 textView.scrollAnnotationToVisible(aHandler.ann);
140 }
141 }
142 });
143
144 table.addMouseListener(new MouseListener() {
145 public void mouseClicked(final MouseEvent me) {
146 int viewRow = table.rowAtPoint(me.getPoint());
147 final int modelRow = viewRow == -1 ?
148 viewRow :
149 table.rowViewToModel(viewRow);
150
151 if(javax.swing.SwingUtilities.isRightMouseButton(me)) {
153 JPopupMenu popup = new JPopupMenu();
154
155 Action deleteAction = new AbstractAction("Delete"){
156 public void actionPerformed(ActionEvent evt){
157 int[] rows = table.getSelectedRows();
158 if(rows == null || rows.length == 0){
159 if(modelRow == -1) return;
161 rows = new int[]{modelRow};
162 }
163
164 ArrayList handlers = new ArrayList();
165
166 for(int i = 0; i < rows.length; i++){
167 Object tag = tagList.get(table.rowViewToModel(rows[i]));
168 handlers.add(tag);
169 }
170
171 for(int i=0;i<handlers.size();i++) {
172 Object tag = handlers.get(i);
173 AnnotationHandler aHandler = (AnnotationHandler)
174 annotationHandlerByTag.get(tag);
175 aHandler.set.remove(aHandler.ann);
176 removeAnnotation(tag);
177 }
178 }
179 };
180 popup.add(deleteAction);
181
182 if(modelRow != -1){
184 AnnotationHandler aHandler = (AnnotationHandler)
185 annotationHandlerByTag.get(tagList.get(modelRow));
186 List editorClasses = Gate.getCreoleRegister().
187 getAnnotationVRs(aHandler.ann.getType());
188 if(editorClasses != null && editorClasses.size() > 0){
189 popup.addSeparator();
190 Iterator editorIter = editorClasses.iterator();
191 while(editorIter.hasNext()){
192 String editorClass = (String) editorIter.next();
193 AnnotationVisualResource editor = (AnnotationVisualResource)
194 editorsCache.get(editorClass);
195 if(editor == null){
196 try{
198 editor = (AnnotationVisualResource)
199 Factory.createResource(editorClass);
200 editorsCache.put(editorClass, editor);
201 }catch(ResourceInstantiationException rie){
202 rie.printStackTrace(Err.getPrintWriter());
203 }
204 }
205 popup.add(new EditAnnotationAction(aHandler.set,
206 aHandler.ann, editor));
207 }
208 }
209 }
210
211
212
213 popup.show(table, me.getX(), me.getY());
214 }
215 }
216 public void mouseReleased(MouseEvent me) { }
217 public void mouseEntered(MouseEvent me) { }
218 public void mouseExited(MouseEvent me) { }
219 public void mousePressed(MouseEvent me) { }
220 });
221
222
223 }
224
227 protected void registerHooks() {
228 }
230
231
234 protected void unregisterHooks() {
235 }
237
238
241 public int getType() {
242 return HORIZONTAL;
243 }
244 protected void guiShown(){
245 tableModel.fireTableDataChanged();
246 }
247
248
249 public void addAnnotation(Object tag, Annotation ann, AnnotationSet set){
250 AnnotationHandler aHandler = new AnnotationHandler(set, ann);
251 Object oldValue = annotationHandlerByTag.put(tag, aHandler);
252 if(oldValue == null){
253 tagList.add(tag);
255 int row = tagList.size() -1;
256 if(tableModel != null) tableModel.fireTableRowsInserted(row, row);
257 }else{
258 int row = tagList.indexOf(tag);
260 if(tableModel != null) tableModel.fireTableRowsUpdated(row,row);
261 }
262 ann.addAnnotationListener(this);
264 }
265
266 public void removeAnnotation(Object tag){
267 int row = tagList.indexOf(tag);
268 if(row >= 0){
269 tagList.remove(row);
270 AnnotationHandler aHandler = (AnnotationHandler)
271 annotationHandlerByTag.remove(tag);
272 if(aHandler != null)aHandler.ann.removeAnnotationListener(this);
273 if(tableModel != null) tableModel.fireTableRowsDeleted(row, row);
274 }
275 }
276
277
286 public void addAnnotations(Collection tags, Collection annotations,
287 AnnotationSet set){
288 if(tags.size() != annotations.size()) throw new GateRuntimeException(
289 "Invalid invocation - different numbers of annotations and tags!");
290 Iterator tagIter = tags.iterator();
291 Iterator annIter = annotations.iterator();
292 while(tagIter.hasNext()){
293 Object tag = tagIter.next();
294 Annotation ann = (Annotation)annIter.next();
295 AnnotationHandler aHandler = new AnnotationHandler(set, ann);
296 Object oldValue = annotationHandlerByTag.put(tag, aHandler);
297 if(oldValue == null){
298 tagList.add(tag);
300 int row = tagList.size() -1;
301 }else{
302 int row = tagList.indexOf(tag);
304 }
305 ann.addAnnotationListener(this);
307 }
308 SwingUtilities.invokeLater(new Runnable(){
309 public void run(){
310 if(tableModel != null) tableModel.fireTableDataChanged();
311 }
312 });
313 }
314
315 public void removeAnnotations(Collection tags){
316 Iterator tagIter = tags.iterator();
317 while(tagIter.hasNext()){
318 Object tag = tagIter.next();
319 int row = tagList.indexOf(tag);
320 if(row >= 0){
321 tagList.remove(row);
322 AnnotationHandler aHandler = (AnnotationHandler)
323 annotationHandlerByTag.remove(tag);
324 if(aHandler != null)aHandler.ann.removeAnnotationListener(this);
325 }
326 }
327 SwingUtilities.invokeLater(new Runnable(){
328 public void run(){
329 if(tableModel != null) tableModel.fireTableDataChanged();
330 }
331 });
332 }
333
334 public void annotationUpdated(AnnotationEvent e){
335 Annotation ann = (Annotation)e.getSource();
337 for(int i = 0; i < tagList.size(); i++){
338 Object tag = tagList.get(i);
339 if(((AnnotationHandler)annotationHandlerByTag.get(tag)).ann == ann){
340 if(tableModel != null)tableModel.fireTableRowsUpdated(i, i);
341 }
342 }
343 }
344
345 class AnnotationTableModel extends AbstractTableModel{
346 public int getRowCount(){
347 return tagList.size();
348 }
349
350 public int getColumnCount(){
351 return 5;
352 }
353
354 public String getColumnName(int column){
355 switch(column){
356 case TYPE_COL: return "Type";
357 case SET_COL: return "Set";
358 case START_COL: return "Start";
359 case END_COL: return "End";
360 case FEATURES_COL: return "Features";
361 default: return "?";
362 }
363 }
364
365 public Class getColumnClass(int column){
366 switch(column){
367 case TYPE_COL: return String.class;
368 case SET_COL: return String.class;
369 case START_COL: return Long.class;
370 case END_COL: return Long.class;
371 case FEATURES_COL: return String.class;
372 default: return String.class;
373 }
374 }
375
376 public boolean isCellEditable(int rowIndex, int columnIndex){
377 return false;
378 }
379
380 public Object getValueAt(int row, int column){
381 AnnotationHandler aHandler = (AnnotationHandler)annotationHandlerByTag.
382 get(tagList.get(row));
383 switch(column){
384 case TYPE_COL: return aHandler.ann.getType();
385 case SET_COL: return aHandler.set.getName();
386 case START_COL: return aHandler.ann.getStartNode().getOffset();
387 case END_COL: return aHandler.ann.getEndNode().getOffset();
388 case FEATURES_COL:
389 FeatureMap features = aHandler.ann.getFeatures();
391 List keyList = new ArrayList(features.keySet());
392 Collections.sort(keyList);
393 StringBuffer strBuf = new StringBuffer("{");
394 Iterator keyIter = keyList.iterator();
395 boolean first = true;
396 while(keyIter.hasNext()){
397 Object key = keyIter.next();
398 Object value = features.get(key);
399 if(first){
400 first = false;
401 }else{
402 strBuf.append(", ");
403 }
404 strBuf.append(key.toString());
405 strBuf.append("=");
406 strBuf.append(value == null ? "[null]" : value.toString());
407 }
408 strBuf.append("}");
409 return strBuf.toString();
410 default: return "?";
411 }
412 }
413
414 }
415
416 protected static class AnnotationHandler{
417 public AnnotationHandler(AnnotationSet set, Annotation ann){
418 this.ann = ann;
419 this.set = set;
420 }
421 Annotation ann;
422 AnnotationSet set;
423 }
424
425 protected class EditAnnotationAction extends AbstractAction{
426 public EditAnnotationAction(AnnotationSet set, Annotation ann,
427 AnnotationVisualResource editor){
428 this.set = set;
429 this.ann = ann;
430 this.editor = editor;
431 ResourceData rData =(ResourceData)Gate.getCreoleRegister().
432 get(editor.getClass().getName());
433 if(rData != null){
434 title = rData.getName();
435 putValue(NAME, "Edit with " + title);
436 putValue(SHORT_DESCRIPTION, rData.getComment());
437 }
438 }
439
440 public void actionPerformed(ActionEvent evt){
441 JScrollPane scroller = new JScrollPane((Component)editor);
442 editor.setTarget(set);
443 editor.setAnnotation(ann);
444 JOptionPane optionPane = new JOptionPane(scroller,
445 JOptionPane.QUESTION_MESSAGE,
446 JOptionPane.OK_CANCEL_OPTION,
447 null, new String[]{"OK", "Cancel"});
448 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
449 scroller.setMaximumSize(new Dimension((int)(screenSize.width * .75),
450 (int)(screenSize.height * .75)));
451 JDialog dialog = optionPane.createDialog(AnnotationListView.this.getGUI(),
452 title);
453 dialog.setModal(true);
454 dialog.setResizable(true);
455 dialog.setVisible(true);
456 try{
457 if(optionPane.getValue().equals("OK")) editor.okAction();
458 else editor.cancelAction();
459 }catch(GateException ge){
460 throw new GateRuntimeException(ge);
461 }
462 }
463
464 String title;
465 Annotation ann;
466 AnnotationSet set;
467 AnnotationVisualResource editor;
468 }
469
470 protected XJTable table;
471 protected AnnotationTableModel tableModel;
472 protected JScrollPane scroller;
473 protected Map annotationHandlerByTag;
474 protected List tagList;
475 protected JPanel mainPanel;
476 protected JLabel statusLabel;
477 protected TextualDocumentView textView;
478
482 protected Map editorsCache;
483
484 private static final int TYPE_COL = 0;
485 private static final int SET_COL = 1;
486 private static final int START_COL = 2;
487 private static final int END_COL = 3;
488 private static final int FEATURES_COL = 4;
489
490 }
491