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 }