1 | /**
|
---|
2 | *#########################################################################
|
---|
3 | *
|
---|
4 | * A component of the Gatherer application, part of the Greenstone digital
|
---|
5 | * library suite from the New Zealand Digital Library Project at the
|
---|
6 | * University of Waikato, New Zealand.
|
---|
7 | *
|
---|
8 | * <BR><BR>
|
---|
9 | *
|
---|
10 | * Author: John Thompson, Greenstone Digital Library, University of Waikato
|
---|
11 | *
|
---|
12 | * <BR><BR>
|
---|
13 | *
|
---|
14 | * Copyright (C) 1999 New Zealand Digital Library Project
|
---|
15 | *
|
---|
16 | * <BR><BR>
|
---|
17 | *
|
---|
18 | * This program is free software; you can redistribute it and/or modify
|
---|
19 | * it under the terms of the GNU General Public License as published by
|
---|
20 | * the Free Software Foundation; either version 2 of the License, or
|
---|
21 | * (at your option) any later version.
|
---|
22 | *
|
---|
23 | * <BR><BR>
|
---|
24 | *
|
---|
25 | * This program is distributed in the hope that it will be useful,
|
---|
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
28 | * GNU General Public License for more details.
|
---|
29 | *
|
---|
30 | * <BR><BR>
|
---|
31 | *
|
---|
32 | * You should have received a copy of the GNU General Public License
|
---|
33 | * along with this program; if not, write to the Free Software
|
---|
34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
35 | *########################################################################
|
---|
36 | */
|
---|
37 | package org.greenstone.gatherer.gui;
|
---|
38 |
|
---|
39 | import calpa.html.*;
|
---|
40 | import java.awt.*;
|
---|
41 | import java.awt.event.*;
|
---|
42 | import java.io.*;
|
---|
43 | import java.net.*;
|
---|
44 | import javax.swing.*;
|
---|
45 | import org.greenstone.gatherer.Dictionary;
|
---|
46 | import org.greenstone.gatherer.Gatherer;
|
---|
47 | import org.greenstone.gatherer.util.GURL;
|
---|
48 | import org.greenstone.gatherer.util.Utility;
|
---|
49 | /** This class provides browser-like functionality, with all the standard buttons. The only tricky bit is that the bookmarks are collection specific.
|
---|
50 | * @author John Thompson, Greenstone Digital Library, University of Waikato
|
---|
51 | * @version 2.3
|
---|
52 | */
|
---|
53 | public class BrowsingPane
|
---|
54 | extends JPanel {
|
---|
55 | private Bookmarks bookmarks = null;
|
---|
56 | private CalHTMLPane view_pane = null;
|
---|
57 | private CalHTMLPreferences preferences = null;
|
---|
58 | private int back_count = 0;
|
---|
59 | private int forward_count = 0;
|
---|
60 | private JButton back_button = null;
|
---|
61 | private JButton bookmarks_button = null; // Collection bookmarks.
|
---|
62 | private JButton forward_button = null;
|
---|
63 | private JButton go_button = null;
|
---|
64 | private JButton home_button = null;
|
---|
65 | private JButton refresh_button = null;
|
---|
66 | private JButton reload_button = null;
|
---|
67 | private JButton stop_button = null;
|
---|
68 | private JLabel status_label = null;
|
---|
69 | private JTextField address_field = null;
|
---|
70 | private Observer observer = null;
|
---|
71 | private String args[] = null;
|
---|
72 | static final String BOOKMARKS_FILE = "bookmarks.txt";
|
---|
73 |
|
---|
74 | public BrowsingPane() {
|
---|
75 | super();
|
---|
76 |
|
---|
77 | CalHTMLManager.setCacheDocuments(false);
|
---|
78 |
|
---|
79 | // Initialization
|
---|
80 | bookmarks = new Bookmarks(); // Empty until collection loaded.
|
---|
81 | observer = new Observer();
|
---|
82 | preferences = new CalHTMLPreferences();
|
---|
83 | preferences.setHomeURL((new GURL(Gatherer.config.getString("general.home_page", false))).getURL());
|
---|
84 | // Creation
|
---|
85 | // Controls
|
---|
86 | JPanel button_pane = new JPanel();
|
---|
87 | JPanel left_button_pane = new JPanel();
|
---|
88 |
|
---|
89 | back_button = new JButton(Utility.getImage("back.gif"));
|
---|
90 | back_button.setEnabled(false);
|
---|
91 | Dictionary.registerTooltip(back_button, "Browser.Back_Tooltip");
|
---|
92 |
|
---|
93 | // refresh_button = new JButton(Utility.getImage("reload.gif"));
|
---|
94 | // refresh_button.setEnabled(false);
|
---|
95 | // Dictionary.registerTooltip(refresh_button, "Browser.Reload");
|
---|
96 |
|
---|
97 | bookmarks_button = new JButton(Utility.getImage("bookmark.gif"));
|
---|
98 | bookmarks_button.setEnabled(false);
|
---|
99 | Dictionary.registerTooltip(bookmarks_button, "Browser.Bookmarks");
|
---|
100 |
|
---|
101 | home_button = new JButton(Utility.getImage("home.gif"));
|
---|
102 | Dictionary.registerTooltip(home_button, "Browser.Home_Tooltip");
|
---|
103 |
|
---|
104 | JPanel address_pane = new JPanel();
|
---|
105 | address_field = new JTextField(Gatherer.config.getString("general.home_page", false));
|
---|
106 | Dictionary.registerTooltip(address_field, "Browser.Address_Tooltip");
|
---|
107 |
|
---|
108 | JPanel right_button_pane = new JPanel();
|
---|
109 | go_button = new JButton(Utility.getImage("go.gif"));
|
---|
110 | Dictionary.registerTooltip(go_button, "Browser.Go_Tooltip");
|
---|
111 |
|
---|
112 | stop_button = new JButton(Utility.getImage("stop.gif"));
|
---|
113 | stop_button.setEnabled(false);
|
---|
114 | Dictionary.registerTooltip(stop_button, "Browser.Stop_Tooltip");
|
---|
115 |
|
---|
116 | forward_button = new JButton(Utility.getImage("forward.gif"));
|
---|
117 | forward_button.setEnabled(false);
|
---|
118 | Dictionary.registerTooltip(forward_button, "Browser.Forward_Tooltip");
|
---|
119 |
|
---|
120 | // Calpa Pane stuff
|
---|
121 | view_pane = new CalHTMLPane(preferences, observer, "VIEW_PANE");
|
---|
122 |
|
---|
123 | // Status bar
|
---|
124 | status_label = new JLabel();
|
---|
125 | Dictionary.registerText(status_label, "Browser.Ready");
|
---|
126 |
|
---|
127 | // Connection
|
---|
128 | address_field.addActionListener(new AddressFieldListener());
|
---|
129 | back_button.addActionListener(new BackButtonListener());
|
---|
130 | bookmarks_button.addActionListener(new BookMarksButtonListener());
|
---|
131 | forward_button.addActionListener(new ForwardButtonListener());
|
---|
132 | go_button.addActionListener(new GoButtonListener());
|
---|
133 | home_button.addActionListener(new HomeButtonListener());
|
---|
134 | // refresh_button.addActionListener(new RefreshButtonListener());
|
---|
135 | stop_button.addActionListener(new StopButtonListener());
|
---|
136 |
|
---|
137 | // Layout
|
---|
138 | left_button_pane.setLayout(new GridLayout(1,3));
|
---|
139 | left_button_pane.add(back_button);
|
---|
140 | left_button_pane.add(bookmarks_button);
|
---|
141 | left_button_pane.add(home_button);
|
---|
142 |
|
---|
143 | address_pane.setBorder(BorderFactory.createEmptyBorder(10,5,10,5));
|
---|
144 | address_pane.setLayout(new BorderLayout());
|
---|
145 | address_pane.add(address_field, BorderLayout.CENTER);
|
---|
146 |
|
---|
147 | right_button_pane.setLayout(new GridLayout(1,3));
|
---|
148 | right_button_pane.add(go_button);
|
---|
149 | right_button_pane.add(stop_button);
|
---|
150 | right_button_pane.add(forward_button);
|
---|
151 |
|
---|
152 | button_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
|
---|
153 | button_pane.setLayout(new BorderLayout());
|
---|
154 | button_pane.add(left_button_pane, BorderLayout.WEST);
|
---|
155 | button_pane.add(address_pane, BorderLayout.CENTER);
|
---|
156 | button_pane.add(right_button_pane, BorderLayout.EAST);
|
---|
157 |
|
---|
158 | setLayout(new BorderLayout());
|
---|
159 | add(button_pane, BorderLayout.NORTH);
|
---|
160 | add(new JScrollPane(view_pane), BorderLayout.CENTER);
|
---|
161 | add(status_label, BorderLayout.SOUTH);
|
---|
162 | }
|
---|
163 |
|
---|
164 | /** Some actions, such as getting the HTML to render properly without throwing sixty bazillion NPE's, can only occur after the frame has been drawn to screen. To this end we have this method so we can action things -after- the frame draw.
|
---|
165 | */
|
---|
166 | public void afterDisplay() {
|
---|
167 | view_pane.goHome();
|
---|
168 | }
|
---|
169 |
|
---|
170 | /** Called when a significant change occurs to the currently loaded collection.
|
---|
171 | * @param ready <i>true</i> if there is a collection ready to be accessed.
|
---|
172 | */
|
---|
173 | public void collectionChanged(boolean ready) {
|
---|
174 | // Reload the bookmarks associated with this collection.
|
---|
175 | if (ready) {
|
---|
176 | bookmarks.load();
|
---|
177 | }
|
---|
178 | else {
|
---|
179 | bookmarks.clear();
|
---|
180 | }
|
---|
181 | }
|
---|
182 |
|
---|
183 | /** If some external class has possibly changed the state of the browsing pane then the controls should be repolled to determine which are still valid.
|
---|
184 | */
|
---|
185 | public void controlsChanged() {
|
---|
186 | }
|
---|
187 |
|
---|
188 | /** Retrieves the current address entered in the address Textfield.
|
---|
189 | * @return A <strong>String</strong> representing the currently entered address.
|
---|
190 | */
|
---|
191 | public String getCurrentURL() {
|
---|
192 | return address_field.getText();
|
---|
193 | }
|
---|
194 |
|
---|
195 |
|
---|
196 | /** Called to validate the status of the controls. Disables those that are no longer applicable or restores those that have come back into scope of usage.
|
---|
197 | * @param update_address <i>true</i> if this pollControls call should update the address bar, <i>false</i> otherwise.
|
---|
198 | */
|
---|
199 | private void validateControls() {
|
---|
200 | back_button.setEnabled(back_count > 0);
|
---|
201 | forward_button.setEnabled(forward_count > 0);
|
---|
202 | }
|
---|
203 |
|
---|
204 | private class AddressFieldListener
|
---|
205 | implements ActionListener {
|
---|
206 | public void actionPerformed(ActionEvent event) {
|
---|
207 | // Attempt to create a GURL
|
---|
208 | GURL url = new GURL(address_field.getText());
|
---|
209 | address_field.setText(url.getURL().toString());
|
---|
210 | if(url.valid()) {
|
---|
211 | // Now load document
|
---|
212 | view_pane.showHTMLDocument(url.getURL());
|
---|
213 | back_count++;
|
---|
214 | forward_count = 0;
|
---|
215 | }
|
---|
216 | validateControls();
|
---|
217 | }
|
---|
218 | }
|
---|
219 |
|
---|
220 | private class BackButtonListener
|
---|
221 | implements ActionListener {
|
---|
222 | public void actionPerformed(ActionEvent event) {
|
---|
223 | view_pane.goBack();
|
---|
224 | back_count--;
|
---|
225 | forward_count++;
|
---|
226 | validateControls();
|
---|
227 | }
|
---|
228 | }
|
---|
229 |
|
---|
230 | private class Bookmarks
|
---|
231 | extends JDialog {
|
---|
232 |
|
---|
233 | private DefaultListModel data = null;
|
---|
234 |
|
---|
235 | public Bookmarks() {
|
---|
236 | data = new DefaultListModel();
|
---|
237 | }
|
---|
238 |
|
---|
239 | public void clear() {
|
---|
240 | data.removeAllElements();
|
---|
241 | // Re-add the "Add Bookmark" entry.
|
---|
242 | //add
|
---|
243 | }
|
---|
244 |
|
---|
245 | public void load() {
|
---|
246 | // Clear existing
|
---|
247 | data.removeAllElements();
|
---|
248 | // Determine the file to load from...
|
---|
249 | File bookmarks = new File(Gatherer.c_man.getCollectionDirectory() + BOOKMARKS_FILE);
|
---|
250 | if(bookmarks.exists()) {
|
---|
251 | // Read in file line at a time adding to bookmarks.
|
---|
252 | }
|
---|
253 | }
|
---|
254 |
|
---|
255 | public int count() {
|
---|
256 | return data.size();
|
---|
257 | }
|
---|
258 |
|
---|
259 | private class Entry {
|
---|
260 | public String title = null;
|
---|
261 | public URL url = null;
|
---|
262 | public Entry(String title, String url_raw) {
|
---|
263 | this.title = title;
|
---|
264 | try {
|
---|
265 | url = new URL(url_raw);
|
---|
266 | }
|
---|
267 | catch(Exception error) {
|
---|
268 |
|
---|
269 | }
|
---|
270 | }
|
---|
271 | public String toString() {
|
---|
272 | return title;
|
---|
273 | }
|
---|
274 | }
|
---|
275 | }
|
---|
276 |
|
---|
277 | private class BookMarksButtonListener
|
---|
278 | implements ActionListener {
|
---|
279 | public void actionPerformed(ActionEvent event) {
|
---|
280 |
|
---|
281 | }
|
---|
282 | }
|
---|
283 |
|
---|
284 | private class ForwardButtonListener
|
---|
285 | implements ActionListener {
|
---|
286 | public void actionPerformed(ActionEvent event) {
|
---|
287 | view_pane.goForward();
|
---|
288 | back_count++;
|
---|
289 | forward_count--;
|
---|
290 | validateControls();
|
---|
291 | }
|
---|
292 | }
|
---|
293 |
|
---|
294 | private class GoButtonListener
|
---|
295 | implements ActionListener {
|
---|
296 | public void actionPerformed(ActionEvent event) {
|
---|
297 | // Attempt to create a GURL
|
---|
298 | GURL url = new GURL(address_field.getText());
|
---|
299 | address_field.setText(url.getURL().toString());
|
---|
300 | if(url.valid()) {
|
---|
301 | // Now load document
|
---|
302 | view_pane.showHTMLDocument(url.getURL());
|
---|
303 | back_count++;
|
---|
304 | forward_count = 0;
|
---|
305 | }
|
---|
306 | validateControls();
|
---|
307 | }
|
---|
308 | }
|
---|
309 |
|
---|
310 | private class HomeButtonListener
|
---|
311 | implements ActionListener {
|
---|
312 | public void actionPerformed(ActionEvent event) {
|
---|
313 | address_field.setText(Gatherer.config.getString("general.home_page", false));
|
---|
314 | view_pane.goHome();
|
---|
315 | back_count++;
|
---|
316 | forward_count = 0;
|
---|
317 | validateControls();
|
---|
318 | }
|
---|
319 | }
|
---|
320 |
|
---|
321 | private class RefreshButtonListener
|
---|
322 | implements ActionListener {
|
---|
323 | public void actionPerformed(ActionEvent event) {
|
---|
324 | view_pane.reloadDocument();
|
---|
325 | validateControls();
|
---|
326 | }
|
---|
327 | }
|
---|
328 |
|
---|
329 | private class StopButtonListener
|
---|
330 | implements ActionListener {
|
---|
331 | public void actionPerformed(ActionEvent event) {
|
---|
332 | view_pane.stopAll();
|
---|
333 | validateControls();
|
---|
334 | }
|
---|
335 | }
|
---|
336 |
|
---|
337 | private class Observer
|
---|
338 | extends DefaultCalHTMLObserver {
|
---|
339 |
|
---|
340 | /** Notification that a form submission has been initiated. */
|
---|
341 | public void formSubmitUpdate(CalHTMLPane pane, URL docBaseURL, int method, String action, String data) {
|
---|
342 | ///ystem.err.println("Form submitted:" + docBaseURL.toString());
|
---|
343 | ///ystem.err.println("Data: " + data);
|
---|
344 | }
|
---|
345 |
|
---|
346 |
|
---|
347 | public void linkActivatedUpdate(CalHTMLPane pane, URL url, String target_frame, String j_name) {
|
---|
348 | ///ystem.err.println("Link clicked: " + url.toString());
|
---|
349 | address_field.setText(url.toString());
|
---|
350 | back_count++;
|
---|
351 | validateControls();
|
---|
352 | }
|
---|
353 |
|
---|
354 | public void linkFocusUpdate(CalHTMLPane pane, URL url) {
|
---|
355 | ///ystem.err.println("Link in focus " + url.toString());
|
---|
356 | args = new String[1];
|
---|
357 | args[0] = url.toString();
|
---|
358 | Dictionary.registerText(status_label, "Browser.Follow");
|
---|
359 | args = null;
|
---|
360 | }
|
---|
361 | public void statusUpdate(CalHTMLPane pane, int state, URL url, int value, String message) {
|
---|
362 | switch(state) {
|
---|
363 | // The Pane is attempting to connect to the given URL to receive data.
|
---|
364 | case CalCons.PRE_CONNECT:
|
---|
365 | ///ystem.err.println("Preconnect: " + url.toString());
|
---|
366 | break;
|
---|
367 | // The Pane was unable to connect to the given URL or was unable to parse the content. Most likely this will be due to an incorrectly specified URL. The message argument may contain further details of the reason for failure.
|
---|
368 | case CalCons.PARSE_FAILED:
|
---|
369 | ///ystem.err.println("Parse Failed: " + url.toString());
|
---|
370 | ///ystem.err.println("Message: " + message);
|
---|
371 | break;
|
---|
372 | // The Pane has established a connection to the given URL and is receiving any content.
|
---|
373 | case CalCons.CONNECTED:
|
---|
374 | // Can only stop if somethings happening.
|
---|
375 | stop_button.setEnabled(true);
|
---|
376 | args = new String[1];
|
---|
377 | args[0] = url.toString();
|
---|
378 | Dictionary.registerText(status_label, "Browser.Loading", args);
|
---|
379 | args = null;
|
---|
380 | break;
|
---|
381 | // The size of the content at the given URL is known and is contained in the value argument.
|
---|
382 | case CalCons.DOC_LENGTH:
|
---|
383 | break;
|
---|
384 | // The title of the document for the given URL is known and is contained in the message argument. Only the title of a document in the Pane's top level frame will be sent to this method. If the document has no name, the message will be null, unless the document is a Frameset document in which case the message "Frameset" will be sent.
|
---|
385 | case CalCons.TITLE:
|
---|
386 | break;
|
---|
387 | // An exception has been thrown during parsing of the data from the URL. This will most likely be an IOException such as a server time-out.
|
---|
388 | case CalCons.PARSE_FAILED_POST_CONNECT:
|
---|
389 | ///ystem.err.println("Parse Failed Post Connect: " + url.toString());
|
---|
390 | break;
|
---|
391 | // The document has been parsed but formatting cannot be completed because the document contains images of unspecified size. The parsing thread is waiting for image updates to give it the information it needs to format and display the document.
|
---|
392 | case CalCons.WAITING_FOR_IMAGES:
|
---|
393 | break;
|
---|
394 | // All text and image data has been received, parsed and the document structure determined.
|
---|
395 | case CalCons.DOC_LOADED:
|
---|
396 | // All done.
|
---|
397 | stop_button.setEnabled(false);
|
---|
398 | // Rendering complete.
|
---|
399 | Dictionary.registerText(status_label, "Browser.Ready");
|
---|
400 | go_button.setEnabled(true);
|
---|
401 | stop_button.setEnabled(false);
|
---|
402 | // refresh_button.setEnabled(true);
|
---|
403 | // Update mirror pane
|
---|
404 | Gatherer.g_man.mirror_pane.setURL(url.toString());
|
---|
405 | break;
|
---|
406 | }
|
---|
407 | }
|
---|
408 | }
|
---|
409 | }
|
---|