source: main/trunk/greenstone2/runtime-src/src/java/org/nzdl/gsdl/Phind/ResultCanvas.java@ 23546

Last change on this file since 23546 was 23546, checked in by ak19, 13 years ago

Fixed minor bug in phrase browser where clicking on a link in the resultset of the Resultcanvas would bring up the document with all individual terms in that phrase highlighted (including words like The). Kathy worked out that this was because the q query argument in the url needed quotes around it to do the right thing. Looking in the code, it turned out there was one instance where quotes were not added around the q query argument.

  • 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=%22" + parent.searchPhrase.replace(' ', '+') + "%22";
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.