source: trunk/gsdl/src/phind/client/ResultCanvas.java@ 1680

Last change on this file since 1680 was 1680, checked in by paynter, 23 years ago

Highlight occurances of the wors in the phrase when we open a document
(i.e. pass the words in as "query term" arguments in the cgi script).

  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/**********************************************************************
2 *
3 * ResultCanvas.java -- a Canvas onto which a phrase list is drawn
4 *
5 * Copyright 1997-2000 Gordon W. Paynter
6 * Copyright 2000 The New Zealand Digital Library Project
7 *
8 * A component of the Greenstone digital library software
9 * from the New Zealand Digital Library Project at the
10 * University of Waikato, New Zealand.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 *********************************************************************/
27
28/*********************************************************************
29
30This class is used in the Phind java applet (Phind.java).
31
32The results of a query are displayed on a ResultCanvas object. Each
33line of the result is stored in a ResultItem, and the ResultCanvas
34contains a Vector of ResultItems.
35
36Each ResultCanvas is embedded in a ResultBox alongside a Scrollbar.
37When the ResultCanvas is drawn, it looks at the scrollbar, calculates
38which ResultItems are visible, then draws them on the screen.
39
40**********************************************************************/
41
42
43import java.awt.Canvas;
44import java.awt.Scrollbar;
45import java.awt.Graphics;
46import java.awt.Font;
47import java.awt.FontMetrics;
48import java.awt.Dimension;
49import java.awt.Color;
50import java.util.Vector;
51import java.awt.Image;
52import java.awt.Event;
53
54import java.net.URL;
55import java.applet.Applet;
56import java.util.Date;
57
58public class ResultCanvas extends Canvas {
59
60 // Other objects associated with this
61 Phind phind;
62 ResultBox parent;
63 Scrollbar scrollbar;
64
65 // fonts and font spacings to use
66 Font areaPlain, areaBold;
67 int lineSpacing;
68
69 // The phrases to display on this canvas
70 int numberOfPhrases;
71 int firstPhraseDisplayed;
72 int phraseSelected;
73 Vector phrases;
74
75 // the background image
76 public static Image backgroundImage;
77
78
79 // Create a ResultCanvas from the ResultBox which is its parent.
80 ResultCanvas(ResultBox p) {
81
82 parent = p;
83 phind = p.phind;
84 scrollbar = p.s;
85 parent.disableScrollbar();
86
87 areaPlain = phind.plainFont;
88 areaBold = phind.boldFont;
89
90 lineSpacing = phind.fontSize + 2;
91
92 phrases = new Vector();
93 numberOfPhrases = 0;
94 firstPhraseDisplayed = 0;
95 phraseSelected = -1;
96
97 if (backgroundImage == null) {
98 backgroundImage = p.phind.backgroundImage;
99 }
100
101 }
102
103 void resetCanvas( ) {
104 phrases.removeAllElements();
105 numberOfPhrases = 0;
106 repaint();
107 }
108
109
110 // add a new item of input.
111 // return true if successful, otherwise false.
112 boolean addResultItem( ResultItem item ) {
113
114 // Add a new result, in sorted order.
115 // First sort key is item kind (lowest first),
116 // second is frequency (highest first).
117 // This is not efficient, but I don't care right now.
118 int index = 0;
119 while ((index < numberOfPhrases) &&
120 ((item.kind > ((ResultItem) phrases.elementAt(index)).kind) ||
121 ((item.kind == ((ResultItem) phrases.elementAt(index)).kind) &&
122 (item.freq <= ((ResultItem) phrases.elementAt(index)).freq)))) {
123 index++;
124 }
125 phrases.insertElementAt(item,index);
126 numberOfPhrases++;
127 return true;
128 }
129
130
131 // Make sure the more Phrases item only appears in the list
132 // if it is meant to.
133 void updateMorePhrasesMarker() {
134
135 // System.out.println("updateMorePhrasesMarker() ");
136
137 // look for a marker
138 boolean found = false;
139 int index = 0;
140 while (!found && (index < numberOfPhrases)) {
141 if (((ResultItem) phrases.elementAt(index)).isMorePhrases()) {
142 // System.out.println("found marker at: " + index + " of " + numberOfPhrases);
143 found = true;
144 } else {
145 index++;
146 }
147 }
148
149 if (parent.expansionsRetrieved == parent.numberOfExpansions) {
150 // there should be no marker
151 // System.out.println("No marker needed");
152 if (found) {
153 // System.out.println("Remove marker");
154 phrases.removeElementAt(index);
155 numberOfPhrases--;
156 }
157
158 } else if (parent.expansionsRetrieved < parent.numberOfExpansions) {
159 // there should be a marker
160 // System.out.println("Needs marker");
161
162 if (!found) {
163 // System.out.println("Add marker");
164 ResultItem ri = new ResultItem(ResultItem.morePhrases, parent.searchKey);
165 addResultItem(ri);
166 }
167 }
168 }
169
170
171 // Make sure the more documents marker appears when required
172 void updateMoreDocumentsMarker() {
173
174 // System.out.println("updateMoreDocumentsMarker() ");
175
176 // look for a marker
177 boolean found = false;
178 int index = 0;
179 while (!found && (index < numberOfPhrases)) {
180 if (((ResultItem) phrases.elementAt(index)).isMoreDocuments()) {
181 found = true;
182 } else {
183 index++;
184 }
185 }
186
187 if (parent.documentsRetrieved == parent.numberOfDocuments) {
188 // there should be no marker
189 if (found) {
190 phrases.removeElementAt(index);
191 numberOfPhrases--;
192 }
193
194 } else if (parent.documentsRetrieved < parent.numberOfDocuments) {
195 // there should be a marker
196 if (!found) {
197 ResultItem ri = new ResultItem(ResultItem.moreDocuments, parent.searchKey);
198 addResultItem(ri);
199 }
200 }
201 }
202
203
204
205
206
207
208 public void update(Graphics g) {
209 paint(g);
210 }
211
212 public void paint(Graphics g) {
213
214 // calculate the canvas size, margins, and spacing
215 Dimension canvasSize = getSize();
216
217 g.setFont(areaPlain);
218 int space = g.getFontMetrics().stringWidth(" ");
219 int margin = g.getFontMetrics().stringWidth(" 8888 ");
220
221 int leftMargin = 0;
222 int secondColumn = canvasSize.width - margin;
223 int firstColumn = secondColumn - margin;
224 int rightMargin = firstColumn;
225
226 // calculate the number of values that will fit onscreen
227 int visible = canvasSize.height / lineSpacing;
228
229 // get the initial scrollbar setting
230 // and calculate the first result to output
231 int scrollValue = scrollbar.getValue();
232 if (numberOfPhrases <= visible) {
233 scrollValue = 0;
234 } else if (scrollValue > (numberOfPhrases - visible)) {
235 scrollValue = numberOfPhrases - visible;
236 }
237 firstPhraseDisplayed = scrollValue;
238
239 // Draw the phrase area
240
241 // draw the background
242 if (phind.showImage) {
243 try {
244 g.drawImage(backgroundImage,
245 leftMargin, 0, rightMargin, canvasSize.height,
246 Color.white, null);
247 } catch (Exception e) {
248 phind.showImage = false;
249 System.err.println("ResultCanvas paint error: " + e);
250 g.setColor(Color.white);
251 g.fillRect(0, 0, canvasSize.width, canvasSize.height);
252 }
253 } else {
254 g.setColor(Color.white);
255 g.fillRect(0, 0, canvasSize.width, canvasSize.height);
256 }
257
258 // If there are no phrases, output a brief explanation.
259 if (numberOfPhrases == 0) {
260 g.drawString("No phrases match this query.", leftMargin + 10, lineSpacing);
261 }
262
263 // Output each of the visible ResultItems
264 ResultItem result;
265 int tab, i, y = 0;
266 int center = leftMargin
267 + ((rightMargin - leftMargin
268 - g.getFontMetrics().stringWidth(parent.searchPhrase)) / 2);
269
270 for (i = scrollValue;
271 (i < numberOfPhrases) && (y + lineSpacing < canvasSize.height); i++) {
272
273 // Get the resultItem to output
274 result = (ResultItem) phrases.elementAt(i);
275
276 // Graphics settings for drawing this line
277 y += lineSpacing;
278 g.setFont(areaPlain);
279
280 // Highlight if the selected phrase.
281 if (i == phraseSelected) {
282 g.setColor(new Color(255, 220, 115));
283 g.fillRect(leftMargin, y-lineSpacing+2, rightMargin, lineSpacing);
284 g.setColor(Color.black);
285 }
286
287 // Draw the item
288
289 if (result.isPhrase()) {
290 // The item is a Phrase
291 tab = center - g.getFontMetrics().stringWidth(result.prefix) - space;
292 g.drawString(result.prefix, tab, y);
293 g.setFont(areaBold);
294 g.drawString(result.body, center, y);
295 tab = center + space + g.getFontMetrics().stringWidth(result.body);
296 g.setFont(areaPlain);
297 g.drawString(result.suffix, tab, y);
298
299 } else if (result.isDocument()){
300 // The item is a URL
301 g.setFont(areaPlain);
302 g.setColor(Color.blue);
303 tab = (rightMargin - g.getFontMetrics().stringWidth(result.body)) / 2;
304 g.drawString(result.body, tab, y);
305 g.setColor(Color.black);
306
307 } else if (result.isMorePhrases()){
308 // The item is a More documents marker
309 g.setColor(new Color(255, 200, 200));
310 g.fillRect(leftMargin, y-lineSpacing+2, rightMargin, lineSpacing);
311 g.setColor(Color.black);
312
313 g.setFont(areaPlain);
314 tab = (rightMargin - g.getFontMetrics().stringWidth("Get more phrases")) / 2;
315 g.drawString("Get more phrases", tab, y);
316
317 } else if (result.isMoreDocuments()){
318 // The item is a More documents marker
319 g.setColor(new Color(150, 193, 156));
320 g.fillRect(leftMargin, y-lineSpacing+2, rightMargin, lineSpacing);
321 g.setColor(Color.black);
322
323 g.setFont(areaPlain);
324 tab = (rightMargin - g.getFontMetrics().stringWidth("Get more documents")) / 2;
325 g.drawString("Get more documents", tab, y);
326
327 }
328
329 }
330
331 // Draw the frequecy columns
332
333 // column backgrounds
334 g.setColor(new Color(235, 245, 235));
335 g.fillRect(firstColumn, 0, margin, canvasSize.height);
336 g.setColor(new Color(200, 220, 200));
337 g.fillRect(secondColumn, 0, margin, canvasSize.height);
338
339 // fill in the numbers
340 g.setColor(Color.black);
341 g.setFont(areaPlain);
342 y = 0;
343
344 for (i = scrollValue;
345 (i < numberOfPhrases) && (y + lineSpacing < canvasSize.height); i++) {
346
347 // Get the resultItem to output
348 result = (ResultItem) phrases.elementAt(i);
349
350 // Graphics settings for drawing this line
351 y += lineSpacing;
352
353 // Write the document frequency
354 if ((result.documents > 1) || result.isPhrase()) {
355 g.drawString(" " + Integer.toString(result.documents), firstColumn, y);
356 }
357
358 // Write the term frequency
359 if (result.freq > 0) {
360 g.drawString(" " + Integer.toString(result.freq), secondColumn, y);
361 }
362 }
363
364 // Adjust the scrollbar
365 if (visible >= numberOfPhrases) {
366 parent.disableScrollbar();
367 } else {
368 //System.out.println("s " + scrollValue + ", v " + visible
369 // + ", m " + (numberOfPhrases));
370 scrollbar.setValues(scrollValue, visible, 0, numberOfPhrases);
371 scrollbar.setBlockIncrement(visible - 1);
372 scrollbar.setEnabled(true);
373 }
374
375 g.drawRect(0,0, canvasSize.width - 1, canvasSize.height - 1);
376 }
377
378
379 // User interaction
380 //
381 // All interaction with the ResultCanvas is therough mouse clicks, and
382 // is handles in this method. Note we ignore clicks that follow
383 // another too closely to avoid problems with slow connections.
384 public boolean handleEvent(Event event) {
385
386 if (event.id == Event.MOUSE_UP) {
387
388 // ignore actions that occur within 1 second of the last
389 Date now = new Date();
390 // System.out.println("Click time: " + now.toString());
391 if (now.getTime() < (phind.lastQueryEndTime.getTime() + 1000)) {
392 System.out.println("Ignoring click - too close to last query.");
393 return true;
394 }
395
396 // which Item is selected?
397 int rowSelected = event.y / lineSpacing;
398 int itemSelected = rowSelected + firstPhraseDisplayed;
399 ResultItem item = (ResultItem) phrases.elementAt(itemSelected);
400
401 // System.out.println("Select: " + String.valueOf(rowSelected) );
402 if (itemSelected <= numberOfPhrases) {
403
404 // What do we do with the event?
405 // If user clicks on a phrase, we expand the phrase
406 // or send the phrase to a search engine (right click)
407
408 if (item.isPhrase()) {
409 // Expand the phrase
410
411 phraseSelected = itemSelected;
412 update(getGraphics());
413
414 parent.lookupPhrase(item.rule, item.toString(), 2);
415
416 if (event.metaDown()) {
417 // Also send to search engine
418 if (phind.search_url.equals("none") || phind.search_url.equals("")) {
419 System.out.println("No searching in this collection");
420 } else {
421 URL url;
422 try {
423 url = new URL(phind.search_url + "%22" + item.toString() + "%22&");
424 phind.getAppletContext().showDocument(url, "phindsearch");
425 System.out.println("The query is: " + url.toString());
426 } catch (Exception e) {
427 System.out.println("URL error: " + e.toString());
428 }
429 }
430 }
431
432 } else if (item.isDocument()) {
433 // The user clicks on a URL; display it.
434 phraseSelected = itemSelected;
435 update(getGraphics());
436
437 URL url;
438 try {
439 String address = phind.library_address
440 + "a=d&c=" + phind.collection
441 + "&d=" + item.rule
442 + "&q=" + parent.searchPhrase.replace(' ', '+');
443 url = new URL(address);
444 System.out.println("URL selected: " + url.toString());
445 phind.getAppletContext().showDocument(url, "phindselect");
446 } catch (Exception e) {
447 System.out.println("URL error: " + e.toString());
448 }
449
450 } else if (item.isMorePhrases()){
451 // The user clicks on a "get more phrases" marker.
452 // We have to send a new query to the host
453 parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 3);
454
455 } else if (item.isMoreDocuments()){
456 parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 4);
457
458
459 }
460 repaint();
461 }
462 }
463 return true;
464 }
465
466}
467
468
469
Note: See TracBrowser for help on using the repository browser.