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

Last change on this file since 2789 was 2789, checked in by kjm18, 23 years ago

fixed the Prev and Next buttons

  • Property svn:keywords set to Author Date Id Revision
File size: 26.6 KB
Line 
1/**********************************************************************
2 *
3 * Phind.java -- the Phind java applet
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/*********************************************************************
30
31To use the applet, you'll need to embed it in a web page like this:
32
33<APPLET CODE="Phind.class" WIDTH=500 HEIGHT=500>
34
35 <PARAM NAME=collection VALUE="fao.org">
36 <PARAM NAME=classifier VALUE="1">
37 <PARAM NAME=phindcgi VALUE="http://kowhai/cgi-bin/phindcgi">
38 <PARAM NAME=library VALUE="http://kowhai/cgi-bin/library">
39 <PARAM NAME=backdrop VALUE="http://kowhai/~paynter/transfer/phindtest/green1.jpg">
40 The Phind java applet.
41</APPLET>
42
43There are a bunch of other parameters; these are described in the
44getParameters method below. It is all done for you in Greenstone
45in the document.dm macro file (the _phindapplet_ macro).
46
47You may have problems with Java applet security. Java applet's can only
48open socket connections (including the HTTP connections the applet uses
49to get data) to the same server the applet was loaded from. This means
50that your phindcgi, library, and (optional) backdrop URLs must be on the
51same machine that your web page was loaded from.
52
53**********************************************************************
54
55The applet comprises several classes:
56
571. Phind (this file) is the applet class, loaded by the browser.
58 It also handles network connections.
592. ResultDisplay is a Panel that sits in the applet and displays
60 things; displays are connected in a doubly-linked list.
613. ResultBox holds the results of a query. Result boxes are shown
62 to the user through ResultDisplays. Another doubly-linked list.
634. ResultTitle acts as a caption to a ResultBox describing its contents.
645. ResultCanvas is what the ResultBox data is drawn on. It draws the
65 words on the screen, and handles user input from the mouse.
666. ResultItem represents a single result object (a phrase or document).
677. PhindTitle is for drawing backdrops in ResultDisplays.
68
69**********************************************************************/
70
71package org.nzdl.gsdl.Phind;
72
73import java.awt.BorderLayout;
74import java.awt.Button;
75import java.awt.Choice;
76import java.awt.Color;
77import java.awt.Component;
78import java.awt.Dimension;
79import java.awt.Event;
80import java.awt.FlowLayout;
81import java.awt.Font;
82import java.awt.GridLayout;
83import java.awt.Image;
84import java.awt.Label;
85import java.awt.Panel;
86import java.awt.TextField;
87
88import java.net.URL;
89import java.io.DataInputStream;
90
91import java.net.Socket;
92import java.net.InetAddress;
93import java.net.UnknownHostException;
94import java.io.IOException;
95
96import java.util.Vector;
97import java.util.Date;
98
99import org.nzdl.gsdl.Phind.URLUTF8Encoder;
100
101public class Phind extends java.applet.Applet {
102
103 // What is the collection called?
104 public String collection;
105
106 // Which phind classifier are we using? (There may be more than one.)
107 public String classifier;
108
109 // Internet address of phind resources
110 public String library_address, phindcgi_address;
111
112 // Initial serach term
113 public String initialSearch;
114
115 // Number of phrases to retrieve at any one time
116 public int phraseBlockSize;
117
118 // Appearance parameters
119 public boolean vertical;
120 public int depth;
121
122 // Font
123 public int fontSize;
124 public String fontName;
125 public Font plainFont, boldFont;
126
127 // Do we want a background image in the applet?
128 public boolean showImage;
129 public String backdrop_address;
130 public Image backgroundImage;
131 public boolean showBorder;
132
133 // Colours
134 public Color panel_fg, panel_bg,
135 column_1_fg, column_1_bg,
136 column_2_fg, column_2_bg,
137 highlight_fg, highlight_bg,
138 thesaurus_fg, thesaurus_bg, thesaurus_bar_fg, thesaurus_bar_bg,
139 expansion_fg, expansion_bg, expansion_bar_fg, expansion_bar_bg,
140 document_fg, document_bg, document_bar_fg, document_bar_bg,
141 message_fg, message_bg;
142
143 // Column dimensions
144 int column_1_width, column_2_width;
145
146 // Where do we open new windows
147 String searchWindowName, documentWindowName;
148
149 // the mode of operation
150 int mode;
151 final int initMode = 0;
152 final int idleMode = 1;
153 final int searchMode = 2;
154
155 // Elements of the control panel
156 boolean showControlPanel;
157 Label titleLabel;
158 TextField wordField;
159 Button searchButton, prevButton, nextButton;
160
161 // Holders for the downloaded data
162 Panel resultPanel;
163 ResultDisplay firstDisplay, lastDisplay;
164
165 // The time at which the last query finished
166 Date lastQueryEndTime;
167
168 // lastQueryEndTime is stored to ensure a 1 second gap between a query
169 // returning and a new one beginning. It is needed because the FAO
170 // folks in Rome have a huge lag, and frquently click several times
171 // while they wait; these clicks are turned into new queries, which
172 // they await again. It is no elegant solution, but it seems like the
173 // easiest, given that I don't know threads.
174 // 1. The search button is easy to disable, and is disabled when a
175 // socket connection is in progress.
176 // 2. ResutCanvas widgets can'r be similarly disabled because the
177 // browser hides or wipes them, which looks very bad.
178 // 3. I cannot just ignore clicks on canvasses because the browser
179 // caches the clicks while the socket connection is going on, and then
180 // sends them through afterwards, when the canvas is accepting clicks
181 // again.
182 // 4. Current sequence of events is to record the time the last query
183 // ends, then whenever a click happens make sure a second has past. if
184 // you double-click the the first query is sent, returns, end-tie is
185 // set, and the second (and any others made during query time) is
186 // *immediately* processed, but since 1 second hasn't past it is
187 // ignored.
188
189
190 public String getAppletInfo() {
191 return "Phind by Gordon Paynter ([email protected]). Copyright 1997-2000.";
192 }
193
194
195 public void init() {
196
197 mode = initMode;
198
199 // Read applet parameters
200 getParameters();
201
202 // Initialise the user interface
203 setBackground(panel_bg);
204 lastQueryEndTime = new Date();
205
206 // fonts used to output text
207 plainFont = new Font(fontName, Font.PLAIN, fontSize);
208 boldFont = new Font(fontName, Font.BOLD, fontSize);
209
210 // The phind applet layout manager
211 setLayout(new BorderLayout());
212
213 // Panel containing the displays is in the center of the display
214 resultPanel = new Panel();
215 if (vertical) {
216 resultPanel.setLayout(new GridLayout(depth,1,0,2));
217 } else {
218 System.out.println("horizontal");
219 resultPanel.setLayout(new GridLayout(1,depth,2,0));
220 }
221 add("Center", resultPanel);
222
223 // Create ResultDisplays and place into the interface
224 ResultDisplay d1, d2 = null;
225 firstDisplay = new ResultDisplay(this, null);
226 resultPanel.add(firstDisplay);
227
228 if (depth == 1) {
229 lastDisplay = firstDisplay;
230 } else {
231 d1 = firstDisplay;
232 for (int i = 2; i <= depth; i++) {
233 d2 = new ResultDisplay(this, d1);
234 resultPanel.add(d2);
235 d1 = d2;
236 }
237 lastDisplay = d2;
238 }
239
240 // The control panel
241 initialiseControlPanel();
242
243 // lets get started then
244 setStatus("Welcome to Phind.");
245 mode = idleMode;
246
247 // Perform initial search, if requested
248 if (initialSearch.length() > 0) {
249 searchForWord(initialSearch);
250 }
251 }
252
253
254 // Display a message in the status bar
255 void setStatus(String status) {
256 showStatus(status);
257 }
258
259 // The user performs an action in the interface
260 public boolean action(Event evt, Object arg) {
261
262 if (evt.target == searchButton) {
263 searchForWord(getSearchTerm());
264 } else if (evt.target == wordField) {
265 searchForWord(getSearchTerm());
266 } else if (evt.target == prevButton) {
267 shiftPrevious();
268 } else if (evt.target == nextButton) {
269 shiftNext();
270 } else {
271 System.out.println("unknown action: " + evt.toString()
272 + ", object: " + arg.toString());
273 }
274 return true;
275 }
276
277
278 // Search for a word
279 //
280 // Called on two occasions:
281 // when the "Search" Button is pressed, or
282 // to perform an "initial search"
283 void searchForWord(String searchWord) {
284
285 if (mode == idleMode) {
286
287 setSearchTerm(searchWord);
288
289 // Convert the String from UTF8 charaters into
290 // an encoding that is okay for a URL.
291 searchWord = URLUTF8Encoder.encode(searchWord);
292
293 // Look up the word
294 if (searchWord.length() > 1) {
295 setStatus("searching for \"" + searchWord + "\"");
296 firstDisplay.emptyContents();
297 ResultBox result = lookupPhraseOnServer(null, false, searchWord, searchWord, 2);
298
299 // if there is an error, return
300 if (result == null) {
301 setStatus("No results for \"" + searchWord + "\"");
302 return;
303 }
304
305 // display the result
306 result.display = firstDisplay.display(result);
307 result.resize(result.display.size());
308 result.paintAll(result.getGraphics());
309 }
310
311 enablePreviousAndNext();
312 }
313 }
314
315
316 // Search for a phrase
317 //
318 // If querymode is 2, the user has clicked on a phrase.
319 // If querymode is 3, the user has requested more phrases.
320 // If querymode is 4, the user has requested more documents.
321 void searchForPhrase(ResultBox source, String key, String phrase, int queryMode) {
322
323 // System.out.println("searchForPhrase: " + key + " " + phrase + " " + queryMode);
324
325 if (mode == idleMode) {
326
327 // If we are going to replace the first ResultDisplay, then empty it
328 if (queryMode <= 2) {
329 if (source.display.next != null) source.display.next.emptyContents();
330 }
331
332 // look up the word
333 setStatus("Searching for \"" + phrase + "\"");
334 ResultBox result = lookupPhraseOnServer(source, true, key, phrase, queryMode);
335 if (result == null) {
336 setStatus("No result for \"" + phrase + "\"");
337 return;
338 }
339
340 // If this is not already displayed, display it in the last free spot
341 if (queryMode <= 2) {
342 result.display = lastDisplay.display(result);
343 result.resize(result.display.size());
344 result.paintAll(result.getGraphics());
345 }
346
347 enablePreviousAndNext();
348 }
349 }
350
351
352 // Look up a phrase (or symbol) on the server
353 //
354 // Arguments are the source of the query (a ResultBox, or null if the
355 // query comes from hitting the search button), the key to search for
356 // (the text of a phrase or a symbol number), the phrase as a string,
357 // and the query mode.
358 // Query modes are:
359 // 0 = obsolete
360 // 1 = obsolete
361 // 2 = get first N phrases and URLs,
362 // 3 = get another N phrases into same window
363 // 4 = get another N documents into same window
364 // 5 = get another N thesaurus links into same window
365
366 ResultBox lookupPhraseOnServer(ResultBox source,
367 boolean keyKnown, String key, String phrase,
368 int queryMode) {
369 disableSearchButton();
370 mode = searchMode;
371 ResultBox r = null;
372
373 if (queryMode <= 2) {
374 r = new ResultBox(this, collection, key, phrase, source);
375 } else if ((queryMode == 3) || (queryMode == 4) || (queryMode == 5)) {
376 r = source;
377 }
378
379 try {
380 queryServer(keyKnown, key, queryMode, r);
381 } catch (Exception e) {
382 System.out.println("Phind query error: " + e.toString());
383 setStatus("Query error: " + e.toString());
384 mode = idleMode;
385 enableSearchButton();
386 return null;
387 }
388
389 // The query is finished
390 setStatus(r.c.numberOfItems + " results for \"" + phrase + "\"");
391 mode = idleMode;
392 enableSearchButton();
393 lastQueryEndTime = new Date();
394
395 return r;
396 }
397
398
399 // Query the phindcgi program
400 //
401 // Send a query (a word or symbol number) to the server
402 // and pass the response to a ResultBox.
403
404 void queryServer(boolean keyKnown, String word, int queryMode, ResultBox area)
405 throws IOException {
406
407 // Build the query
408 String query = phindcgi_address + "pxml=1&c=" + collection + "&pc=" + classifier;
409
410 if (keyKnown) {
411 query = query + "&ppnum=" + word;
412 } else {
413 query = query + "&pptext=" + word;
414 }
415
416
417 // Specify the set of results to return
418 int first_e = 0;
419 int last_e = 0;
420 int first_d = 0;
421 int last_d = 0;
422 int first_l = 0;
423 int last_l = 0;
424
425 // the initial query
426 if (queryMode <= 2) {
427 last_e = phraseBlockSize;
428 last_d = phraseBlockSize;
429 last_l = phraseBlockSize;
430 }
431
432 // add phrases to an existing result set
433 else if (queryMode == 3) {
434 first_e = area.nextPhraseBlock * phraseBlockSize;
435 area.nextPhraseBlock++;
436 last_e = area.nextPhraseBlock * phraseBlockSize;
437 }
438
439 // add documents to existing result set
440 else if (queryMode == 4) {
441 first_d = area.nextDocumentBlock * phraseBlockSize;
442 area.nextDocumentBlock++;
443 last_d = area.nextDocumentBlock * phraseBlockSize;
444 }
445
446 // add thesaurus links to existing result set
447 else if (queryMode == 5) {
448 first_l = area.nextThesaurusLinkBlock * phraseBlockSize;
449 area.nextThesaurusLinkBlock++;
450 last_l = area.nextThesaurusLinkBlock * phraseBlockSize;
451 }
452
453 query = query + "&pfe=" + first_e + "&ple=" + last_e
454 + "&pfd=" + first_d + "&pld=" + last_d
455 + "&pfl=" + first_l + "&pll=" + last_l;
456
457 // Send the query to the phindcgi program
458 System.out.println("sending query: " + query);
459 try {
460 URL phindcgi = new URL(query);
461 DataInputStream in = new DataInputStream(phindcgi.openStream());
462 byte[] buffer;
463 int availableBytes = 0;
464
465 while (!area.finished) {
466 availableBytes = in.available();
467 if (availableBytes == 0) {
468 // if i had threads i'd do a wait here for 1 second
469 } else {
470 buffer = new byte[availableBytes];
471 in.read(buffer);
472 area.parseBytes(buffer);
473 }
474 }
475
476 in.close();
477 } catch (Exception e) {
478 System.err.println( "Error sending query to phindcgi: " + e);
479 }
480 area.repaint();
481 }
482
483
484 // Tidy up URLs
485 //
486 // Ensure a URL address (as string) has a protocol, host, and file.
487 //
488 // If the URL is a CGI script URL, it should be tidied up so that it is
489 // appropriate to tage attrib=value pairs on the end. This means it
490 // must either end with a "?" or (if it contains a question-mark
491 // internally) end with a "&".
492 String tidy_URL(String address, boolean isCGI) {
493
494 // System.out.println("tidy URL: " + address);
495
496 // make sure the URL has protocol, host, and file
497 if (address.startsWith("http")) {
498 // the address has all the necessary components
499 } else if (address.startsWith("/")) {
500 // there is not protocol and host
501 URL document = getDocumentBase();
502 address = "http://" + document.getHost() + ":" + document.getPort() + address;
503 } else {
504 // this URL is relative to the directory the document is in
505 URL document = getDocumentBase();
506 String directory = document.getFile();
507 int end = directory.lastIndexOf('/');
508 directory = directory.substring(0,end + 1);
509 address = "http://" + document.getHost() + ":" + document.getPort() + directory + address;
510
511 }
512
513 // if the URL is a cgi script, make sure it has a "?" in ti,
514 // and that it ends with a "?" or "&"
515 if (isCGI) {
516 if (address.indexOf((int) '?') == -1) {
517 address = address + "?";
518 } else if (!address.endsWith("?")) {
519 address = address + "&";
520 }
521 }
522
523 return address;
524 }
525
526
527
528 // Open an arbitrary web page
529 void displayWebPage(String address, String window) {
530 try {
531 URL url= new URL(address);
532 if (window.length() > 0) {
533 getAppletContext().showDocument(url, window);
534 } else {
535 getAppletContext().showDocument(url);
536 }
537 } catch (Exception e) {
538 System.out.println("Cannot open web page: " + e.toString());
539 }
540 }
541
542
543 // Get the applet parameters
544 void getParameters() {
545
546 // What is this collection called?
547 collection = parameterValue("collection");
548 System.out.println("Phind collection: " + collection);
549
550 // Which of the collection's classifiers are we using?
551 classifier = parameterValue("classifier", "1");
552 System.out.println("Phind classifier: " + classifier);
553
554 // Where is the phind CGI script
555 phindcgi_address = parameterValue("phindcgi");
556 phindcgi_address = tidy_URL(phindcgi_address, true);
557 System.out.println("Phind phindcgi: " + phindcgi_address);
558
559 // Where is the Greenstone library
560 library_address = parameterValue("library");
561 library_address = tidy_URL(library_address, true);
562 System.out.println("Phind library: " + library_address);
563
564 // Is there a default search term?
565 initialSearch = parameterValue("initial_search", "");
566
567 // Should we display the control panel
568 showControlPanel = true;
569 if (parameterValue("control_panel", "show").toLowerCase().equals("hide")) {
570 showControlPanel = false;
571 }
572
573 // Should we show a background image?
574 backdrop_address = parameterValue("backdrop", "");
575 if (backdrop_address.length() > 0) {
576 backdrop_address = tidy_URL(backdrop_address, false);
577 System.out.println("Phind backdrop URL: " + backdrop_address);
578
579 try {
580 URL backdrop_url = new URL(backdrop_address);
581 backgroundImage = getImage(backdrop_url);
582 showImage = true;
583 } catch (Exception e) {
584 System.out.println("Phind could not load " + backdrop_address);
585 showImage = false;
586 }
587 }
588
589 // Should we draw a border?
590 showBorder = parameterValue("border", "on").equals("off");
591
592 // Are the windows arranged vertically or horizontally
593 if (parameterValue("orientation", "vertical").toLowerCase().startsWith("hori")) {
594 vertical = false;
595 } else {
596 vertical = true;
597 }
598
599 // How many phind windows are there?
600 depth = parameterValue("depth", 3);
601
602 // Result sort order
603 // Standard is "LlEeDd", expansion-first is "EeLlDd"
604 String order = parameterValue("resultorder", "standard");
605 if (!order.equals("standard")) {
606 int next = 20;
607 ResultItem.sortMessage = next;
608 for (int x = 0; x < order.length(); x++) {
609 if (order.charAt(x) == ',') {
610 next--;
611 } else if (order.charAt(x) == 'L') {
612 ResultItem.sortLinkItem = next;
613 } else if (order.charAt(x) == 'l') {
614 ResultItem.sortMoreLinks = next;
615 } else if (order.charAt(x) == 'E') {
616 ResultItem.sortPhraseItem = next;
617 } else if (order.charAt(x) == 'e') {
618 ResultItem.sortMorePhrases = next;
619 } else if (order.charAt(x) == 'D') {
620 ResultItem.sortDocumentItem = next;
621 } else if (order.charAt(x) == 'd') {
622 ResultItem.sortMoreDocuments = next;
623 }
624 }
625 System.out.println("link: " + ResultItem.sortLinkItem);
626 System.out.println("exps: " + ResultItem.sortPhraseItem);
627 System.out.println("docs: " + ResultItem.sortDocumentItem);
628
629 }
630
631 // How many phrases should we fetch at any given time?
632 phraseBlockSize = parameterValue("blocksize", 10);
633
634 // What font should we use?
635 fontSize = parameterValue("fontsize", 10);
636 fontName = parameterValue("fontname", "Helvetica");
637
638 // Column dimensions
639 column_1_width = parameterValue("first_column_width", 6);
640 column_2_width = parameterValue("second_column_width", column_1_width);
641
642 // Where do we open new windows
643 searchWindowName = parameterValue("search_window", "phindsearch");
644 documentWindowName = parameterValue("document_window", "phinddoc");
645
646 // Colours
647 panel_fg = parameterValue("panel_fg", Color.black);
648 panel_bg = parameterValue("panel_bg", Color.white);
649
650 highlight_bg = parameterValue("highlight_bg", Color.yellow);
651
652 expansion_fg = parameterValue("expansion_fg", Color.black);
653 thesaurus_fg = parameterValue("thesaurus_fg", new Color(0, 100, 0));
654 document_fg = parameterValue("document_fg", Color.blue);
655
656 thesaurus_bar_fg = parameterValue("thesaurus_bar_fg", Color.black);
657 expansion_bar_fg = parameterValue("expansion_bar_fg", Color.black);
658 document_bar_fg = parameterValue("document_bar_fg", Color.black);
659
660 thesaurus_bar_bg = parameterValue("thesaurus_bar_bg", new Color(160, 160, 190));
661 expansion_bar_bg = parameterValue("expansion_bar_bg", new Color(255, 200, 200));
662 document_bar_bg = parameterValue("document_bar_bg", new Color(150, 193, 156));
663
664 column_1_fg = parameterValue("first_column_fg", Color.black);
665 column_1_bg = parameterValue("first_column_bg", new Color(235, 245, 235));
666 column_2_fg = parameterValue("second_column_fg", Color.black);
667 column_2_bg = parameterValue("second_column_bg", new Color(200, 220, 200));
668
669 message_fg = parameterValue("message_fg", Color.black);
670 message_bg = parameterValue("message_bg", Color.white);
671
672 // Colours I don't use, yet
673 // thesaurus_bg = parameterValue("thesaurus_bg", Color.white);
674 // expansion_bg = parameterValue("expansion_bg", Color.white);
675 // document_bg = parameterValue("document_bg", Color.white);
676 }
677
678 // Get the value of a parameter given its name.
679 // There are many types of parameters, hence the variety of functions.
680
681 // Get a REQUIRED string. Stop the applet if we cannot.
682 String parameterValue(String name) {
683 try {
684 return getParameter(name);
685 } catch (Exception e) {
686 System.err.println("Phind: you must give a parameter for \""
687 + name + "\". Stopping.");
688 stop();
689 }
690 return "";
691 }
692
693 // Get an optional parameter. Return a default if we cannot.
694 String parameterValue(String name, String defaultValue) {
695 String text = getParameter(name);
696 if (text == null) {
697 return defaultValue;
698 }
699 System.out.println("Phind " + name + ": " + text);
700 return text;
701 }
702
703 int parameterValue(String name, int defaultValue) {
704 int value;
705 try {
706 value = Integer.parseInt(getParameter(name));
707 } catch (Exception e) {
708 return defaultValue;
709 }
710 System.out.println("Phind " + name + ": " + value);
711 return value;
712 }
713
714 Color parameterValue(String name, Color defaultValue) {
715
716 String text = getParameter(name);
717 if (text == null) {
718 return defaultValue;
719 }
720 text = text.toLowerCase();
721
722 // a number of the form "#ddffee"
723 if (text.startsWith("#") && (text.length() == 7)) {
724 text = text.substring(1);
725 int r, g, b;
726 try {
727 r = Integer.parseInt(text.substring(0,2), 16);
728 g = Integer.parseInt(text.substring(2,4), 16);
729 b = Integer.parseInt(text.substring(4), 16);
730 return new Color(r, g, b);
731 } catch (Exception e) {
732 return defaultValue;
733 }
734 }
735
736 // a known Java colour string
737 else if (text.equals("black")) { return Color.black; }
738 else if (text.equals("blue")) { return Color.blue; }
739 else if (text.equals("cyan")) { return Color.cyan; }
740 else if (text.equals("darkgray")) { return Color.darkGray; }
741 else if (text.equals("gray")) { return Color.gray; }
742 else if (text.equals("green")) { return Color.green; }
743 else if (text.equals("lightgray")) { return Color.lightGray; }
744 else if (text.equals("magenta")) { return Color.magenta; }
745 else if (text.equals("orange")) { return Color.orange; }
746 else if (text.equals("pink")) { return Color.pink; }
747 else if (text.equals("red")) { return Color.red; }
748 else if (text.equals("white")) { return Color.white; }
749 else if (text.equals("yellow")) { return Color.yellow; }
750
751 return defaultValue;
752 }
753
754
755 // Control panel operations
756
757 // Initialise the control panel
758 void initialiseControlPanel() {
759
760 if (showControlPanel) {
761 Panel p1 = new Panel();
762 add("North", p1);
763 p1.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
764
765 searchButton = new Button("Search");
766 searchButton.setFont(boldFont);
767 p1.add(searchButton);
768
769 Label tempLabel = new Label(" for");
770 tempLabel.setFont(boldFont);
771 p1.add(tempLabel);
772
773 wordField = new TextField(12);
774 wordField.setFont(boldFont);
775 p1.add(wordField);
776
777 Label temp2 = new Label(" ");
778 p1.add(temp2);
779
780 prevButton = new Button("Previous");
781 prevButton.setFont(boldFont);
782 prevButton.disable();
783
784 p1.add(prevButton);
785
786 nextButton = new Button(" Next ");
787 nextButton.setFont(boldFont);
788 nextButton.disable();
789 p1.add(nextButton);
790
791 }
792 }
793
794 // Button and field functionality
795
796 // Enable and disable the word field
797 void enableSearchButton() {
798 if (showControlPanel) {
799 searchButton.enable();
800 }
801 }
802 void disableSearchButton() {
803 if (showControlPanel) {
804 searchButton.disable();
805 }
806 }
807
808 // Get and set the search text in the wordField
809 String getSearchTerm() {
810 if (showControlPanel) {
811 return wordField.getText();
812 } else {
813 return initialSearch;
814 }
815 }
816 void setSearchTerm(String word) {
817 if (showControlPanel) {
818 wordField.setText(word);
819 }
820 }
821
822 // Enable or disable the "Previous" and "Next" buttons
823 void enablePreviousAndNext() {
824 if (showControlPanel) {
825 Component c = firstDisplay.current;
826 if (c.getClass().getName().endsWith("ResultBox")) {
827 if (((ResultBox) c).prevBoxExists()) {
828 prevButton.enable();
829 } else {
830 prevButton.disable();
831 }
832 }
833
834 c = lastDisplay.current;
835 if (c.getClass().getName().endsWith("ResultBox")) {
836 if (((ResultBox) c).nextBoxExists()) {
837 nextButton.enable();
838 } else {
839 nextButton.disable();
840 }
841 }
842 }
843 }
844
845 // Shift to previous box
846 //
847 // If the user clicks "Previous" then scroll up.
848 void shiftPrevious() {
849
850 Component c = firstDisplay.current;
851 if (c.getClass().getName().endsWith("ResultBox")) {
852
853 ResultBox b = (ResultBox) c;
854 if (b.prevBoxExists()) {
855 b = b.prev;
856
857 // empty all the displays
858 firstDisplay.emptyContents();
859
860 // add as many result boxes as there are displays
861 for (int i = 1 ; ((i <= depth) && (b != null)); i++) {
862 lastDisplay.display(b);
863 b.resize(b.display.size());
864 b.paintAll(b.getGraphics());
865 b = b.next;
866 }
867 }
868 }
869 enablePreviousAndNext();
870 }
871
872 // Shift to next box
873 //
874 // If the user clicks "Next" then scroll down if possible
875 void shiftNext() {
876
877 Component c = lastDisplay.current;
878 if (c.getClass().getName().endsWith("ResultBox")) {
879
880 ResultBox b = (ResultBox) c;
881 if (b.nextBoxExists()) {
882
883 // find the new "first" displayed box
884 c = firstDisplay.current;
885 b = (ResultBox) c;
886 b = b.next;
887
888 // empty all the displays
889 firstDisplay.emptyContents();
890
891 // add as many result boxes as there are displays
892 for (int i = 1 ; ((i <= depth) && (b != null)); i++) {
893 lastDisplay.display(b);
894 b.resize(b.display.size());
895 b.paintAll(b.getGraphics());
896 b = b.next;
897 }
898 }
899 }
900 enablePreviousAndNext();
901 }
902
903
904
905
906
907}
Note: See TracBrowser for help on using the repository browser.