001 /*
002 * Copyright (c) 1995-2010, The University of Sheffield. See the file
003 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004 *
005 * This file is part of GATE (see http://gate.ac.uk/), and is free
006 * software, licenced under the GNU Library General Public License,
007 * Version 2, June 1991 (in the distribution as file licence.html,
008 * and also available at http://gate.ac.uk/gate/licence.html).
009 *
010 * Valentin Tablan 15 May 2002
011 *
012 * $Id: SearchPRViewer.java 12006 2009-12-01 17:24:28Z thomas_heitz $
013 */
014 package gate.gui;
015
016 import java.awt.*;
017 import java.awt.event.MouseAdapter;
018 import java.awt.event.MouseEvent;
019 import java.text.NumberFormat;
020 import java.util.*;
021 import java.util.List;
022
023 import javax.swing.*;
024 import javax.swing.table.AbstractTableModel;
025 import javax.swing.table.TableCellRenderer;
026
027 import gate.*;
028 import gate.creole.AbstractVisualResource;
029 import gate.creole.ir.*;
030 import gate.event.ProgressListener;
031 import gate.swing.XJTable;
032
033
034 /**
035 * Shows the results of a IR query. This VR is associated to
036 * {@link gate.creole.ir.SearchPR}.
037 */
038 public class SearchPRViewer extends AbstractVisualResource
039 implements ProgressListener{
040
041 public Resource init(){
042 initLocalData();
043 initGuiComponents();
044 initListeners();
045 return this;
046 }
047
048 protected void initLocalData(){
049 results = new ArrayList();
050 }
051
052 protected void initGuiComponents(){
053 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
054 resultsTableModel = new ResultsTableModel();
055 resultsTable = new XJTable(resultsTableModel);
056 resultsTable.getColumnModel().getColumn(1).
057 setCellRenderer(new FloatRenderer());
058 add(new JScrollPane(resultsTable));
059 // add(Box.createHorizontalGlue());
060 }
061
062 protected void initListeners(){
063 resultsTable.addMouseListener(new MouseAdapter() {
064 public void mouseClicked(MouseEvent e) {
065 if(e.getClickCount() == 2){
066 //where inside the table
067 selectDocument((String)resultsTable.getValueAt(
068 resultsTable.rowAtPoint(e.getPoint()), 0));
069 }
070 }
071 });
072 }
073
074 /**
075 * Tries to load (if necessary) and select (i.e. bring to front) a document
076 * based on its name.
077 */
078 protected void selectDocument(String documentName){
079 Corpus corpus = target.getCorpus();
080 int i = 0;
081 for(;
082 i < corpus.size() &&
083 (!corpus.getDocumentName(i).equals(documentName));
084 i++);
085 if(corpus.getDocumentName(i).equals(documentName)){
086 //trigger document loading if needed
087 Document doc = (Document)corpus.get(i);
088 //try to select the document
089 Component root = SwingUtilities.getRoot(this);
090 if(root instanceof MainFrame){
091 MainFrame mainFrame = (MainFrame)root;
092 mainFrame.select(doc);
093 }
094 }
095 }
096
097 /**
098 * Called by the GUI when this viewer/editor has to initialise itself for a
099 * specific object.
100 * @param target the object (be it a {@link gate.Resource},
101 * {@link gate.DataStore} or whatever) this viewer has to display
102 */
103 public void setTarget(Object target){
104 if(!(target instanceof SearchPR)){
105 throw new IllegalArgumentException(
106 "The GATE IR results viewer can only be used with a GATE search PR!\n" +
107 target.getClass().toString() + " is not a GATE search PR!");
108 }
109 this.target = (SearchPR)target;
110 this.target.addProgressListener(this);
111 }
112
113 /**
114 * Does nothing.
115 * @param i
116 */
117 public void progressChanged(int i){}
118
119 /**
120 * Called when the process is finished, fires a refresh for this VR.
121 */
122 public void processFinished(){
123 updateDisplay();
124 }
125
126 protected void updateDisplay(){
127 results.clear();
128 if(target != null){
129 QueryResultList resultsList = target.getResult();
130 Iterator resIter = resultsList.getQueryResults();
131 while(resIter.hasNext()){
132 results.add(resIter.next());
133 }
134 SwingUtilities.invokeLater(new Runnable(){
135 public void run(){
136 resultsTableModel.fireTableDataChanged();
137 }
138 });
139 }
140 }
141
142 protected class ResultsTableModel extends AbstractTableModel{
143 public int getRowCount(){
144 return results.size();
145 }
146
147 public int getColumnCount(){
148 return 2;
149 }
150
151 public String getColumnName(int columnIndex){
152 switch(columnIndex){
153 case DOC_NAME_COLUMN: return "Document";
154 case DOC_SCORE_COLUMN: return "Score";
155 default: return "?";
156 }
157 }
158
159 public Class getColumnClass(int columnIndex){
160 switch(columnIndex){
161 case DOC_NAME_COLUMN: return String.class;
162 case DOC_SCORE_COLUMN: return Float.class;
163 default: return Object.class;
164 }
165 }
166
167 public boolean isCellEditable(int rowIndex, int columnIndex){
168 return false;
169 }
170
171 public Object getValueAt(int rowIndex, int columnIndex){
172 QueryResult aResult = (QueryResult)results.get(rowIndex);
173 switch(columnIndex){
174 case DOC_NAME_COLUMN: return guessDocName(aResult.getDocumentID()).
175 toString();
176 case DOC_SCORE_COLUMN: return new Float(aResult.getScore());
177 default: return null;
178 }
179 }
180
181 /**
182 * Attempts to guess the document name from the ID returned by the searcher
183 */
184 protected Object guessDocName(Object docID){
185 //the doc ID is most likely the persistence ID for the doc
186 Corpus corpus = target.getCorpus();
187 DataStore ds = corpus.getDataStore();
188 if(ds != null){
189 try{
190 return ds.getLrName(docID);
191 }catch(Exception e){}
192 }
193 //we couldn't guess anything
194 return docID;
195 }
196
197 static private final int DOC_NAME_COLUMN = 0;
198 static private final int DOC_SCORE_COLUMN = 1;
199 }
200
201 protected class FloatRenderer extends JProgressBar
202 implements TableCellRenderer{
203 public FloatRenderer(){
204 setStringPainted(true);
205 setForeground(new Color(150, 75, 150));
206 setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
207 setMinimum(0);
208 //we'll use 3 decimal digits
209 setMaximum(1000);
210 numberFormat = NumberFormat.getInstance(Locale.getDefault());
211 numberFormat.setMaximumFractionDigits(3);
212 }
213
214
215 public Component getTableCellRendererComponent(JTable table,
216 Object value,
217 boolean isSelected,
218 boolean hasFocus,
219 int row,
220 int column){
221
222 float fValue = ((Float)value).floatValue();
223 setValue((int)(fValue * 1000));
224 setBackground(table.getBackground());
225
226 setString(numberFormat.format(value));
227 return this;
228 }
229
230 /*
231 * The following methods are overridden as a performance measure to
232 * to prune code-paths are often called in the case of renders
233 * but which we know are unnecessary.
234 */
235
236 /**
237 * Overridden for performance reasons.
238 */
239 public boolean isOpaque() {
240 Color back = getBackground();
241 Component p = getParent();
242 if (p != null) {
243 p = p.getParent();
244 }
245 // p should now be the JTable.
246 boolean colorMatch = (back != null) && (p != null) &&
247 back.equals(p.getBackground()) &&
248 p.isOpaque();
249 return !colorMatch && super.isOpaque();
250 }
251
252 /**
253 * Overridden for performance reasons.
254 */
255 public void validate() {}
256
257 /**
258 * Overridden for performance reasons.
259 */
260 public void revalidate() {}
261
262 /**
263 * Overridden for performance reasons.
264 */
265 public void repaint(long tm, int x, int y, int width, int height) {}
266
267 /**
268 * Overridden for performance reasons.
269 */
270 public void repaint(Rectangle r) { }
271
272 /**
273 * Overridden for performance reasons.
274 */
275 protected void firePropertyChange(String propertyName, Object oldValue,
276 Object newValue) {
277 // Strings get interned...
278 if (propertyName=="text") {
279 super.firePropertyChange(propertyName, oldValue, newValue);
280 }
281 }
282
283 /**
284 * Overridden for performance reasons.
285 */
286 public void firePropertyChange(String propertyName, boolean oldValue,
287 boolean newValue) { }
288
289 NumberFormat numberFormat;
290 }
291
292 /**
293 * The search PR this VR is associated to.
294 */
295 SearchPR target;
296
297 /**
298 * The table displaying the results
299 */
300 XJTable resultsTable;
301
302 /**
303 * The model for the results table.
304 */
305 ResultsTableModel resultsTableModel;
306
307 /**
308 * Contains the {@link gate.creole.ir.QueryResult} objects returned by the
309 * search.
310 */
311 List results;
312
313 }
|