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 }