source: trunk/gsdl/src/java/org/nzdl/gsdl/Phind/ResultCanvas.java@ 2507

Last change on this file since 2507 was 2507, checked in by sjboddie, 23 years ago

Tidied up the phind client a little more. It now belongs to the
org.nzdl.gsdl.Phind package and is compiled as a jar file. The jar file
itself is now included in the CVS tree in a new bin/java directory.

  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 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
33entry in the result list 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
42package org.nzdl.gsdl.Phind;
43
44import java.awt.Canvas;
45import java.awt.Scrollbar;
46import java.awt.Graphics;
47import java.awt.Font;
48import java.awt.FontMetrics;
49import java.awt.Dimension;
50import java.awt.Color;
51import java.util.Vector;
52import java.awt.Image;
53import java.awt.Event;
54
55import java.net.URL;
56import java.applet.Applet;
57import java.util.Date;
58
59public class ResultCanvas extends Canvas {
60
61 // Other objects associated with this
62 Phind phind;
63 ResultBox parent;
64 Scrollbar scrollbar;
65
66 // fonts and font spacings to use
67 Font areaPlain, areaBold;
68 int lineSpacing;
69
70 // The items to display on this canvas
71 int numberOfItems;
72 int firstItemDisplayed;
73 int itemSelected;
74 Vector items;
75
76 // the background image
77 public static Image backgroundImage;
78
79
80 // Create a ResultCanvas from the ResultBox which is its parent.
81 ResultCanvas(ResultBox p) {
82
83 parent = p;
84 phind = p.phind;
85 scrollbar = p.s;
86 parent.disableScrollbar();
87
88 areaPlain = phind.plainFont;
89 areaBold = phind.boldFont;
90
91 lineSpacing = phind.fontSize + 2;
92
93 items = new Vector();
94 numberOfItems = 0;
95 firstItemDisplayed = 0;
96 itemSelected = -1;
97
98 if (backgroundImage == null) {
99 backgroundImage = p.phind.backgroundImage;
100 }
101
102 }
103
104 void resetCanvas( ) {
105 items.removeAllElements();
106 numberOfItems = 0;
107 repaint();
108 }
109
110
111 // Add a new search result.
112 // Return true if successful, otherwise false.
113 boolean addResultItem( ResultItem item ) {
114
115 // Add a new result, in sorted order.
116 // First sort key is item kind (lowest first),
117 // second is frequency (highest first).
118 // This is not efficient, but I don't care right now.
119 int index = 0;
120 while ((index < numberOfItems) &&
121 ((item.sort < ((ResultItem) items.elementAt(index)).sort) ||
122 ((item.sort == ((ResultItem) items.elementAt(index)).sort) &&
123 (item.frequency <= ((ResultItem) items.elementAt(index)).frequency)))) {
124 index++;
125 }
126 items.insertElementAt(item,index);
127 numberOfItems++;
128 return true;
129 }
130
131
132 // Update more phrases/documents/links markers
133 void updateMarkers() {
134 updateMorePhrasesMarker();
135 updateMoreDocumentsMarker();
136 updateMoreLinksMarker();
137 }
138
139 // Make sure the more Phrases item only appears in the list
140 // if it is meant to.
141 void updateMorePhrasesMarker() {
142
143 // System.out.println("updateMorePhrasesMarker() ");
144
145 // look for a marker
146 boolean found = false;
147 int index = 0;
148 while (!found && (index < numberOfItems)) {
149 if (((ResultItem) items.elementAt(index)).isMorePhrases()) {
150 found = true;
151 } else {
152 index++;
153 }
154 }
155
156 if (parent.expansionsRetrieved == parent.numberOfExpansions) {
157 // there should be no marker
158 if (found) {
159 items.removeElementAt(index);
160 numberOfItems--;
161 }
162
163 } else if (parent.expansionsRetrieved < parent.numberOfExpansions) {
164 if (!found) {
165 ResultItem ri = new ResultItem(ResultItem.morePhrases);
166 addResultItem(ri);
167 }
168 }
169 }
170
171
172 // Make sure the more documents marker appears when required
173 void updateMoreDocumentsMarker() {
174
175 // System.out.println("updateMoreDocumentsMarker() ");
176
177 // look for a marker
178 boolean found = false;
179 int index = 0;
180 while (!found && (index < numberOfItems)) {
181 if (((ResultItem) items.elementAt(index)).isMoreDocuments()) {
182 found = true;
183 } else {
184 index++;
185 }
186 }
187
188 if (parent.documentsRetrieved == parent.numberOfDocuments) {
189 // there should be no marker
190 if (found) {
191 items.removeElementAt(index);
192 numberOfItems--;
193 }
194
195 } else if (parent.documentsRetrieved < parent.numberOfDocuments) {
196 // there should be a marker
197 if (!found) {
198 ResultItem ri = new ResultItem(ResultItem.moreDocuments);
199 addResultItem(ri);
200 }
201 }
202 }
203
204
205 // Make sure the more links marker appears when required
206 void updateMoreLinksMarker() {
207
208 // System.out.println("updateMoreLinksMarker() ");
209
210 // look for a marker
211 boolean found = false;
212 int index = 0;
213 while (!found && (index < numberOfItems)) {
214 if (((ResultItem) items.elementAt(index)).isMoreLinks()) {
215 found = true;
216 } else {
217 index++;
218 }
219 }
220
221 if (parent.thesaurusLinksRetrieved == parent.numberOfThesaurusLinks) {
222 // there should be no marker
223 if (found) {
224 items.removeElementAt(index);
225 numberOfItems--;
226 }
227
228 } else if (parent.thesaurusLinksRetrieved < parent.numberOfThesaurusLinks) {
229 // there should be a marker
230 if (!found) {
231 ResultItem ri = new ResultItem(ResultItem.moreLinks);
232 addResultItem(ri);
233 }
234 }
235 }
236
237
238
239
240
241
242 public void update(Graphics g) {
243 paint(g);
244 }
245
246 public void paint(Graphics g) {
247
248 // calculate the canvas size, margins, and spacing
249
250 // Note: the size() method is deprecated, but getSize fails in NetScape 4
251 // Dimension canvasSize = getSize();
252 Dimension canvasSize = size();
253
254 g.setFont(areaPlain);
255 int space = g.getFontMetrics().stringWidth(" ");
256 int nought = g.getFontMetrics().stringWidth("0");
257
258 int firstColumnWidth = phind.column_1_width * nought;
259 int secondColumnWidth = phind.column_2_width * nought;
260 int columnWidth = firstColumnWidth + secondColumnWidth;
261
262 int firstColumnLeft = canvasSize.width - columnWidth;
263 int secondColumnLeft = firstColumnLeft + firstColumnWidth;
264
265 int mainLeftMargin = 0;
266 int mainRightMargin = firstColumnLeft;
267
268 // the number of items that will fit on the canvas
269 int visible = canvasSize.height / lineSpacing;
270
271 // calculate the first item to output
272 int scrollValue = scrollbar.getValue();
273 if (numberOfItems <= visible) {
274 scrollValue = 0;
275 } else if (scrollValue > (numberOfItems - visible)) {
276 scrollValue = numberOfItems - visible;
277 }
278 firstItemDisplayed = scrollValue;
279
280 // Draw the phrase area
281 Color fore = phind.panel_fg;
282 Color back = phind.panel_bg;
283
284
285 // draw the background
286 if (phind.showImage) {
287 try {
288 g.drawImage(backgroundImage,
289 mainLeftMargin, 0, mainRightMargin, canvasSize.height,
290 back, null);
291 } catch (Exception e) {
292 phind.showImage = false;
293 System.err.println("ResultCanvas paint error: " + e);
294 g.setColor(back);
295 g.fillRect(0, 0, canvasSize.width, canvasSize.height);
296 }
297 } else {
298 g.setColor(back);
299 g.fillRect(0, 0, canvasSize.width, canvasSize.height);
300 }
301
302 // If there are no phrases, output a brief explanation.
303 if (numberOfItems == 0) {
304 g.drawString("No phrases match this query.", mainLeftMargin + 10, lineSpacing);
305 }
306
307 // Output each of the visible ResultItems
308 ResultItem result;
309 int tab, i, y = 0;
310 int center = mainLeftMargin
311 + ((mainRightMargin - mainLeftMargin
312 - g.getFontMetrics().stringWidth(parent.searchPhrase)) / 2);
313 int thesColumn = mainLeftMargin + firstColumnWidth
314 + g.getFontMetrics().stringWidth("Narrower term");
315
316 String body, prefix, suffix;
317
318 for (i = scrollValue;
319 (i < numberOfItems) && (y + lineSpacing < canvasSize.height); i++) {
320
321 // Get the resultItem to output
322 result = (ResultItem) items.elementAt(i);
323
324 // Graphics settings for drawing this line
325 y += lineSpacing;
326 g.setFont(areaPlain);
327
328 // Highlight the selected phrase.
329 if (i == itemSelected) {
330 g.setColor(phind.highlight_bg);
331 g.fillRect(mainLeftMargin, y-lineSpacing+2, mainRightMargin, lineSpacing);
332 }
333
334 // Draw the item
335
336 // Draw a phrase item
337 if (result.isPhrase()) {
338 prefix = result.prefixText();
339 body = result.mainText();
340 suffix = result.suffixText();
341
342 g.setColor(phind.expansion_fg);
343 g.setFont(areaPlain);
344 tab = center - g.getFontMetrics().stringWidth(prefix) - space;
345 g.drawString(prefix, tab, y);
346
347 g.setFont(areaBold);
348 g.drawString(body, center, y);
349
350 tab = center + space + g.getFontMetrics().stringWidth(body);
351 g.setFont(areaPlain);
352 g.drawString(suffix, tab, y);
353
354 }
355
356 // Draw a document item
357 else if (result.isDocument()){
358 body = result.mainText();
359
360 g.setColor(phind.document_fg);
361 g.setFont(areaPlain);
362 tab = (mainRightMargin - g.getFontMetrics().stringWidth(body)) / 2;
363 g.drawString(body, tab, y);
364
365 }
366
367 // Draw a thesaurus link item
368 else if (result.isLink()){
369 prefix = result.prefixText() + ":";
370 body = result.mainText();
371 tab = thesColumn - g.getFontMetrics().stringWidth(prefix) - space;
372
373 g.setColor(phind.thesaurus_fg);
374 g.setFont(areaPlain);
375 g.drawString(prefix, tab, y);
376 g.setFont(areaBold);
377 g.drawString(body, thesColumn, y);
378 }
379
380 // Draw a "more phrases/documents/links" marker
381 else if (result.isMorePhrases()
382 || result.isMoreDocuments()
383 || result.isMoreLinks()){
384 body = result.mainText();
385
386 if (result.isMorePhrases()) {
387 g.setColor(phind.expansion_bar_bg);
388 } else if (result.isMoreDocuments()) {
389 g.setColor(phind.document_bar_bg);
390 } else {
391 g.setColor(phind.thesaurus_bar_bg);
392 }
393 g.fillRect(mainLeftMargin, y-lineSpacing+2, mainRightMargin, lineSpacing);
394
395 if (result.isMorePhrases()) {
396 g.setColor(phind.expansion_bar_fg);
397 } else if (result.isMoreDocuments()) {
398 g.setColor(phind.document_bar_fg);
399 } else {
400 g.setColor(phind.thesaurus_bar_fg);
401 }
402 g.setFont(areaPlain);
403 tab = (mainRightMargin - g.getFontMetrics().stringWidth(body)) / 2;
404 g.drawString(body, tab, y);
405 }
406 }
407
408 // Draw the frequecy columns
409
410 // column backgrounds
411 g.setColor(phind.column_1_bg);
412 g.fillRect(firstColumnLeft, 0, firstColumnWidth, canvasSize.height);
413 g.setColor(phind.column_2_bg);
414 g.fillRect(secondColumnLeft, 0, secondColumnWidth, canvasSize.height);
415
416 // fill in the numbers
417 g.setColor(phind.column_1_fg);
418 g.setFont(areaPlain);
419 y = 0;
420 String docsText, freqText;
421
422 for (i = scrollValue;
423 (i < numberOfItems) && (y + lineSpacing < canvasSize.height); i++) {
424
425 // Get the resultItem to output
426 result = (ResultItem) items.elementAt(i);
427 docsText = result.docsText();
428 freqText = result.freqText();
429
430 // Graphics settings for drawing this line
431 y += lineSpacing;
432
433 // Write the document frequency
434 if (docsText.length() > 0) {
435 tab = secondColumnLeft - space - g.getFontMetrics().stringWidth(docsText);
436 g.drawString(docsText, tab, y);
437 }
438
439 // Write the term frequency
440 if (freqText.length() > 0) {
441 tab = secondColumnLeft + secondColumnWidth
442 - space - g.getFontMetrics().stringWidth(freqText);
443 g.drawString(freqText, tab, y);
444 }
445 }
446
447 // Adjust the scrollbar
448 if (visible >= numberOfItems) {
449 parent.disableScrollbar();
450 } else {
451 scrollbar.setValues(scrollValue, visible, 0, numberOfItems);
452 // Deprecated - setPageIncrement() has been replaced by
453 // setBlockIncrement(), but the latter doesn't work on some
454 // browsers. Damn.
455 // scrollbar.setBlockIncrement(visible - 1);
456 scrollbar.setPageIncrement(visible - 1);
457 // Deprecated - more nonsense: enable() has been replaced by
458 // setEnabled(true), but this doesn't work on some browsers.
459 //scrollbar.setEnabled(true);
460 scrollbar.enable();
461 }
462
463
464 // draw the border
465 if (phind.showBorder) {
466 g.setColor(phind.panel_fg);
467 g.drawRect(0,0, canvasSize.width - 1, canvasSize.height - 1);
468 }
469 }
470
471 // User interaction
472 //
473 // All interaction with the ResultCanvas is therough mouse clicks, and
474 // is handles in this method. Note we ignore clicks that follow
475 // another too closely to avoid problems with slow connections.
476 public boolean handleEvent(Event event) {
477
478 if (event.id == Event.MOUSE_UP) {
479
480 // ignore actions that occur within 1 second of the last
481 Date now = new Date();
482 // System.out.println("Click time: " + now.toString());
483 if (now.getTime() < (phind.lastQueryEndTime.getTime() + 1000)) {
484 System.out.println("Ignoring click - too close to last query.");
485 return true;
486 }
487
488 // which Item is selected?
489 int rowSelected = event.y / lineSpacing;
490 itemSelected = rowSelected + firstItemDisplayed;
491 ResultItem item = (ResultItem) items.elementAt(itemSelected);
492
493 if (itemSelected <= numberOfItems) {
494
495 //User clicks on a phrase
496 if (item.isPhrase()) {
497 itemSelected = itemSelected;
498 update(getGraphics());
499 parent.lookupPhrase(item.hiddenText(), item.toString(), 2);
500
501 // If meta key is held down, send query to search engine
502 if (event.metaDown() && !phind.library_address.equals("")) {
503 String address = phind.library_address
504 + "a=q&c=" + phind.collection
505 + "&q=%22" + item.toString().replace(' ', '+') + "%22";
506 phind.displayWebPage(address, phind.searchWindowName);
507 }
508 }
509
510 // Click on a thesaurus link
511 else if (item.isLink()) {
512 itemSelected = itemSelected;
513 update(getGraphics());
514 parent.lookupPhrase(item.hiddenText(), item.toString(), 2);
515
516 // If meta key is held down, send query to search engine
517 if (event.metaDown() && !phind.library_address.equals("")) {
518 String address = phind.library_address
519 + "a=q&c=" + phind.collection
520 + "&q=%22" + item.toString().replace(' ', '+') + "%22";
521 phind.displayWebPage(address, phind.searchWindowName);
522 }
523 }
524
525 // The user clicks on a URL; display it.
526 else if (item.isDocument()) {
527 itemSelected = itemSelected;
528 update(getGraphics());
529
530 String address = phind.library_address
531 + "a=d&c=" + phind.collection
532 + "&d=" + item.hiddenText()
533 + "&q=" + parent.searchPhrase.replace(' ', '+');
534 phind.displayWebPage(address, phind.documentWindowName);
535 }
536
537 // When the user clicks on "get more phrases" or other marker,
538 // we have to send a new query to the host
539 else if (item.isMorePhrases()){
540 parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 3);
541 } else if (item.isMoreDocuments()){
542 parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 4);
543 } else if (item.isMoreLinks()){
544 parent.lookupPhrase(parent.searchKey, parent.searchPhrase, 5);
545
546
547 }
548 repaint();
549 }
550 }
551 return true;
552 }
553
554}
555
556
557
Note: See TracBrowser for help on using the repository browser.