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 029 /** 030 * Changes: 031 * 8/11/2005 pvo modified highlightSelectedInstance such that annotations 032 * referenced by the selected instance are also highlighted. 033 */ 034 package edu.uchsc.ccp.knowtator.ui; 035 036 /** 037 * 038 * changes 1/23/2006 added 039 * textPane.setFont(UIManager.getFont("TextArea.font")); 040 * to initialize method 041 */ 042 043 import java.awt.BorderLayout; 044 import java.awt.Color; 045 import java.awt.Point; 046 import java.awt.Rectangle; 047 import java.io.PrintWriter; 048 import java.io.StringWriter; 049 import java.util.Comparator; 050 import java.util.List; 051 052 import javax.swing.BorderFactory; 053 import javax.swing.JOptionPane; 054 import javax.swing.JPanel; 055 import javax.swing.JScrollBar; 056 import javax.swing.JScrollPane; 057 import javax.swing.UIManager; 058 import javax.swing.border.TitledBorder; 059 import javax.swing.event.ChangeEvent; 060 import javax.swing.event.ChangeListener; 061 import javax.swing.text.BadLocationException; 062 063 import edu.stanford.smi.protege.model.SimpleInstance; 064 import edu.uchsc.ccp.knowtator.KnowtatorManager; 065 import edu.uchsc.ccp.knowtator.Span; 066 import edu.uchsc.ccp.knowtator.SpanUtil; 067 import edu.uchsc.ccp.knowtator.event.EventHandler; 068 import edu.uchsc.ccp.knowtator.event.FilterChangedEvent; 069 import edu.uchsc.ccp.knowtator.event.FilterChangedListener; 070 import edu.uchsc.ccp.knowtator.textsource.TextSource; 071 import edu.uchsc.ccp.knowtator.textsource.TextSourceChangeEvent; 072 import edu.uchsc.ccp.knowtator.textsource.TextSourceChangeListener; 073 074 public class TextViewer implements TextSourceChangeListener, FilterChangedListener { 075 JPanel panel; 076 077 KnowtatorTextPane textPane; 078 079 JScrollPane scrollPane; 080 081 JScrollBar verticalScrollBar; 082 083 String textSourceDisplayText; 084 085 String filterInstanceDisplayText; 086 087 TitledBorder border; 088 089 KnowtatorManager manager; 090 091 Rectangle viewportBounds = null; 092 093 public TextViewer(KnowtatorTextPane textPane, KnowtatorManager manager) { 094 this.textPane = textPane; 095 this.manager = manager; 096 initialize(); 097 EventHandler.getInstance().addFilterChangedListener(this); 098 } 099 100 public Color getSelectedTextColor() { 101 Color selectionColor = textPane.getSelectionColor(); 102 return selectionColor; 103 } 104 105 public void initialize() { 106 scrollPane = new JScrollPane(textPane); 107 scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 108 scrollPane.getViewport().addChangeListener(new ChangeListener() { 109 public void stateChanged(ChangeEvent event) { 110 manager.updateVisibleFilteredAnnotations(); 111 manager.refreshAnnotationsDisplay(false); 112 } 113 }); 114 verticalScrollBar = scrollPane.getVerticalScrollBar(); 115 116 panel = new JPanel(new BorderLayout()); 117 panel.add(scrollPane, BorderLayout.CENTER); 118 border = BorderFactory.createTitledBorder(""); 119 border.setTitleFont(UIManager.getFont("Label.font")); 120 panel.setBorder(border); 121 122 textPane.setScrollPane(scrollPane); 123 } 124 125 public void filterChanged(FilterChangedEvent event) { 126 SimpleInstance filter = event.getNewFilter(); 127 setFilterInstanceDisplayText(filter.getBrowserText()); 128 } 129 130 public JPanel getContentPane() { 131 return panel; 132 } 133 134 public void textSourceChanged(TextSourceChangeEvent event) { 135 136 try { 137 TextSource textSource = event.getTextSource(); 138 setTextSourceDisplayText(textSource.getName()); 139 panel.repaint(); 140 panel.validate(); 141 textPane.setText(textSource.getText()); 142 verticalScrollBar.setValue(verticalScrollBar.getMinimum()); 143 manager.refreshAnnotationsDisplay(true); 144 } catch (Exception exception) { 145 StringWriter stackTraceWriter = new StringWriter(); 146 exception.printStackTrace(new PrintWriter(stackTraceWriter)); 147 String stackTrace = stackTraceWriter.toString(); 148 JOptionPane.showMessageDialog(panel, "Exception thrown when text source changed: " + "\n" + stackTrace, 149 "Exception", JOptionPane.ERROR_MESSAGE); 150 exception.printStackTrace(); 151 } 152 } 153 154 public void setTextSourceDisplayText(String textSourceDisplayText) { 155 this.textSourceDisplayText = textSourceDisplayText; 156 setBorderText(); 157 } 158 159 private void setFilterInstanceDisplayText(String filterInstanceDisplayText) { 160 this.filterInstanceDisplayText = filterInstanceDisplayText; 161 setBorderText(); 162 } 163 164 private void setBorderText() { 165 String borderText = ""; 166 if (textSourceDisplayText != null) 167 borderText = "text source: " + textSourceDisplayText; 168 if (filterInstanceDisplayText != null) 169 borderText = borderText + " filter: " + filterInstanceDisplayText; 170 border.setTitle(borderText); 171 panel.repaint(); 172 } 173 174 public KnowtatorTextPane getTextPane() { 175 return textPane; 176 } 177 178 /** 179 * Calculates the verticle distance in pixels between annotation1 and 180 * annotation2 as they appear in the text. If annotation1 comes before 181 * annotation2 in the text, then the vertical distance will be a positive 182 * number. The spans compared are the spans returned from 183 * SpanUtil.getFirstSpan() 184 * 185 * @param annotation1 186 * @param annotation2 187 * @return the calculated vertical distance or if spans do not exist, then 188 * Integer.MIN_VALUE 189 * @see SpanUtil#getFirstSpan(SimpleInstance) 190 */ 191 public int getVerticalDistance(SimpleInstance annotation1, SimpleInstance annotation2) { 192 Span span1 = manager.getSpanUtil().getFirstSpan(annotation1); 193 Span span2 = manager.getSpanUtil().getFirstSpan(annotation2); 194 195 if (span1 == null || span2 == null) 196 return Integer.MIN_VALUE; 197 198 try { 199 Rectangle span1Pos = textPane.modelToView(span1.getStart()); 200 Rectangle span2Pos = textPane.modelToView(span2.getStart()); 201 return span2Pos.y - span1Pos.y; 202 } catch (BadLocationException ble) { 203 ble.printStackTrace(); 204 return Integer.MIN_VALUE; 205 } 206 207 } 208 209 public boolean isVisible(SimpleInstance annotation) { 210 List<Span> spans = manager.getAnnotationUtil().getSpans(annotation); 211 Span span; 212 if(spans == null || spans.size() == 0) { 213 span = manager.getSpanUtil().getAReferencedSpan(annotation); 214 } else { 215 span = spans.get(0); 216 } 217 if (span != null) { 218 try { 219 Rectangle annotationLocation = textPane.modelToView(span.getStart()); 220 if (annotationLocation == null) 221 return false; 222 annotationLocation = new Rectangle(annotationLocation.x, annotationLocation.y, 1, 1); 223 Rectangle viewportBounds = scrollPane.getViewport().getViewRect(); 224 return viewportBounds.contains(annotationLocation); 225 } catch (BadLocationException ble) { 226 return false; 227 } 228 } 229 return false; 230 } 231 232 public Span getVisibleSpan() { 233 Rectangle viewportBounds = scrollPane.getViewport().getViewRect(); 234 int start = textPane.viewToModel(new Point(viewportBounds.x, viewportBounds.y)); 235 236 start = Math.max(0, start); 237 int end = textPane.viewToModel(new Point(viewportBounds.x + viewportBounds.width, viewportBounds.y 238 + viewportBounds.height)); 239 end = Math.max(end, start); 240 return new Span(start, end); 241 } 242 243 public Comparator<SimpleInstance> comparator(final SimpleInstance annotation) { 244 return new Comparator<SimpleInstance>() { 245 public int compare(SimpleInstance annotation1, SimpleInstance annotation2) { 246 boolean isVisible1 = isVisible(annotation1); 247 boolean isVisible2 = isVisible(annotation2); 248 if (isVisible1 && !isVisible2) 249 return -1; 250 if (!isVisible1 && isVisible2) 251 return 1; 252 else { 253 int distance1 = Math.abs(getVerticalDistance(annotation, annotation1)); 254 int distance2 = Math.abs(getVerticalDistance(annotation, annotation2)); 255 return distance1 <= distance2 ? -1 : 1; 256 } 257 } 258 }; 259 } 260 }