source: main/trunk/greenstone3/src/java/org/greenstone/applet/phind/ResultCanvas.java@ 25635

Last change on this file since 25635 was 25635, checked in by sjm84, 12 years ago

Fixing Greenstone 3's use (or lack thereof) of generics, this was done automatically so we may want to change it over time. This change will also auto-format any files that have not already been formatted.

  • Property svn:keywords set to Author Date Id Revision
File size: 18.3 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<ResultItem> 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<ResultItem>();
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 < items.elementAt(index).sort) ||
135 ((item.sort == items.elementAt(index).sort) &&
136 (item.frequency <= 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 (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 (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 (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 = 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 = 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 = 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.