source: trunk/gsdl3/src/java/org/greenstone/applet/phind/ResultCanvas.java@ 3658

Last change on this file since 3658 was 3658, checked in by kjdon, 21 years ago

small change

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