1
13 package gate.gui.docview;
14
15 import java.awt.*;
16 import java.awt.event.*;
17 import java.io.IOException;
18 import java.io.Reader;
19 import java.util.*;
20 import java.util.List;
21
22 import javax.swing.*;
23 import javax.swing.Timer;
24 import javax.swing.text.*;
25
26
27 import gate.Annotation;
28 import gate.AnnotationSet;
29 import gate.Document;
30 import gate.corpora.DocumentContentImpl;
31 import gate.event.DocumentEvent;
32 import gate.event.DocumentListener;
33 import gate.util.*;
34
35
36
39
40 public class TextualDocumentView extends AbstractDocumentView {
41
42 public TextualDocumentView(){
43 blinkingTagsForAnnotations = new HashMap();
44 gateDocListener = new GateDocumentListener();
45 }
46
47 public Object addHighlight(Annotation ann, AnnotationSet set, Color colour){
48 Highlighter highlighter = textView.getHighlighter();
49 try{
50 Object tag = highlighter.addHighlight(
51 ann.getStartNode().getOffset().intValue(),
52 ann.getEndNode().getOffset().intValue(),
53 new DefaultHighlighter.DefaultHighlightPainter(colour));
54 annotationListView.addAnnotation(tag, ann, set);
55 return tag;
56 }catch(BadLocationException ble){
57 throw new GateRuntimeException(ble.toString());
59 }
60 }
61
62
63 public void scrollAnnotationToVisible(Annotation ann){
64 Rectangle visibleView = scroller.getViewport().getViewRect();
69 int viewStart = textView.viewToModel(visibleView.getLocation());
70 Point endPoint = new Point(visibleView.getLocation());
71 endPoint.translate(visibleView.width, visibleView.height);
72 int viewEnd = textView.viewToModel(endPoint);
73 int annStart = ann.getStartNode().getOffset().intValue();
74 int annEnd = ann.getEndNode().getOffset().intValue();
75 if(annEnd < viewStart || viewEnd < annStart){
76 try{
77 textView.scrollRectToVisible(textView.modelToView(annStart));
78 }catch(BadLocationException ble){
79 throw new GateRuntimeException(ble);
81 }
82 }
83 }
84
85 public void removeHighlight(Object tag){
86 Highlighter highlighter = textView.getHighlighter();
87 highlighter.removeHighlight(tag);
88 annotationListView.removeAnnotation(tag);
89 }
90
91
99 public void moveHighlight(Object tag, int newStart, int newEnd)
100 throws BadLocationException{
101 textView.getHighlighter().changeHighlight(tag, newStart, newEnd);
102 }
103
104
115 public List addHighlights(Collection annotations,
116 AnnotationSet set, Color colour){
117 SwingUtilities.invokeLater(new Runnable(){
119 public void run(){
120 textView.setVisible(false);
121 scroller.getViewport().setView(new JLabel("Updating"));
122 }
123 });
124 while(textView.isVisible())
126 try{
127 Thread.sleep(30);
128 }catch(InterruptedException ie){
129 }
131
132 Highlighter highlighter = textView.getHighlighter();
133
134 Iterator annIter = annotations.iterator();
135 List tagsList = new ArrayList(annotations.size());
136 while(annIter.hasNext()){
137 Annotation ann = (Annotation)annIter.next();
138 try{
139 Object tag = highlighter.addHighlight(
140 ann.getStartNode().getOffset().intValue(),
141 ann.getEndNode().getOffset().intValue(),
142 new DefaultHighlighter.DefaultHighlightPainter(colour));
143 tagsList.add(tag);
144 }catch(BadLocationException ble){
145 throw new GateRuntimeException(ble.toString());
147 }
148 }
149 annotationListView.addAnnotations(tagsList, annotations, set);
150 SwingUtilities.invokeLater(new Runnable(){
151 public void run(){
152 scroller.getViewport().setView(textView);
153 textView.setVisible(true);
154 }
155 });
156 return tagsList;
157 }
158
159
164 public void removeHighlights(Collection tags){
165 SwingUtilities.invokeLater(new Runnable(){
167 public void run(){
168 textView.setVisible(false);
169 scroller.getViewport().setView(new JLabel("Updating"));
170 }
171 });
172 while(textView.isVisible())
174 try{
175 Thread.sleep(30);
176 }catch(InterruptedException ie){
177 }
179
180 Highlighter highlighter = textView.getHighlighter();
181
182 Iterator tagIter = tags.iterator();
183 while(tagIter.hasNext()){
184 highlighter.removeHighlight(tagIter.next());
185 }
186 annotationListView.removeAnnotations(tags);
187 SwingUtilities.invokeLater(new Runnable(){
188 public void run(){
189 scroller.getViewport().setView(textView);
190 textView.setVisible(true);
191 }
192 });
193 }
194
195
196 public void addBlinkingHighlight(Annotation ann){
197 synchronized(blinkingTagsForAnnotations){
198 blinkingTagsForAnnotations.put(ann.getId(), new AnnotationTag(ann, null));
199 }
200 }
201
202 public void removeBlinkingHighlight(Annotation ann){
203 synchronized(blinkingTagsForAnnotations){
204 AnnotationTag annTag = (AnnotationTag)blinkingTagsForAnnotations.
205 remove(ann.getId());
206 if(annTag != null && annTag.getTag() != null)
207 textView.getHighlighter().removeHighlight(annTag.getTag());
208 }
209 }
210
211
212 public void removeAllBlinkingHighlights(){
213 synchronized(blinkingTagsForAnnotations){
214 Iterator annIdIter = new ArrayList(blinkingTagsForAnnotations.keySet()).
215 iterator();
216 while(annIdIter.hasNext()){
217 AnnotationTag annTag = (AnnotationTag)
218 blinkingTagsForAnnotations.remove(annIdIter.next());
219 Annotation ann = annTag.getAnnotation();
220 Object tag = annTag.getTag();
221 if(tag != null){
222 Highlighter highlighter = textView.getHighlighter();
223 highlighter.removeHighlight(tag);
224 }
225 }
226 }
227 }
228
229
230 public int getType() {
231 return CENTRAL;
232 }
233
234
238 public void setTarget(Object target) {
239 if(document != null){
240 document.removeDocumentListener(gateDocListener);
242 }
243 super.setTarget(target);
244 this.document.addDocumentListener(gateDocListener);
246 }
247
248
249
252 protected void initGUI() {
253 textView = new JEditorPane();
254 textView.setContentType("text/plain");
255 textView.setEditorKit(new RawEditorKit());
256 textView.setAutoscrolls(false);
257 scroller = new JScrollPane(textView);
258
259 textView.setText(document.getContent().toString());
260 textView.getDocument().addDocumentListener(new SwingDocumentListener());
261 scroller.getViewport().setViewPosition(new Point(0, 0));
262
263 Iterator horizViewsIter = owner.getHorizontalViews().iterator();
266 while(annotationListView == null && horizViewsIter.hasNext()){
267 DocumentView aView = (DocumentView)horizViewsIter.next();
268 if(aView instanceof AnnotationListView)
269 annotationListView = (AnnotationListView)aView;
270 }
271 blinker = new Timer(BLINK_DELAY, new BlinkAction());
272 blinker.setRepeats(true);
273 blinker.start();
274 initListeners();
275 }
276
277 public Component getGUI(){
278 return scroller;
279 }
280
281 protected void initListeners(){
282 textView.addComponentListener(new ComponentAdapter(){
283 public void componentResized(ComponentEvent e){
284 try{
285 scroller.getViewport().setViewPosition(
286 textView.modelToView(0).getLocation());
287 scroller.paintImmediately(textView.getBounds());
288 }catch(BadLocationException ble){
289 }
291 }
292 });
293 }
294 protected void unregisterHooks(){}
295 protected void registerHooks(){}
296
297
298
301 protected class BlinkAction extends AbstractAction{
302 public void actionPerformed(ActionEvent evt){
303 synchronized(blinkingTagsForAnnotations){
305 if(blinkingTagsForAnnotations.isEmpty()) return;
307 Iterator annIdIter = new ArrayList(blinkingTagsForAnnotations.keySet()).
308 iterator();
309 Highlighter highlighter = textView.getHighlighter();
310 if(highlightsShown){
311 while(annIdIter.hasNext()){
313 AnnotationTag annTag = (AnnotationTag)
314 blinkingTagsForAnnotations.get(annIdIter.next());
315 Annotation ann = annTag.getAnnotation();
316 Object tag = annTag.getTag();
317 if(tag != null) highlighter.removeHighlight(tag);
318 annTag.setTag(null);
319 }
320 highlightsShown = false;
321 }else{
322 while(annIdIter.hasNext()){
324 AnnotationTag annTag = (AnnotationTag)
325 blinkingTagsForAnnotations.get(annIdIter.next());
326 Annotation ann = annTag.getAnnotation();
327 try{
328 Object tag = highlighter.addHighlight(
329 ann.getStartNode().getOffset().intValue(),
330 ann.getEndNode().getOffset().intValue(),
331 new DefaultHighlighter.DefaultHighlightPainter(
332 textView.getSelectionColor()));
333 annTag.setTag(tag);
334 }catch(BadLocationException ble){
336 throw new GateRuntimeException(ble);
338 }
339 }
340 highlightsShown = true;
341 }
342 }
343 }
344 protected boolean highlightsShown = false;
345 }
346
347 class GateDocumentListener implements DocumentListener{
348
349 public void annotationSetAdded(DocumentEvent e) {
350 }
351
352 public void annotationSetRemoved(DocumentEvent e) {
353 }
354
355 public void contentEdited(DocumentEvent e) {
356 if(active){
357 textView.setText(document.getContent().toString());
359 }
360 }
361
362 public void setActive(boolean active){
363 this.active = active;
364 }
365 private boolean active = true;
366 }
367
368 class SwingDocumentListener implements javax.swing.event.DocumentListener{
369 public void insertUpdate(final javax.swing.event.DocumentEvent e) {
370 try{
372 gateDocListener.setActive(false);
374 document.edit(new Long(e.getOffset()), new Long(e.getOffset()),
375 new DocumentContentImpl(
376 e.getDocument().getText(e.getOffset(), e.getLength())));
377 }catch(BadLocationException ble){
378 ble.printStackTrace(Err.getPrintWriter());
379 }catch(InvalidOffsetException ioe){
380 ioe.printStackTrace(Err.getPrintWriter());
381 }finally{
382 gateDocListener.setActive(true);
384 }
385 Component listView = annotationListView.getGUI();
387 if(listView != null) listView.repaint();
388 }
389
390 public void removeUpdate(final javax.swing.event.DocumentEvent e) {
391 try{
393 gateDocListener.setActive(false);
395 document.edit(new Long(e.getOffset()),
396 new Long(e.getOffset() + e.getLength()),
397 new DocumentContentImpl(""));
398 }catch(InvalidOffsetException ioe){
399 ioe.printStackTrace(Err.getPrintWriter());
400 }finally{
401 gateDocListener.setActive(true);
403 }
404 Component listView = annotationListView.getGUI();
406 if(listView != null) listView.repaint();
407 }
408
409 public void changedUpdate(javax.swing.event.DocumentEvent e) {
410 }
412 }
414
417 class AnnotationTag{
418
419
422 public void setTag(Object tag){
423 this.tag = tag;
424 }
425 public AnnotationTag(Annotation annotation, Object tag){
426 this.annotation = annotation;
427 this.tag = tag;
428 }
429
430
433 public Annotation getAnnotation(){
434 return annotation;
435 }
436
439 public Object getTag(){
440 return tag;
441 }
442 Annotation annotation;
443 Object tag;
444 }
445
446 protected JScrollPane scroller;
447 protected AnnotationListView annotationListView;
448
449 protected GateDocumentListener gateDocListener;
450
451
455 protected Map blinkingTagsForAnnotations;
456
457 protected Timer blinker;
458
459 protected JEditorPane textView;
460
461
464 protected final static int BLINK_DELAY = 400;
465 }
466