source: main/trunk/greenstone3/src/java/org/greenstone/applet/phind/JPhind.java@ 38782

Last change on this file since 38782 was 38782, checked in by anupama, 4 months ago

First commit related to attempting to move (applet) Phind to Webswing. Unfortunately, Phind was an awt applet and not a JApplet, so the first step was to make a JApplet out of it as Webswing only supports swing and not awt as Dr Bainbridge had explained. Then I thought, should I make it a regular Java application, since I was going to be reworking a copy of the code anyway (the new classes have a J prefix in front of them to indicate they use Java Swing). I couldn't find Dr Bainbridge to ask, so I found out it's possible to write a class as an (J)Applet and as an Application (just need a main method), so I've tried to recreate it as an application. I think I've got it working to the point where I beleive I'm hitting the same error the original Applet hit when run through java's appletviewer commandline tool.

File size: 32.7 KB
Line 
1/**********************************************************************
2 * 2024 - rewriting as JApplet to work with webswing (which won't work with AWT Applet)
3 * http://fizyka.umk.pl/~jacek/docs/javatutorial/uiswing/converting/how.html
4 *
5 * Phind.java -- the Phind java applet - modified to work with gsdl3 kjdon
6 *
7 * Copyright 1997-2000 Gordon W. Paynter
8 * Copyright 2000 The New Zealand Digital Library Project
9 *
10 * A component of the Greenstone digital library software
11 * from the New Zealand Digital Library Project at the
12 * University of Waikato, New Zealand.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 *
28 *********************************************************************/
29
30
31/*********************************************************************
32
33To run this applet as an application, for which this class has a main(), run as:
34
35java -cp ./web/WEB-INF/lib/gsdl3.jar:./web/WEB-INF/lib/gutil.jar:./web/applet/phind.jar:./web/WEB-INF/lib/log4j-1.2.8.jar:./web/WEB-INF/classes org.greenstone.applet.phind.JPhind "http://localhost:8383/greenstone3/library" --collection tudor --classifier 1 --phindcgi "?a=a&rt=r&s=PhindApplet&o=xml&ro=1" --library "gs2-library" --backdrop "interfaces/default/images/phindbg1.jpg"
36
37To print very basic usage, run this as an application so:
38java -cp ./web/WEB-INF/lib/gsdl3.jar:./web/WEB-INF/lib/gutil.jar:./web/applet/phind.jar:./web/WEB-INF/lib/log4j-1.2.8.jar:./web/WEB-INF/classes org.greenstone.applet.phind.JPhind
39
40
41To use the applet, you'll need to embed it in a web page like this:
42
43<APPLET CODE="Phind.class" WIDTH=500 HEIGHT=500>
44
45 <PARAM NAME=collection VALUE="fao.org">
46 <PARAM NAME=classifier VALUE="1">
47 <PARAM NAME=phindcgi VALUE="http://kowhai/cgi-bin/phindcgi">
48 <PARAM NAME=library VALUE="http://kowhai/cgi-bin/library">
49 <PARAM NAME=backdrop VALUE="http://kowhai/~paynter/transfer/phindtest/green1.jpg">
50 The Phind java applet.
51</APPLET>
52
53There are a bunch of other parameters; these are described in the
54getParameters method below. It is all done for you in Greenstone
55in the document.dm macro file (the _phindapplet_ macro).
56
57You may have problems with Java applet security. Java applet's can only
58open socket connections (including the HTTP connections the applet uses
59to get data) to the same server the applet was loaded from. This means
60that your phindcgi, library, and (optional) backdrop URLs must be on the
61same machine that your web page was loaded from.
62
63**********************************************************************
64
65The applet comprises several classes:
66
671. Phind (this file) is the applet class, loaded by the browser.
68 It also handles network connections.
692. ResultDisplay is a Panel that sits in the applet and displays
70 things; displays are connected in a doubly-linked list.
713. ResultBox holds the results of a query. Result boxes are shown
72 to the user through ResultDisplays. Another doubly-linked list.
734. ResultTitle acts as a caption to a ResultBox describing its contents.
745. ResultCanvas is what the ResultBox data is drawn on. It draws the
75 words on the screen, and handles user input from the mouse.
766. ResultItem represents a single result object (a phrase or document).
777. PhindTitle is for drawing backdrops in ResultDisplays.
78
79**********************************************************************/
80
81package org.greenstone.applet.phind;
82
83import javax.swing.JApplet;
84import javax.swing.JComponent;
85import javax.swing.JFrame;
86import javax.swing.JLabel;
87import javax.swing.JPanel;
88import javax.swing.JTextField;
89import javax.swing.JButton;
90
91//import java.awt.Choice;
92import java.awt.Color;
93import java.awt.Dimension;
94import java.awt.Font;
95import java.awt.event.ActionEvent;
96import java.awt.event.ActionListener;
97
98import java.awt.BorderLayout;
99import java.awt.FlowLayout;
100import java.awt.GridLayout;
101import java.awt.Image;
102
103import java.net.URL;
104import java.net.MalformedURLException;
105import java.io.DataInputStream;
106
107import java.net.Socket;
108import java.net.InetAddress;
109import java.net.UnknownHostException;
110import java.io.IOException;
111
112import java.util.Vector;
113import java.util.Date;
114
115import org.w3c.dom.Element;
116import org.w3c.dom.Document;
117//import javax.xml.parsers.*;
118import org.xml.sax.InputSource;
119import org.apache.xerces.parsers.DOMParser;
120
121import java.util.HashMap;
122import java.util.Map;
123
124public class JPhind extends JApplet
125 implements ActionListener {
126
127 boolean isRunAsApplet = true;
128 // set only if JPhind object is run as an application
129 URL docBaseURL = null;
130 JTextField statusField = null;
131 Map<String,String> appParams;
132
133 // What is the collection called?
134 public String collection;
135
136 // Which phind classifier are we using? (There may be more than one.)
137 public String classifier;
138
139 // Internet address of phind resources
140 public String library_address, phindcgi_address;
141
142 // Initial search term
143 public String initialSearch;
144
145 // Number of phrases to retrieve at any one time
146 public int phraseBlockSize;
147
148 // Appearance parameters
149 public boolean vertical;
150 public int depth;
151
152 // Font
153 public int fontSize;
154 public String fontName;
155 public Font plainFont, boldFont;
156
157 // Do we want a background image in the applet?
158 public boolean showImage;
159 public String backdrop_address;
160 public Image backgroundImage;
161 public boolean showBorder;
162
163 // Colours
164 public Color panel_fg, panel_bg,
165 column_1_fg, column_1_bg,
166 column_2_fg, column_2_bg,
167 highlight_fg, highlight_bg,
168 thesaurus_fg, thesaurus_bg, thesaurus_bar_fg, thesaurus_bar_bg,
169 expansion_fg, expansion_bg, expansion_bar_fg, expansion_bar_bg,
170 document_fg, document_bg, document_bar_fg, document_bar_bg,
171 message_fg, message_bg;
172
173 // Column dimensions
174 int column_1_width, column_2_width;
175
176 // Where do we open new windows
177 String searchWindowName, documentWindowName;
178
179 // the mode of operation
180 int mode;
181 final int initMode = 0;
182 final int idleMode = 1;
183 final int searchMode = 2;
184
185 // Elements of the control panel
186 boolean showControlPanel;
187 JLabel titleLabel;
188 JTextField wordField;
189 JButton searchButton, prevButton, nextButton;
190
191 // Holders for the downloaded data
192 JPanel resultPanel;
193 JResultDisplay firstDisplay, lastDisplay;
194
195 // The time at which the last query finished
196 Date lastQueryEndTime;
197
198 // lastQueryEndTime is stored to ensure a 1 second gap between a query
199 // returning and a new one beginning. It is needed because the FAO
200 // folks in Rome have a huge lag, and frquently click several times
201 // while they wait; these clicks are turned into new queries, which
202 // they await again. It is no elegant solution, but it seems like the
203 // easiest, given that I don't know threads.
204 // 1. The search button is easy to disable, and is disabled when a
205 // socket connection is in progress.
206 // 2. ResutCanvas widgets can'r be similarly disabled because the
207 // browser hides or wipes them, which looks very bad.
208 // 3. I cannot just ignore clicks on canvasses because the browser
209 // caches the clicks while the socket connection is going on, and then
210 // sends them through afterwards, when the canvas is accepting clicks
211 // again.
212 // 4. Current sequence of events is to record the time the last query
213 // ends, then whenever a click happens make sure a second has past. if
214 // you double-click the the first query is sent, returns, end-tie is
215 // set, and the second (and any others made during query time) is
216 // *immediately* processed, but since 1 second hasn't past it is
217 // ignored.
218
219
220 public JPhind() { super(); /*super.init();*/ }
221
222 public JPhind(String[] args) {
223
224 this.isRunAsApplet = false;
225 try {
226 this.docBaseURL = new URL(args[0]);
227 } catch(MalformedURLException mue) {
228 mue.printStackTrace();
229 System.err.println("*** Unable to instantiate URL from parameter: " + args[0]);
230 System.exit(-1);
231 }
232
233 appParams = new HashMap<String,String>(args.length/2);
234
235 String key = null;
236 String value = null;
237 for(int i = 1; i < args.length; i++) { // after arg0, have key-value pairs (params)
238 if(i%2==1) {
239 key = args[i].substring(2); // remove -- prefix of paramname
240 System.err.println("got key: " + key);
241 } else {
242 value = args[i];
243 appParams.put(key, value);
244 System.err.println("got value: " + value);
245 key = value = null;
246 }
247 }
248
249 // manually calling (J)Applet method init()
250 init();
251 }
252
253 /**
254 * Overriding (J)Applet method getParameter to first check appParams map
255 * if Phind was run run as an application.
256 * https://stackoverflow.com/questions/15905127/overridden-methods-in-javadoc
257 */
258 @Override
259 public String getParameter(String name) {
260 if(!isRunAsApplet) {
261 return appParams.get(name);
262 }
263 else {
264 return super.getParameter(name);
265 }
266 }
267
268 @Override
269 public void stop() {
270 if(!isRunAsApplet) {
271 System.exit(-1);
272 }
273 else {
274 super.stop(); // or put this applet's stop() method's contents here if there was one
275 }
276 }
277
278 public String getAppletInfo() {
279 return "Phind by Gordon Paynter ([email protected]). Copyright 1997-2000.";
280 }
281
282
283 public void init() {
284
285 mode = initMode;
286
287 // Read applet parameters
288 getParameters();
289
290 // Initialise the user interface
291 setBackground(panel_bg);
292 lastQueryEndTime = new Date();
293
294 // fonts used to output text
295 plainFont = new Font(fontName, Font.PLAIN, fontSize);
296 boldFont = new Font(fontName, Font.BOLD, fontSize);
297
298 // The phind applet layout manager
299 setLayout(new BorderLayout());
300
301 // Panel containing the displays is in the center of the display
302 resultPanel = new JPanel();
303 if (vertical) {
304 resultPanel.setLayout(new GridLayout(depth,1,0,2));
305 } else {
306 System.out.println("horizontal");
307 resultPanel.setLayout(new GridLayout(1,depth,2,0));
308 }
309 add(resultPanel, BorderLayout.CENTER);
310
311 // status bar that applet has, but we want one also if we run JPhind as application
312 if(!isRunAsApplet) {
313 JPanel statusBar = new JPanel();
314 this.statusField = new JTextField();
315 statusBar.add(statusField);
316 this.add(statusBar, BorderLayout.SOUTH);
317 }
318
319 // Create ResultDisplays and place into the interface
320 JResultDisplay d1, d2 = null;
321 firstDisplay = new JResultDisplay(this, null);
322 resultPanel.add(firstDisplay);
323
324 if (depth == 1) {
325 lastDisplay = firstDisplay;
326 } else {
327 d1 = firstDisplay;
328 for (int i = 2; i <= depth; i++) {
329 d2 = new JResultDisplay(this, d1);
330 resultPanel.add(d2);
331 d1 = d2;
332 }
333 lastDisplay = d2;
334 }
335
336 // The control panel
337 initialiseControlPanel();
338
339 // lets get started then
340 setStatus("Welcome to Phind.");
341 mode = idleMode;
342
343 // Perform initial search, if requested
344 if (initialSearch.length() > 0) {
345 searchForWord(initialSearch);
346 }
347 }
348
349
350 // Display a message in the status bar
351 void setStatus(String status) {
352 showStatus(status);
353 }
354
355 // The user performs an action in the interface
356 /* public boolean action(Event evt, Object arg) {
357
358 if (evt.getSource() == searchButton) {
359 System.out.println("evt source ==searchButton");
360 searchForWord(getSearchTerm());
361 } else if (evt.getSource() == wordField) {
362 System.out.println("evt source ==wordField");
363 searchForWord(getSearchTerm());
364 } else if (evt.getSource() == prevButton) {
365 shiftPrevious();
366 } else if (evt.getSource() == nextButton) {
367 shiftNext();
368 } else {
369 System.out.println("unknown action: " + evt.toString()
370 + ", object: " + arg.toString());
371 }
372 return true;
373 }
374
375 */
376
377 public void actionPerformed(ActionEvent evt) {
378
379 JComponent target = (JComponent)evt.getSource();
380 if (target==searchButton) {
381 System.out.println("search button pressed");
382 searchForWord(getSearchTerm());
383 } else if (target == wordField) {
384 System.out.println("word field entered");
385 searchForWord(getSearchTerm());
386 } else if (target == prevButton) {
387 System.out.println("prev button pressed");
388 shiftPrevious();
389 }else if (target == nextButton) {
390 System.out.println("prev button pressed");
391 shiftNext();
392 } else {
393 System.out.println("unknown action: " + evt.toString() );
394
395 }
396 }
397
398 // Search for a word
399 //
400 // Called on two occasions:
401 // when the "Search" Button is pressed, or
402 // to perform an "initial search"
403 void searchForWord(String searchWord) {
404
405 System.err.println("in searchforword!!");
406 if (mode == idleMode) {
407
408 setSearchTerm(searchWord);
409
410 // Convert the String from UTF8 charaters into
411 // an encoding that is okay for a URL.
412 searchWord = URLUTF8Encoder.encode(searchWord);
413
414 // Look up the word
415 if (searchWord.length() > 1) {
416 setStatus("searching for \"" + searchWord + "\"");
417 firstDisplay.emptyContents();
418 JResultBox result = lookupPhraseOnServer(null, false, searchWord, searchWord, 2);
419
420 // if there is an error, return
421 if (result == null) {
422 setStatus("No results for \"" + searchWord + "\"");
423 return;
424 }
425
426 // display the result
427 result.display = firstDisplay.display(result);
428 result.setSize(result.display.getSize());
429 result.paintAll(result.getGraphics());
430 }
431
432 enablePreviousAndNext();
433 }
434 }
435
436
437 // Search for a phrase
438 //
439 // If querymode is 2, the user has clicked on a phrase.
440 // If querymode is 3, the user has requested more phrases.
441 // If querymode is 4, the user has requested more documents.
442 void searchForPhrase(JResultBox source, String key, String phrase, int queryMode) {
443
444 // System.out.println("searchForPhrase: " + key + " " + phrase + " " + queryMode);
445
446 if (mode == idleMode) {
447
448 // If we are going to replace the first ResultDisplay, then empty it
449 if (queryMode <= 2) {
450 if (source.display.next != null) source.display.next.emptyContents();
451 }
452
453 // look up the word
454 setStatus("Searching for \"" + phrase + "\"");
455 JResultBox result = lookupPhraseOnServer(source, true, key, phrase, queryMode);
456 if (result == null) {
457 setStatus("No result for \"" + phrase + "\"");
458 return;
459 }
460
461 // If this is not already displayed, display it in the last free spot
462 if (queryMode <= 2) {
463 result.display = lastDisplay.display(result);
464 result.setSize(result.display.getSize());
465 result.paintAll(result.getGraphics());
466 }
467
468 enablePreviousAndNext();
469 }
470 }
471
472
473 // Look up a phrase (or symbol) on the server
474 //
475 // Arguments are the source of the query (a ResultBox, or null if the
476 // query comes from hitting the search button), the key to search for
477 // (the text of a phrase or a symbol number), the phrase as a string,
478 // and the query mode.
479 // Query modes are:
480 // 0 = obsolete
481 // 1 = obsolete
482 // 2 = get first N phrases and URLs,
483 // 3 = get another N phrases into same window
484 // 4 = get another N documents into same window
485 // 5 = get another N thesaurus links into same window
486
487 JResultBox lookupPhraseOnServer(JResultBox source,
488 boolean keyKnown, String key, String phrase,
489 int queryMode) {
490 disableSearchButton();
491 mode = searchMode;
492 JResultBox r = null;
493
494 if (queryMode <= 2) {
495 r = new JResultBox(this, collection, key, phrase, source);
496 } else if ((queryMode == 3) || (queryMode == 4) || (queryMode == 5)) {
497 r = source;
498 }
499
500 try {
501 queryServer(keyKnown, key, queryMode, r);
502 } catch (Exception e) {
503 System.out.println("Phind query error: " + e.toString());
504 setStatus("Query error: " + e.toString());
505 mode = idleMode;
506 enableSearchButton();
507 return null;
508 }
509
510 // The query is finished
511 setStatus(r.c.numberOfItems + " results for \"" + phrase + "\"");
512 mode = idleMode;
513 enableSearchButton();
514 lastQueryEndTime = new Date();
515
516 return r;
517 }
518
519
520 // Query the phindcgi program
521 //
522 // Send a query (a word or symbol number) to the server
523 // and pass the response to a ResultBox.
524
525 void queryServer(boolean keyKnown, String word, int queryMode, JResultBox area)
526 throws IOException {
527
528 // Build the query
529 String query = phindcgi_address + "c=" + collection + "&pc=" + classifier;
530
531 if (keyKnown) {
532 query = query + "&ppnum=" + word;
533 } else {
534 query = query + "&ppnum=0" + "&pptext=" + word;
535 }
536
537
538 // Specify the set of results to return
539 int first_e = 0;
540 int last_e = 0;
541 int first_d = 0;
542 int last_d = 0;
543 int first_l = 0;
544 int last_l = 0;
545
546 // the initial query
547 if (queryMode <= 2) {
548 last_e = phraseBlockSize;
549 last_d = phraseBlockSize;
550 last_l = phraseBlockSize;
551 }
552
553 // add phrases to an existing result set
554 else if (queryMode == 3) {
555 first_e = area.nextPhraseBlock * phraseBlockSize;
556 area.nextPhraseBlock++;
557 last_e = area.nextPhraseBlock * phraseBlockSize;
558 }
559
560 // add documents to existing result set
561 else if (queryMode == 4) {
562 first_d = area.nextDocumentBlock * phraseBlockSize;
563 area.nextDocumentBlock++;
564 last_d = area.nextDocumentBlock * phraseBlockSize;
565 }
566
567 // add thesaurus links to existing result set
568 else if (queryMode == 5) {
569 first_l = area.nextThesaurusLinkBlock * phraseBlockSize;
570 area.nextThesaurusLinkBlock++;
571 last_l = area.nextThesaurusLinkBlock * phraseBlockSize;
572 }
573
574 query = query + "&pfe=" + first_e + "&ple=" + last_e
575 + "&pfd=" + first_d + "&pld=" + last_d
576 + "&pfl=" + first_l + "&pll=" + last_l;
577
578 // Send the query to the phindcgi program
579 System.out.println("1:sending query: " + query);
580 try {
581 URL phindcgi = new URL(query);
582 DataInputStream in = new DataInputStream(phindcgi.openStream());
583 DOMParser parser = new DOMParser();
584 parser.parse(new InputSource(in));
585 Document data_doc = parser.getDocument();
586 Element data_elem = data_doc.getDocumentElement();
587 area.parseXML(data_elem);
588 in.close();
589 } catch (Exception e) {
590 System.err.println( "Error sending query to phindcgi: " + e);
591 e.printStackTrace();
592 }
593 area.repaint();
594 }
595
596 public void showStatus(String msg) {
597 if(!isRunAsApplet) {
598 this.statusField.setText(msg);
599 } else {
600 super.showStatus(msg);
601 }
602 }
603
604 public URL getDocumentBase() {
605 if(!isRunAsApplet) { // launched as application
606 return this.docBaseURL;
607 } else {
608 return super.getDocumentBase();
609 }
610 }
611
612 /*
613 public URL getDocumentBase(String url) {
614 int index = url.indexOf("?"); // base URL is string before the query parameters
615 if(index == -1) {
616 return new URL(url);
617 } else {
618 return new URL(url.substring(index));
619 }
620 }*/
621
622 // Tidy up URLs
623 //
624 // Ensure a URL address (as string) has a protocol, host, and file.
625 //
626 // If the URL is a CGI script URL, it should be tidied up so that it is
627 // appropriate to tage attrib=value pairs on the end. This means it
628 // must either end with a "?" or (if it contains a question-mark
629 // internally) end with a "&".
630 String tidy_URL(String address, boolean isCGI) {
631
632 System.err.println("tidy URL: " + address);
633
634 // make sure the URL has protocol, host, and file
635 if (address.startsWith("http") || address.startsWith("https")) {
636 // the address has all the necessary components
637 } else if (address.startsWith("/")) {
638 // there is not protocol and host
639 URL document = getDocumentBase();
640 //if(document == null) {
641 // document = getDocumentBase(address);
642 //}
643 String port = "";
644 if (document.getPort()!=-1) {
645 port = ":" + document.getPort();
646 }
647 address = "http://" + document.getHost() + port + address;
648 } else {
649 // this URL is relative to the directory the document is in
650 URL document = getDocumentBase();
651 //if(document == null) {
652 // document = getDocumentBase(address);
653 //}
654 String directory = document.getFile();
655 int end = directory.lastIndexOf('/');
656 String port = "";
657 if (document.getPort()!=-1) {
658 port = ":" + document.getPort();
659 }
660 directory = directory.substring(0,end + 1);
661 address = "http://" + document.getHost() + port + directory + address;
662
663 }
664
665 // if the URL is a cgi script, make sure it has a "?" in ti,
666 // and that it ends with a "?" or "&"
667 if (isCGI) {
668 if (address.indexOf((int) '?') == -1) {
669 address = address + "?";
670 } else if (!address.endsWith("?")) {
671 address = address + "&";
672 }
673 }
674
675 return address;
676 }
677
678
679
680 // Open an arbitrary web page
681 void displayWebPage(String address, String window) {
682 try {
683 URL url= new URL(address);
684 if (window.length() > 0) {
685 getAppletContext().showDocument(url, window);
686 } else {
687 getAppletContext().showDocument(url);
688 }
689 } catch (Exception e) {
690 System.out.println("Cannot open web page: " + e.toString());
691 }
692 }
693
694
695 // Get the applet parameters
696 void getParameters() {
697
698 // What is this collection called?
699 collection = parameterValue("collection");
700 System.out.println("Phind collection: " + collection);
701
702 // Which of the collection's classifiers are we using?
703 classifier = parameterValue("classifier", "1");
704 System.out.println("Phind classifier: " + classifier);
705
706 // Where is the Greenstone library
707 library_address = parameterValue("library");
708 library_address = tidy_URL(library_address, true);
709 System.out.println("Phind library: " + library_address);
710
711 // Where is the phind CGI script
712 // we assume this is relative to the greenstone library
713 phindcgi_address = parameterValue("library")+parameterValue("phindcgi");
714 phindcgi_address = tidy_URL(phindcgi_address, true);
715 System.out.println("Phind phindcgi: " + phindcgi_address);
716
717
718 // Is there a default search term?
719 initialSearch = parameterValue("initial_search", "");
720
721 // Should we display the control panel
722 showControlPanel = true;
723 if (parameterValue("control_panel", "show").toLowerCase().equals("hide")) {
724 showControlPanel = false;
725 }
726
727 // Should we show a background image?
728 backdrop_address = parameterValue("backdrop", "");
729 if (backdrop_address.length() > 0) {
730 backdrop_address = tidy_URL(backdrop_address, false);
731 System.out.println("Phind backdrop URL: " + backdrop_address);
732
733 try {
734 URL backdrop_url = new URL(backdrop_address);
735 backgroundImage = getImage(backdrop_url);
736 showImage = true;
737 } catch (Exception e) {
738 System.out.println("Phind could not load " + backdrop_address);
739 showImage = false;
740 }
741 }
742
743 // Should we draw a border?
744 showBorder = parameterValue("border", "on").equals("off");
745
746 // Are the windows arranged vertically or horizontally
747 if (parameterValue("orientation", "vertical").toLowerCase().startsWith("hori")) {
748 vertical = false;
749 } else {
750 vertical = true;
751 }
752
753 // How many phind windows are there?
754 depth = parameterValue("depth", 3);
755
756 // Result sort order
757 // Standard is "LlEeDd", expansion-first is "EeLlDd"
758 String order = parameterValue("resultorder", "standard");
759 if (!order.equals("standard")) {
760 int next = 20;
761 ResultItem.sortMessage = next;
762 for (int x = 0; x < order.length(); x++) {
763 if (order.charAt(x) == ',') {
764 next--;
765 } else if (order.charAt(x) == 'L') {
766 ResultItem.sortLinkItem = next;
767 } else if (order.charAt(x) == 'l') {
768 ResultItem.sortMoreLinks = next;
769 } else if (order.charAt(x) == 'E') {
770 ResultItem.sortPhraseItem = next;
771 } else if (order.charAt(x) == 'e') {
772 ResultItem.sortMorePhrases = next;
773 } else if (order.charAt(x) == 'D') {
774 ResultItem.sortDocumentItem = next;
775 } else if (order.charAt(x) == 'd') {
776 ResultItem.sortMoreDocuments = next;
777 }
778 }
779 System.out.println("link: " + ResultItem.sortLinkItem);
780 System.out.println("exps: " + ResultItem.sortPhraseItem);
781 System.out.println("docs: " + ResultItem.sortDocumentItem);
782
783 }
784
785 // How many phrases should we fetch at any given time?
786 phraseBlockSize = parameterValue("blocksize", 10);
787
788 // What font should we use?
789 fontSize = parameterValue("fontsize", 10);
790 fontName = parameterValue("fontname", "Helvetica");
791
792 // Column dimensions
793 column_1_width = parameterValue("first_column_width", 6);
794 column_2_width = parameterValue("second_column_width", column_1_width);
795
796 // Where do we open new windows
797 searchWindowName = parameterValue("search_window", "phindsearch");
798 documentWindowName = parameterValue("document_window", "phinddoc");
799
800 // Colours
801 panel_fg = parameterValue("panel_fg", Color.black);
802 panel_bg = parameterValue("panel_bg", Color.white);
803
804 highlight_bg = parameterValue("highlight_bg", Color.yellow);
805
806 expansion_fg = parameterValue("expansion_fg", Color.black);
807 thesaurus_fg = parameterValue("thesaurus_fg", new Color(0, 100, 0));
808 document_fg = parameterValue("document_fg", Color.blue);
809
810 thesaurus_bar_fg = parameterValue("thesaurus_bar_fg", Color.black);
811 expansion_bar_fg = parameterValue("expansion_bar_fg", Color.black);
812 document_bar_fg = parameterValue("document_bar_fg", Color.black);
813
814 thesaurus_bar_bg = parameterValue("thesaurus_bar_bg", new Color(160, 160, 190));
815 expansion_bar_bg = parameterValue("expansion_bar_bg", new Color(255, 200, 200));
816 document_bar_bg = parameterValue("document_bar_bg", new Color(150, 193, 156));
817
818 column_1_fg = parameterValue("first_column_fg", Color.black);
819 column_1_bg = parameterValue("first_column_bg", new Color(235, 245, 235));
820 column_2_fg = parameterValue("second_column_fg", Color.black);
821 column_2_bg = parameterValue("second_column_bg", new Color(200, 220, 200));
822
823 message_fg = parameterValue("message_fg", Color.black);
824 message_bg = parameterValue("message_bg", Color.white);
825
826 // Colours I don't use, yet
827 // thesaurus_bg = parameterValue("thesaurus_bg", Color.white);
828 // expansion_bg = parameterValue("expansion_bg", Color.white);
829 // document_bg = parameterValue("document_bg", Color.white);
830 }
831
832 // Get the value of a parameter given its name.
833 // There are many types of parameters, hence the variety of functions.
834
835 // Get a REQUIRED string. Stop the applet if we cannot.
836 String parameterValue(String name) {
837 try {
838 return getParameter(name);
839 } catch (Exception e) {
840 System.err.println("Phind: you must give a parameter for \""
841 + name + "\". Stopping.");
842 stop();
843 }
844 return "";
845 }
846
847 // Get an optional parameter. Return a default if we cannot.
848 String parameterValue(String name, String defaultValue) {
849 String text = getParameter(name);
850 if (text == null) {
851 return defaultValue;
852 }
853 System.out.println("Phind " + name + ": " + text);
854 return text;
855 }
856
857 int parameterValue(String name, int defaultValue) {
858 int value;
859 try {
860 value = Integer.parseInt(getParameter(name));
861 } catch (Exception e) {
862 return defaultValue;
863 }
864 System.out.println("Phind " + name + ": " + value);
865 return value;
866 }
867
868 Color parameterValue(String name, Color defaultValue) {
869
870 String text = getParameter(name);
871 if (text == null) {
872 return defaultValue;
873 }
874 text = text.toLowerCase();
875
876 // a number of the form "#ddffee"
877 if (text.startsWith("#") && (text.length() == 7)) {
878 text = text.substring(1);
879 int r, g, b;
880 try {
881 r = Integer.parseInt(text.substring(0,2), 16);
882 g = Integer.parseInt(text.substring(2,4), 16);
883 b = Integer.parseInt(text.substring(4), 16);
884 return new Color(r, g, b);
885 } catch (Exception e) {
886 return defaultValue;
887 }
888 }
889
890 // a known Java colour string
891 else if (text.equals("black")) { return Color.black; }
892 else if (text.equals("blue")) { return Color.blue; }
893 else if (text.equals("cyan")) { return Color.cyan; }
894 else if (text.equals("darkgray")) { return Color.darkGray; }
895 else if (text.equals("gray")) { return Color.gray; }
896 else if (text.equals("green")) { return Color.green; }
897 else if (text.equals("lightgray")) { return Color.lightGray; }
898 else if (text.equals("magenta")) { return Color.magenta; }
899 else if (text.equals("orange")) { return Color.orange; }
900 else if (text.equals("pink")) { return Color.pink; }
901 else if (text.equals("red")) { return Color.red; }
902 else if (text.equals("white")) { return Color.white; }
903 else if (text.equals("yellow")) { return Color.yellow; }
904
905 return defaultValue;
906 }
907
908
909 // Control panel operations
910
911 // Initialise the control panel
912 void initialiseControlPanel() {
913
914 if (showControlPanel) {
915 JPanel p1 = new JPanel();
916 this.add(p1, BorderLayout.NORTH);
917 p1.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
918
919 searchButton = new JButton("Search");
920 searchButton.setFont(boldFont);
921 //searchButton.setEnabled(true);
922 searchButton.addActionListener(this);
923 p1.add(searchButton);
924
925 JLabel tempLabel = new JLabel(" for");
926 tempLabel.setFont(boldFont);
927 p1.add(tempLabel);
928
929 wordField = new JTextField(12);
930 wordField.setFont(boldFont);
931 wordField.addActionListener(this);
932 p1.add(wordField);
933
934 JLabel temp2 = new JLabel(" ");
935 p1.add(temp2);
936
937 prevButton = new JButton("Previous");
938 prevButton.setFont(boldFont);
939 prevButton.addActionListener(this);
940 prevButton.setEnabled(false);
941
942 p1.add(prevButton);
943
944 nextButton = new JButton(" Next ");
945 nextButton.setFont(boldFont);
946 nextButton.addActionListener(this);
947 nextButton.setEnabled(false);
948 p1.add(nextButton);
949
950 }
951 }
952
953 // Button and field functionality
954
955 // Enable and disable the word field
956 void enableSearchButton() {
957 if (showControlPanel) {
958 searchButton.setEnabled(true);
959 }
960 }
961 void disableSearchButton() {
962 if (showControlPanel) {
963 searchButton.setEnabled(false);
964 }
965 }
966
967 // Get and set the search text in the wordField
968 String getSearchTerm() {
969 if (showControlPanel) {
970 return wordField.getText();
971 } else {
972 return initialSearch;
973 }
974 }
975 void setSearchTerm(String word) {
976 if (showControlPanel) {
977 wordField.setText(word);
978 }
979 }
980
981 // Enable or disable the "Previous" and "Next" buttons
982 void enablePreviousAndNext() {
983 if (showControlPanel) {
984 JComponent c = firstDisplay.current;
985 if (c.getClass().getName().endsWith("JResultBox")) {
986 if (((JResultBox) c).prevBoxExists()) {
987 prevButton.setEnabled(true);
988 } else {
989 prevButton.setEnabled(false);
990 }
991 }
992
993 c = lastDisplay.current;
994 if (c.getClass().getName().endsWith("JResultBox")) {
995 if (((JResultBox) c).nextBoxExists()) {
996 nextButton.setEnabled(true);
997 } else {
998 nextButton.setEnabled(false);
999 }
1000 }
1001 }
1002 }
1003
1004 // Shift to previous box
1005 //
1006 // If the user clicks "Previous" then scroll up.
1007 void shiftPrevious() {
1008
1009 JComponent c = firstDisplay.current;
1010 if (c.getClass().getName().endsWith("JResultBox")) {
1011
1012 JResultBox b = (JResultBox) c;
1013 if (b.prevBoxExists()) {
1014 b = b.prev;
1015
1016 // empty all the displays
1017 firstDisplay.emptyContents();
1018
1019 // add as many result boxes as there are displays
1020 for (int i = 1 ; ((i <= depth) && (b != null)); i++) {
1021 lastDisplay.display(b);
1022 b.setSize(b.display.getSize());
1023 b.paintAll(b.getGraphics());
1024 b = b.next;
1025 }
1026 }
1027 }
1028 enablePreviousAndNext();
1029 }
1030
1031 // Shift to next box
1032 //
1033 // If the user clicks "Next" then scroll down if possible
1034 void shiftNext() {
1035
1036 JComponent c = lastDisplay.current;
1037 if (c.getClass().getName().endsWith("JResultBox")) {
1038
1039 JResultBox b = (JResultBox) c;
1040 if (b.nextBoxExists()) {
1041
1042 // find the new "first" displayed box
1043 c = firstDisplay.current;
1044 b = (JResultBox) c;
1045 b = b.next;
1046
1047 // empty all the displays
1048 firstDisplay.emptyContents();
1049
1050 // add as many result boxes as there are displays
1051 for (int i = 1 ; ((i <= depth) && (b != null)); i++) {
1052 lastDisplay.display(b);
1053 b.setSize(b.display.getSize());
1054 b.paintAll(b.getGraphics());
1055 b = b.next;
1056 }
1057 }
1058 }
1059 enablePreviousAndNext();
1060 }
1061
1062 // adding a main method to allow this applet to function as an application also
1063 public static void main(String args[]) {
1064 if(args.length < 9) {
1065 System.err.println("Need minimum --params: <baseURL> --collection <collection> --classifier <classifier> --phindcgi <URL> --library <libURL> [--backdrop <ImgURL>]");
1066 }
1067 else { // collection fao.org, classifier 1, phindcgi url, library url, backdrop imgurl
1068 JPhind phind = new JPhind(args);
1069 JFrame frame = new JFrame("Phind Applet as Application");
1070 frame.getContentPane().add(phind, BorderLayout.CENTER);
1071 frame.setSize(500,500);
1072 // https://stackoverflow.com/questions/19433358/difference-between-dispose-and-exit-on-close-in-java
1073 // default: https://docs.oracle.com/javase/8/docs/api/javax/swing/JFrame.html#EXIT_ON_CLOSE
1074 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // don't do EXIT_ON_CLOSE in Applets!
1075 frame.setVisible(true);
1076
1077 }
1078 }
1079
1080
1081}
Note: See TracBrowser for help on using the repository browser.