001 /*
002 * The contents of this file are subject to the Mozilla Public
003 * License Version 1.1 (the "License"); you may not use this file
004 * except in compliance with the License. You may obtain a copy of
005 * the License at http://www.mozilla.org/MPL/
006 *
007 * Software distributed under the License is distributed on an "AS
008 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
009 * implied. See the License for the specific language governing
010 * rights and limitations under the License.
011 *
012 * The Original Code is Knowtator.
013 *
014 * The Initial Developer of the Original Code is University of Colorado.
015 * Copyright (C) 2005-2008. All Rights Reserved.
016 *
017 * Knowtator was developed by the Center for Computational Pharmacology
018 * (http://compbio.uchcs.edu) at the University of Colorado Health
019 * Sciences Center School of Medicine with support from the National
020 * Library of Medicine.
021 *
022 * Current information about Knowtator can be obtained at
023 * http://knowtator.sourceforge.net/
024 *
025 * Contributor(s):
026 * Philip V. Ogren <philip@ogren.info> (Original Author)
027 */
028 package edu.uchsc.ccp.knowtator.ui;
029
030 import java.awt.Color;
031 import java.awt.Font;
032 import java.awt.FontMetrics;
033 import java.awt.Graphics;
034 import java.awt.Point;
035 import java.awt.Rectangle;
036 import java.awt.Shape;
037 import java.awt.event.ActionEvent;
038 import java.awt.event.ActionListener;
039 import java.awt.event.KeyAdapter;
040 import java.awt.event.KeyEvent;
041 import java.awt.event.KeyListener;
042 import java.awt.event.MouseAdapter;
043 import java.awt.event.MouseEvent;
044 import java.awt.event.MouseListener;
045 import java.util.ArrayList;
046 import java.util.Collection;
047 import java.util.Collections;
048 import java.util.HashMap;
049 import java.util.HashSet;
050 import java.util.LinkedHashSet;
051 import java.util.List;
052 import java.util.Map;
053 import java.util.Set;
054 import java.util.regex.Pattern;
055
056 import javax.swing.JMenuItem;
057 import javax.swing.JPopupMenu;
058 import javax.swing.JScrollPane;
059 import javax.swing.JTextPane;
060 import javax.swing.UIManager;
061 import javax.swing.text.BadLocationException;
062 import javax.swing.text.DefaultHighlighter;
063 import javax.swing.text.Highlighter;
064 import javax.swing.text.JTextComponent;
065 import javax.swing.text.Position;
066 import javax.swing.text.Style;
067 import javax.swing.text.StyleConstants;
068 import javax.swing.text.StyleContext;
069 import javax.swing.text.StyledDocument;
070 import javax.swing.text.View;
071
072 import org.apache.log4j.Logger;
073
074 import edu.stanford.smi.protege.model.Cls;
075 import edu.stanford.smi.protege.model.Frame;
076 import edu.stanford.smi.protege.model.Instance;
077 import edu.stanford.smi.protege.model.SimpleInstance;
078 import edu.stanford.smi.protege.model.Slot;
079 import edu.uchsc.ccp.knowtator.AnnotationUtil;
080 import edu.uchsc.ccp.knowtator.BrowserTextUtil;
081 import edu.uchsc.ccp.knowtator.DisplayColors;
082 import edu.uchsc.ccp.knowtator.InvalidSpanException;
083 import edu.uchsc.ccp.knowtator.KnowtatorManager;
084 import edu.uchsc.ccp.knowtator.MentionUtil;
085 import edu.uchsc.ccp.knowtator.Span;
086 import edu.uchsc.ccp.knowtator.SpanUtil;
087 import edu.uchsc.ccp.knowtator.event.AnnotationCreatedEvent;
088 import edu.uchsc.ccp.knowtator.event.AnnotationCreatedListener;
089 import edu.uchsc.ccp.knowtator.event.EventHandler;
090 import edu.uchsc.ccp.knowtator.event.RefreshAnnotationsDisplayListener;
091 import edu.uchsc.ccp.knowtator.util.ProtegeUtil;
092
093 public class KnowtatorTextPane extends JTextPane implements RefreshAnnotationsDisplayListener,
094 AnnotationCreatedListener {
095
096 public void annotationCreated(AnnotationCreatedEvent event) {
097 clearSelectionHighlights();
098 }
099
100 public static final int NO_LINES = 0;
101
102 public static final int SOLID_LINES = 1;
103
104 public static final int DASHED_LINES = 2;
105
106 public static final int VERTICAL_LINES = 3;
107
108 Logger logger = Logger.getLogger(KnowtatorTextPane.class);
109
110 static final long serialVersionUID = 0;
111
112 Set<Span> annotationSpans;
113
114 Map<Span, Color> annotationSpanColors;
115
116 Map<Span, Integer> annotationSpanLines;
117
118 Map<Span, String> annotationSpanSubtexts;
119
120 List<Span> selectionSpans;
121
122 List<Span> selectedAnnotationSpans;
123
124 // we don't need selectionSpanColors because we will always use
125 // getSelectionColor for selection spans
126
127 Map<Color, KnowtatorHighlighter> painters;
128
129 Map<Color, KnowtatorHighlighter> linePainters;
130
131 Map<Color, KnowtatorHighlighter> dashedLinePainters;
132
133 Map<Color, KnowtatorHighlighter> verticalLinePainters;
134
135 String text = "";
136
137 KnowtatorManager manager;
138
139 AnnotationUtil annotationUtil;
140
141 MentionUtil mentionUtil;
142
143 DisplayColors displayColors;
144
145 BrowserTextUtil browserTextUtil;
146
147 SpanUtil spanUtil;
148
149 String tokenRegex = null;
150
151 Pattern tokenPattern;
152
153 Highlighter highlighter;
154
155 Color lineHighlightColor = Color.BLACK;
156
157 Map<Integer, Set<SimpleInstance>> window2AnnotationsMap;
158
159 int windowSize = 20;
160
161 JPopupMenu popupMenu;
162
163 boolean mouseButtonDown = false;
164
165 JScrollPane scrollPane;
166
167 Style doubleSpace;
168
169 boolean initComplete = false;
170
171 public KnowtatorTextPane(KnowtatorManager manager) {
172 super();
173 this.manager = manager;
174 annotationUtil = manager.getAnnotationUtil();
175 mentionUtil = manager.getMentionUtil();
176 browserTextUtil = manager.getBrowserTextUtil();
177 displayColors = manager.getDisplayColors();
178 spanUtil = manager.getSpanUtil();
179
180 popupMenu = new JPopupMenu();
181
182 annotationSpans = new LinkedHashSet<Span>();
183 annotationSpanColors = new HashMap<Span, Color>();
184 annotationSpanLines = new HashMap<Span, Integer>();
185 annotationSpanSubtexts = new HashMap<Span, String>();
186 selectionSpans = new ArrayList<Span>();
187 selectedAnnotationSpans = new ArrayList<Span>();
188
189 addMouseListener(createMouseListener());
190 addKeyListener(createKeyListener());
191
192 painters = new HashMap<Color, KnowtatorHighlighter>();
193 linePainters = new HashMap<Color, KnowtatorHighlighter>();
194 dashedLinePainters = new HashMap<Color, KnowtatorHighlighter>();
195 verticalLinePainters = new HashMap<Color, KnowtatorHighlighter>();
196 updateTokenRegex();
197 setEditable(false);
198
199 window2AnnotationsMap = new HashMap<Integer, Set<SimpleInstance>>();
200 highlighter = getHighlighter();
201
202 EventHandler.getInstance().addRefreshAnnotationsDisplayListener(this);
203 EventHandler.getInstance().addAnnotationCreatedListener(this);
204 logger.debug("made it to here.");
205 initComplete = true;
206 }
207
208 public void refreshAnnotationsDisplay(boolean scrollToSelection) {
209 logger.debug("");
210 highlightSpans(scrollToSelection);
211 repaint();
212 }
213
214 public void repaint() {
215 super.repaint();
216 if (!initComplete)
217 return;
218 if (doubleSpace == null) {
219 StyledDocument doc = getStyledDocument();
220 if (doc == null)
221 return;
222 Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
223 if (def == null)
224 return;
225 doubleSpace = doc.addStyle("doubleSpace", def);
226 }
227 if (doubleSpace != null && text.length() > 0) {
228 Font font = UIManager.getFont("TextArea.font");
229 if (font.getSize() != StyleConstants.getFontSize(doubleSpace)) {
230 StyleConstants.setFontFamily(doubleSpace, "TextArea.font");
231 StyleConstants.setFontSize(doubleSpace, font.getSize());
232 setParagraphAttributes(doubleSpace, true);
233 }
234 if (manager.getSubtextSlot() == null) {
235 if (StyleConstants.getLineSpacing(doubleSpace) != 0.2f) {
236 StyleConstants.setLineSpacing(doubleSpace, 0.2f);
237 setParagraphAttributes(doubleSpace, true);
238 }
239 } else if (StyleConstants.getLineSpacing(doubleSpace) != 1.0f) {
240 StyleConstants.setLineSpacing(doubleSpace, 1.0f);
241 setParagraphAttributes(doubleSpace, true);
242 }
243 }
244 }
245
246 public void highlightSpans(boolean scrollToSelection) {
247
248 logger.debug("");
249 SimpleInstance selectedAnnotation = manager.getSelectedAnnotation();
250 List<SimpleInstance> visibleAnnotations = manager.getVisibleFilteredAnnotations();
251 highlightSpans(selectedAnnotation, visibleAnnotations, scrollToSelection);
252 }
253
254 public void setScrollPane(JScrollPane scrollPane) {
255 logger.debug("");
256 this.scrollPane = scrollPane;
257 }
258
259 public void setAnnotationUtil(AnnotationUtil annotationUtil) {
260 logger.debug("");
261 this.annotationUtil = annotationUtil;
262 }
263
264 public void setDisplayColors(DisplayColors displayColors) {
265 logger.debug("");
266 this.displayColors = displayColors;
267 }
268
269 public void updateTokenRegex() {
270 logger.debug("");
271 if (tokenRegex == null) {
272 tokenRegex = manager.getTokenRegex();
273 tokenPattern = Pattern.compile(tokenRegex);
274 } else {
275 String currentRegex = manager.getTokenRegex();
276 if (!tokenRegex.equals(currentRegex)) {
277 tokenRegex = currentRegex;
278 tokenPattern = Pattern.compile(tokenRegex);
279 }
280 }
281 }
282
283 public void select(int start) {
284 logger.debug("");
285 int st = Math.max(0, start);
286 st = Math.min(st, text.length() - 1);
287 select(st, st);
288 }
289
290 /*
291 * overrides inherited method. super.select is called in
292 * select(Collection<Span)
293 */
294 public void select(int start, int end) {
295 logger.debug("");
296 if (start <= end)
297 select(new Span(start, end));
298 else
299 select(start);
300 }
301
302 public void select(Span span) {
303 logger.debug("");
304 Collection<Span> spans = new ArrayList<Span>();
305 spans.add(span);
306 select(spans);
307 }
308
309 public boolean select(Span span, boolean isNew) {
310 logger.debug("");
311 select(span);
312 if (annotationSpans.contains(span))
313 return true;
314 return false;
315 }
316
317 public void select(Collection<Span> spans) {
318 logger.debug("");
319 for (Span span : spans) {
320 int start = Math.max(0, span.getStart());
321 int end = Math.min(span.getEnd(), text.length() - 1);
322 super.select(start, end);
323 if (start != end) {
324 selectionSpans.add(span);
325 manager.setSelectedSpans(selectionSpans);
326 highlightSpan(span, getSelectionColor(), NO_LINES);
327 }
328 }
329 }
330
331 public void addAnnotationHighlights(Collection<Span> spans, Color color, int lines) {
332 logger.debug("");
333 for (Span span : spans) {
334 if (annotationSpans.contains(span))
335 continue;
336 annotationSpans.add(span);
337 annotationSpanColors.put(span, color);
338 annotationSpanLines.put(span, lines);
339 }
340 }
341
342 public void clearHighlights() {
343 logger.debug("");
344 clearAnnotationHighlights();
345 // clearSelectionHighlights();
346 hideHighlights();
347 }
348
349 public void hideHighlights() {
350 logger.debug("");
351 highlighter.removeAllHighlights();
352 repaint();
353 }
354
355 public void clearAnnotationHighlights() {
356 logger.debug("");
357 annotationSpans.clear();
358 annotationSpanColors.clear();
359 annotationSpanLines.clear();
360
361 annotationSpanSubtexts.clear();
362 }
363
364 public void clearSelectionHighlights() {
365 logger.debug("");
366 selectionSpans.clear();
367 manager.setSelectedSpans(selectionSpans);
368 }
369
370 // consider getting rid of this method. I don't think it does anything
371 // useful as
372 // showSelectionHighlights is superceded by shoAnnotationHighlights
373 public void showAllHighlights() {
374 logger.debug("");
375 showAnnotationHighlights();
376 showSelectionHighlights();
377 }
378
379 public void showSelectionHighlights() {
380 logger.debug(" number of selection spans = " + selectionSpans.size());
381 for (Span span : selectionSpans) {
382 Color color = getSelectionColor();
383
384 highlightSpan(span, color, NO_LINES);
385 }
386 }
387
388 public void showAnnotationHighlights() {
389 logger.debug("");
390 for (Span span : annotationSpans) {
391 Color color = annotationSpanColors.get(span);
392 int lines = annotationSpanLines.get(span);
393 highlightSpan(span, color, lines);
394 }
395 repaint();
396 }
397
398 private void updateAnnotationLines() {
399 logger.debug("");
400 List<Span> sortedSpans = new ArrayList<Span>(annotationSpans);
401 Collections.sort(sortedSpans);
402
403 for (int i = 0; i < sortedSpans.size(); i++) {
404 if (i == 0 || i == sortedSpans.size() - 1)
405 continue;
406 else {
407 Span previousSpan = sortedSpans.get(i - 1);
408 Span currentSpan = sortedSpans.get(i);
409 if (previousSpan.getEnd() == currentSpan.getStart()) {
410 if (annotationSpanLines.containsKey(currentSpan)
411 && annotationSpanLines.get(currentSpan) != NO_LINES) {
412 continue;
413 } else {
414 annotationSpanLines.put(currentSpan, VERTICAL_LINES);
415 highlightSpan(currentSpan, annotationSpanColors.get(currentSpan), VERTICAL_LINES);
416 }
417 }
418 }
419 }
420 }
421
422 private Object highlightSpan(Span span, Color color, int lines) {
423 try {
424 int start = Math.max(0, span.getStart());
425 int end = Math.min(span.getEnd(), text.length() - 1);
426 KnowtatorHighlighter painter = getHighlightPainter(color, lines);
427
428 Object highlight = highlighter.addHighlight(start, end, painter);
429 return highlight;
430 } catch (BadLocationException ble) {
431 ble.printStackTrace();
432 return null;
433 }
434 }
435
436 public void setText(String text) {
437 try {
438 logger.debug("");
439 super.setText(text);
440 // super.setPage(new File(
441 // "C:/Documents and Settings/Philip/My Documents/CSLR/workspace/CoordinationResolution/data/annotation/pilot/textsources/test.html"
442 // ).toURL());
443 // this.text ="Hello!\nThis is some test html.\nGoodbye!";
444 this.text = text;
445 select(0, 0);
446 } catch (Exception e) {
447 e.printStackTrace();
448 }
449 }
450
451 /**
452 * written to provide a way for AnnotationPicker and AnnotationSchemaTree
453 * context menu to temporarily highlight an annotation.
454 *
455 * @param annotation
456 * @see AnnotationPicker#mouseMoved(MouseEvent)
457 */
458 public void highlightAnnotationTemp(SimpleInstance annotation) {
459 logger.debug("");
460 hideHighlights();
461 try {
462 Color annotationColor = displayColors.getColor(annotation);
463 java.util.List<Span> spans = annotationUtil.getSpans(annotation);
464 if (spans.size() > 0) {
465 for (Span span : spans) {
466 highlightSpan(span, annotationColor, SOLID_LINES);
467 }
468 select(spans.get(0).getStart()); // this here so that the
469 // textpane will scroll to the
470 // highlighted text.
471 } else {
472 Set<SimpleInstance> referencedAnnotations = annotationUtil
473 .getRelatedAnnotations((SimpleInstance) annotation);
474 boolean textSelectionChanged = false; // we only want to do a
475 // textPane.select(int)
476 // once see comment below.
477 for (SimpleInstance referencedAnnotation : referencedAnnotations) {
478 annotationColor = displayColors.getColor(referencedAnnotation);
479 spans = annotationUtil.getSpans(referencedAnnotation);
480 for (Span span : spans) {
481 highlightSpan(span, annotationColor, SOLID_LINES);
482 if (!textSelectionChanged) {
483 select(span.getStart()); // this here so that the
484 // textpane will scroll to
485 // the highlighted text.
486 textSelectionChanged = true;
487 }
488 }
489 }
490 }
491 } catch (InvalidSpanException ise) {
492 ise.printStackTrace();
493 }
494 showAllHighlights();
495 }
496
497 private void selectAnnotation(int offset) {
498 logger.debug("");
499 Collection<SimpleInstance> clickedAnnotations = getAnnotationsAt(offset);
500 if (clickedAnnotations.size() > 0) {
501 SimpleInstance annotation = annotationUtil.getShortestAnnotation(clickedAnnotations);
502 SimpleInstance selectedAnnotation = manager.getSelectedAnnotation();
503 if (annotation.equals(selectedAnnotation)) {
504 manager.setSelectedAnnotation(null);
505 } else {
506 manager.setSelectedAnnotation(annotation);
507 }
508 }
509 }
510
511 public void highlightSelectedInstance(SimpleInstance selectedAnnotation, boolean scrollToSelection) throws InvalidSpanException {
512 logger.debug("");
513 selectedAnnotationSpans.clear();
514 if (selectedAnnotation != null) {
515 Color annotationColor;
516 java.util.List<Span> spans;
517
518 Set<SimpleInstance> referencedAnnotations = annotationUtil
519 .getRelatedAnnotations((SimpleInstance) selectedAnnotation);
520
521 boolean textSelectionChanged = false; // we only want to do a
522 // textPane.select(int) once
523 // see comment below.
524
525 for (SimpleInstance referencedAnnotation : referencedAnnotations) {
526 if (referencedAnnotation.equals(selectedAnnotation))
527 continue;
528 annotationColor = displayColors.getColor(referencedAnnotation);
529 getSubtext(referencedAnnotation);
530 spans = annotationUtil.getSpans(referencedAnnotation);
531 if (spans.size() > 0) {
532 addAnnotationHighlights(spans, annotationColor, DASHED_LINES);
533 if (!textSelectionChanged && scrollToSelection) {
534 select(spans.get(0).getStart()); // this here so that
535 // the textpane will
536 // scroll to the
537 // highlighted text.
538 textSelectionChanged = true;
539 }
540 }
541 }
542
543 annotationColor = displayColors.getColor(selectedAnnotation);
544 getSubtext(selectedAnnotation);
545 spans = annotationUtil.getSpans(selectedAnnotation);
546 if (spans.size() > 0) {
547 addAnnotationHighlights(spans, annotationColor, SOLID_LINES);
548 if(scrollToSelection) {
549 select(spans.get(0).getStart()); // we do this so that the
550 // textpane will scroll to the
551 // highlighted annotation.
552 }
553 }
554 selectedAnnotationSpans.addAll(spans);
555 }
556 }
557
558 public void highlightSpans(SimpleInstance selectedAnnotation, java.util.List<SimpleInstance> annotations, boolean scrollToSelection)
559 throws InvalidSpanException {
560 logger.debug("");
561 clearHighlights();
562 highlightSelectedInstance(selectedAnnotation, scrollToSelection);
563 Set<SimpleInstance> referencedAnnotations;
564 if (selectedAnnotation != null)
565 referencedAnnotations = annotationUtil.getRelatedAnnotations((SimpleInstance) selectedAnnotation);
566 else
567 referencedAnnotations = Collections.emptySet();
568
569 if (annotations != null) {
570 for (SimpleInstance annotation : annotations) {
571 if (!annotation.equals(selectedAnnotation) && !referencedAnnotations.contains(annotation)) {
572 Color annotationColor = displayColors.getColor(annotation);
573 getSubtext(annotation);
574 if (manager.getFadeUnselectedAnnotations())
575 annotationColor = DisplayColors.getBackgroundColor(annotationColor);
576 if (manager.isConsensusMode() && annotationUtil.hasTeamAnnotator(annotation)) {
577 annotationColor = DisplayColors.getBackgroundColor(annotationColor);
578 }
579 java.util.List<Span> spans = annotationUtil.getSpans(annotation);
580 addAnnotationHighlights(spans, annotationColor, NO_LINES);
581 }
582 }
583 }
584 populateSpan2Annotations(annotations);
585 updateAnnotationLines();
586 hideHighlights();
587 showSelectionHighlights();
588 showAnnotationHighlights();
589 }
590
591 private void populateSpan2Annotations(Collection<SimpleInstance> annotations) {
592 logger.debug("");
593 window2AnnotationsMap.clear();
594 for (SimpleInstance annotation : annotations) {
595 List<Span> spans = annotationUtil.getSpans(annotation);
596 for (Span span : spans) {
597 int startKey = span.getStart() / windowSize;
598 int endKey = span.getEnd() / windowSize;
599 for (int key = startKey; key <= endKey; key++) {
600 if (!window2AnnotationsMap.containsKey(key)) {
601 window2AnnotationsMap.put(key, new HashSet<SimpleInstance>());
602 }
603 window2AnnotationsMap.get(key).add(annotation);
604 }
605 }
606 }
607 }
608
609 private Collection<SimpleInstance> getAnnotationsAt(int offset) {
610 logger.debug("");
611 Integer key = new Integer(offset / windowSize);
612 Collection<SimpleInstance> returnValues = new ArrayList<SimpleInstance>();
613 if (window2AnnotationsMap.containsKey(key)) {
614 Set<SimpleInstance> candidateAnnotations = window2AnnotationsMap.get(key);
615 for (SimpleInstance annotation : candidateAnnotations) {
616 List<Span> spans = annotationUtil.getSpans(annotation);
617 for (Span span : spans) {
618 if (offset >= span.getStart() && offset <= span.getEnd()) {
619 returnValues.add(annotation);
620 break;
621 }
622 }
623 }
624 }
625 return returnValues;
626 }
627
628 private void showContextMenu(MouseEvent mouseEvent) {
629 logger.debug("");
630 popupMenu.removeAll();
631 int offset = viewToModel(mouseEvent.getPoint());
632 List<SimpleInstance> clickedAnnotations = new ArrayList<SimpleInstance>(getAnnotationsAt(offset));
633 if (clickedAnnotations == null || clickedAnnotations.size() == 0)
634 return;
635 Collections.sort(clickedAnnotations, spanUtil.comparator(browserTextUtil.comparator()));
636
637 for (final SimpleInstance annotation : clickedAnnotations) {
638 JMenuItem menuItem = new JMenuItem("select: " + browserTextUtil.getBrowserText(annotation, 50),
639 displayColors.getIcon(displayColors.getColor(annotation)));
640 menuItem.addActionListener(new ActionListener() {
641 public void actionPerformed(ActionEvent actionEvent) {
642 manager.setSelectedAnnotation(annotation);
643 }
644 });
645 menuItem.addMouseListener(new MouseAdapter() {
646 public void mouseEntered(MouseEvent event) {
647 highlightAnnotationTemp(annotation);
648 }
649
650 public void mouseExited(MouseEvent event) {
651 manager.refreshAnnotationsDisplay(true);
652 }
653 });
654 popupMenu.add(menuItem);
655 }
656
657 try {
658 SimpleInstance annotation = manager.getSelectedAnnotation();
659 final SimpleInstance mention = annotationUtil.getMention(annotation);
660 final Cls cls = manager.getMentionUtil().getMentionCls(mention);
661 if (cls != null) {
662 Collection<Slot> slots = cls.getDirectTemplateSlots();
663 for (final Slot slot : slots) {
664 if (slot.getBrowserText().startsWith(":"))
665 continue;
666 final SimpleInstance slotMention = mentionUtil.getSlotMention(mention, slot);
667 if (slotMention == null)
668 continue;
669
670 List<SimpleInstance> slotFillerCandidates = manager.getMentionUtil().getSlotFillerCandidates(
671 mention, slot, clickedAnnotations);
672 for (final SimpleInstance candidate : slotFillerCandidates) {
673 String slotLabel = ProtegeUtil.getSlotLabel(cls, slot, manager.getKnowledgeBase().getProject());
674 // String annotationText =
675 // browserTextUtil.getBrowserText(annotation);
676 // <b>"+annotationText+"</b>
677 JMenuItem menuItem = new JMenuItem("<html>fill " + "<b>" + slotLabel
678 + "</b> slot of selected annotation with " + "<b>"
679 + browserTextUtil.getBrowserText(candidate, 50) + "</b></html>");
680 menuItem.addActionListener(new ActionListener() {
681 public void actionPerformed(ActionEvent actionEvent) {
682 mentionUtil.addValueToSlotMention(slotMention, annotationUtil.getMention(candidate));
683 mentionUtil.adjustSlotMentionForCardinality(cls, slot, mention);
684 mentionUtil.addInverse(mention, slot, annotationUtil.getMention(candidate));
685
686 refreshAnnotationsDisplay(true);
687 }
688 });
689 popupMenu.add(menuItem);
690 }
691 }
692 }
693
694 } catch (NullPointerException npe) {
695 npe.printStackTrace();
696 }
697
698 if (popupMenu.getSubElements().length == 1)
699 selectAnnotation(offset);
700 else if (popupMenu.getSubElements().length > 1)
701 popupMenu.show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY() + 10);
702 }
703
704 private String getSubtext(SimpleInstance annotation) {
705 try {
706 Slot subtextSlot = manager.getSubtextSlot();
707 if (subtextSlot == null)
708 return null;
709 SimpleInstance mention = annotationUtil.getMention(annotation);
710 SimpleInstance slotMention = mentionUtil.getSlotMention(mention, subtextSlot);
711 List<Object> slotValues = mentionUtil.getSlotMentionValues(slotMention);
712 if (slotValues != null && slotValues.size() > 0) {
713 String subtext = slotValues.get(0).toString();
714 List<Span> spans = annotationUtil.getSpans(annotation);
715 if (subtext != null && !subtext.trim().equals("") && spans != null) {
716 for (Span span : spans)
717 annotationSpanSubtexts.put(span, subtext);
718 }
719
720 return subtext;
721 }
722 } catch (NullPointerException npe) {
723 return null;
724 }
725
726 return null;
727 }
728
729 private KnowtatorHighlighter getHighlightPainter(Color color, int lines) {
730 logger.debug("");
731 if (lines == SOLID_LINES) {
732 if (!linePainters.containsKey(color))
733 linePainters.put(color, new KnowtatorSelectionHighlighter(color));
734 return linePainters.get(color);
735 } else if (lines == DASHED_LINES) {
736 if (!dashedLinePainters.containsKey(color))
737 dashedLinePainters.put(color, new KnowtatorDashedHighlighter(color));
738 return dashedLinePainters.get(color);
739
740 } else if (lines == VERTICAL_LINES) {
741 if (!verticalLinePainters.containsKey(color))
742 verticalLinePainters.put(color, new KnowtatorVerticalHighlighter(color));
743 return verticalLinePainters.get(color);
744 } else {
745 if (!painters.containsKey(color))
746 painters.put(color, new KnowtatorHighlighter(color));
747 return painters.get(color);
748 }
749 }
750
751 /**
752 * This code was taken right out of its superclass
753 * DefaultHighlighter.DefaultHighlightPainter and modified to draw lines
754 * above and below the selected annotation.
755 */
756 class KnowtatorHighlighter extends DefaultHighlighter.DefaultHighlightPainter {
757
758 public KnowtatorHighlighter(Color c) {
759 super(c);
760 }
761
762 public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c, View view) {
763 logger.debug("");
764 Shape returnValue = super.paintLayer(g, offs0, offs1, bounds, c, view);
765
766 g.setColor(lineHighlightColor);
767 Font textFont = UIManager.getFont("TextArea.font");
768 int fontSize = textFont.getSize();
769 g.setFont(new Font(textFont.getName(), textFont.getStyle(), fontSize));
770
771 Rectangle rec = getRectangle(offs0, offs1, bounds, view);
772 if (rec != null) {
773 int start = viewToModel(new Point(rec.x, rec.y));
774 int end = viewToModel(new Point(rec.x + rec.width, rec.y));
775 String subtext = annotationSpanSubtexts.get(new Span(start, end));
776 if (subtext != null) {
777 FontMetrics fontMetrics = g.getFontMetrics();
778 int stringWidth = fontMetrics.stringWidth(subtext);
779 int startPoint = rec.x + (rec.width / 2);
780 startPoint = startPoint - (stringWidth / 2);
781 startPoint = Math.max(0, startPoint);
782 g.drawString(subtext, startPoint, rec.y + rec.height + fontSize + 3);
783 }
784 }
785 return returnValue;
786 }
787
788 public Rectangle getRectangle(int offs0, int offs1, Shape bounds, View view) {
789 logger.debug("");
790 Rectangle rec = null;
791 if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) {
792 rec = (bounds instanceof Rectangle) ? (Rectangle) bounds : bounds.getBounds();
793 } else {
794 try {
795 Shape shape = view.modelToView(offs0, Position.Bias.Forward, offs1, Position.Bias.Backward, bounds);
796 rec = (shape instanceof Rectangle) ? (Rectangle) shape : shape.getBounds();
797 } catch (BadLocationException e) {
798 }
799 }
800 return rec;
801 }
802 }
803
804 /**
805 * This code was taken right out of its superclass
806 * DefaultHighlighter.DefaultHighlightPainter and modified to draw lines
807 * above and below the selected annotation.
808 */
809 class KnowtatorSelectionHighlighter extends KnowtatorHighlighter {
810 public KnowtatorSelectionHighlighter(Color c) {
811 super(c);
812 }
813
814 public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c, View view) {
815 logger.debug("");
816 Shape returnValue = super.paintLayer(g, offs0, offs1, bounds, c, view);
817
818 g.setColor(lineHighlightColor);
819
820 Rectangle rec = getRectangle(offs0, offs1, bounds, view);
821 if (rec != null) {
822 g.drawLine(rec.x, rec.y, rec.x + rec.width - 1, rec.y);
823 g.drawLine(rec.x, rec.y - 1, rec.x + rec.width - 1, rec.y - 1);
824 g.drawLine(rec.x, rec.y + rec.height, rec.x + rec.width - 1, rec.y + rec.height);
825 g.drawLine(rec.x, rec.y + rec.height + 1, rec.x + rec.width - 1, rec.y + rec.height + 1);
826 }
827 return returnValue;
828 }
829 }
830
831 class KnowtatorDashedHighlighter extends KnowtatorHighlighter {
832 public KnowtatorDashedHighlighter(Color c) {
833 super(c);
834 }
835
836 public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c, View view) {
837 logger.debug("");
838 Shape returnValue = super.paintLayer(g, offs0, offs1, bounds, c, view);
839
840 Rectangle rec = getRectangle(offs0, offs1, bounds, view);
841 if (rec != null) {
842 drawDashedLine(g, rec.x, rec.x + rec.width - 1, rec.y);
843 drawDashedLine(g, rec.x, rec.x + rec.width - 1, rec.y - 1);
844 drawDashedLine(g, rec.x, rec.x + rec.width - 1, rec.y + rec.height);
845 drawDashedLine(g, rec.x, rec.x + rec.width - 1, rec.y + rec.height + 1);
846 }
847 return returnValue;
848 }
849
850 private void drawDashedLine(Graphics g, int x1, int x2, int y) {
851 logger.debug("");
852 if (x1 >= x2) {
853 logger.debug("x1 is larger than x2");
854 return;
855 }
856 for (int x = x1; x < x2; x += 10) {
857 g.drawLine(x, y, Math.min(x + 5, x2), y);
858 }
859 g.drawLine(x2, y, x2 - 2, y);
860 }
861 }
862
863 class KnowtatorVerticalHighlighter extends KnowtatorHighlighter {
864 public KnowtatorVerticalHighlighter(Color c) {
865 super(c);
866 }
867
868 public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c, View view) {
869 logger.debug("");
870 Shape returnValue = super.paintLayer(g, offs0, offs1, bounds, c, view);
871
872 Rectangle rec = getRectangle(offs0, offs1, bounds, view);
873 if (rec != null) {
874 g.drawLine(rec.x, rec.y, rec.x, rec.y + rec.height - 1);
875 }
876 return returnValue;
877 }
878 }
879
880 private MouseListener createMouseListener() {
881 return new MouseAdapter() {
882 public void mousePressed(MouseEvent mouseEvent) {
883 logger.debug("");
884 hideHighlights();
885 if (!mouseEvent.isControlDown()) {
886 clearSelectionHighlights();
887 } else {
888 showSelectionHighlights();
889 }
890 mouseButtonDown = true;
891 }
892
893 public void mouseClicked(MouseEvent mouseEvent) {
894 logger.debug("");
895 showContextMenu(mouseEvent);
896 // int offset = viewToModel(mouseEvent.getPoint());
897 // selectAnnotation(offset);
898 }
899
900 public void mouseReleased(MouseEvent mouseEvent) {
901 logger.debug("");
902
903 mouseButtonDown = false;
904 if (getSelectionStart() != getSelectionEnd()) {
905 Span selectedSpan = new Span(getSelectionStart(), getSelectionEnd());
906 updateTokenRegex();
907 Span expandedSpan = SpanUtil.expandToSplits(text, selectedSpan, 15, 15, tokenPattern);
908 if (expandedSpan != null) {
909 select(expandedSpan);
910 }
911 showSelectionHighlights();
912 }
913 showAnnotationHighlights();
914
915 boolean fastAnnotateMode = manager.isFastAnnotateMode();
916 Frame fastAnnotateFrame = manager.getFastAnnotateFrame();
917 if (fastAnnotateMode && fastAnnotateFrame != null && manager.getSelectedSpans().size() > 0) {
918 manager.createAnnotation((Instance) fastAnnotateFrame);
919 }
920 }
921 };
922 }
923
924 private KeyListener createKeyListener() {
925 return new KeyAdapter() {
926 public void keyReleased(KeyEvent keyEvent) {
927 logger.debug("");
928 if (keyEvent.getKeyCode() == KeyEvent.VK_CONTROL && mouseButtonDown) {
929 hideHighlights();
930 clearSelectionHighlights();
931 }
932 }
933 };
934 }
935
936 }