source: trunk/gli/src/org/greenstone/gatherer/gui/CreatePane.java@ 7091

Last change on this file since 7091 was 7091, checked in by kjdon, 20 years ago

destroy the AppendLineOnlyFileDocument beloonging to the log_textarea when we change collections so that the old log is not displayed in the new collection

  • Property svn:keywords set to Author Date Id Revision
File size: 38.1 KB
Line 
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 */
37package org.greenstone.gatherer.gui;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.io.*;
42import javax.swing.*;
43import javax.swing.event.*;
44import javax.swing.text.*;
45import javax.swing.tree.*;
46import org.greenstone.gatherer.Configuration;
47import org.greenstone.gatherer.Dictionary;
48import org.greenstone.gatherer.Gatherer;
49import org.greenstone.gatherer.cdm.SearchTypeManager;
50import org.greenstone.gatherer.collection.BuildOptions;
51import org.greenstone.gatherer.collection.Collection;
52import org.greenstone.gatherer.gui.GLIButton;
53import org.greenstone.gatherer.gui.OptionsPane;
54import org.greenstone.gatherer.shell.GBasicProgressMonitor;
55import org.greenstone.gatherer.shell.GBuildProgressMonitor;
56import org.greenstone.gatherer.shell.GImportProgressMonitor;
57import org.greenstone.gatherer.shell.GShell;
58import org.greenstone.gatherer.shell.GShellEvent;
59import org.greenstone.gatherer.shell.GShellListener;
60import org.greenstone.gatherer.shell.GShellProgressMonitor;
61import org.greenstone.gatherer.util.AppendLineOnlyFileDocument;
62import org.greenstone.gatherer.util.StaticStrings;
63
64/** This class provides a GUI view showing some statistics on your current collection, and options for building it. As the collection is built this initial view is replaced with one showing progress bars and a message log of the creation process. This log can be later accessed via the options tree located in the center of the initial pane. This class is also responsible for creating the GShellProgressMonitors that are then attatched to external shell processes, and calling the methods in the CollectionManager for actually importing and building the collection. <br><BR>
65 * <center><table width=80% border=2 cellspacing=0 cellpadding=2><tr><td align=center colspan=4>
66 * The (i)mport and/or (b)uild options supported:</td></tr>
67 * <tr background=black><font color=white><td>Script</td><td>Associated Argument</td><td>Control</td><td>Comments</td></font></tr>
68 * <tr><td>b</td><td>-allclassifications</td><td>JCheckBox</td><td>&nbsp;</td></tr>
69 * <tr><td>i/b</td><td>-archivedir</td><td>JTextField</td><td>&nbsp;</td></tr>
70 * <tr><td>b</td><td>-builddir</td><td>JTextField</td><td>&nbsp;</td></tr>
71 * <tr><td>i/b</td><td>-debug</td><td>JCheckBox</td><td>&nbsp;</td></tr>
72 * <tr><td>i/b</td><td>-collectdir</td><td>JTextField</td><td>&nbsp;</td></tr>
73 * <tr><td>b</td><td>-create_images</td><td>JCheckBox</td><td>&nbsp;</td></tr>
74 * <tr><td>i</td><td>-groupsize</td><td>JSpinner </td><td>&nbsp;</td></tr>
75 * <tr><td>i</td><td>-gzip</td><td>JCheckBox</td><td>&nbsp;</td></tr>
76 * <tr><td>i</td><td>-importdir</td><td>JTextField</td><td>&nbsp;</td></tr>
77 * <tr><td>b</td><td>-index</td><td>GCheckList</td><td>&nbsp;</td></tr>
78 * <tr><td>i/b</td><td>-keepold</td><td>JCheckBox</td><td>sanity check removeold</td></tr>
79 * <tr><td>i/b</td><td>-maxdocs</td><td>JSpinner</td><td>&nbsp;</td></tr>
80 * <tr><td>b</td><td>-mode</td><td>JComboBox</td><td>"all", "compress_text", "infodb", "build_index"</td></tr>
81 * <tr><td>b</td><td>-no_text</td><td>JCheckBox</td><td>&nbsp;</td></tr>
82 * <tr><td>i</td><td>-OIDtype</td><td>JComboBox</td><td>"hash","incremental"</td></tr>
83 * <tr><td>i/b</td><td>-out</td><td>JTextField</td><td>&nbsp;</td></tr>
84 * <tr><td>i</td><td>-removeold</td><td>JCheckBox</td><td>sanity check keepold</td></tr>
85 * <tr><td>i</td><td>-sortmeta</td><td>JComboBox</td><td>&nbsp;</td></tr>
86 * <tr><td>i/b</td><td>-verbosity</td><td>JSpinner</td><td>1, 3</td></tr>
87 * </table></center>
88 * @author John Thompson, Greenstone Digital Library, University of Waikato
89 * @version 2.3
90 */
91public class CreatePane
92 extends JPanel
93 implements GShellListener {
94
95 static private Dimension ARGUMENT_SIZE = new Dimension(800,90);
96 /** The size of the buttons at the bottom of the screen. */
97 static private Dimension BUTTON_SIZE = new Dimension (256, 40);//(386, 50);
98 /** The size of the labels on the progress pane. */
99 static private Dimension LABEL_SIZE = new Dimension(140, 25);
100 /** The threshold for when the simple view is replaced by the complex one. */
101 static private final int THRESHOLD = Configuration.EXPERT_MODE;
102 /** An identifier for the control panel within the card layout. */
103 static private String CONTROL = "Control";
104 /** An identifier for the progress panel within the card layout. */
105 static private String PROGRESS = "Progress";
106 /** An identifier for the simple panel within the card layout. */
107 static private String SIMPLE = "Simple";
108
109 /** Determines the current view that should be shown for this pane. */
110 public boolean processing = false;
111 /** The options pane generates all the various option sheet configuations. */
112 public OptionsPane options_pane = null;
113 private AppendLineOnlyFileDocument document;
114 /** A card layout is used to store the separate configuration and progress panes. */
115 private CardLayout card_layout = null;
116 /** Stores a reference to the current collection. */
117 private Collection previous_collection = null;
118 /** This monitor tracks the build processes progress. */
119 private GShellProgressMonitor build_monitor = null;
120 /** This monitor tracks the copy processes progress. */
121 private GShellProgressMonitor copy_monitor = null;
122 /** This monitor tracks the import processes progress. */
123 private GShellProgressMonitor import_monitor = null;
124 /** The button for begining the building processes. */
125 private JButton build_button = null;
126 /** The button for stopping the building processes. */
127 private JButton cancel_button = null;
128 /** The button for viewing the collection. */
129 private JButton preview_button = null;
130 private JButton simple_build_button;
131 private JButton simple_cancel_button;
132 private JButton simple_preview_button;
133 /** The label displaying the number of documents in this collection. */
134 private JLabel document_count = null;
135 /** The label alongside the build progress bar gets some special treatment so... */
136 private JLabel progress_build_label = null;
137 /** The label alongside the copy progress bar gets some special treatment so... */
138 private JLabel progress_copy_label = null;
139 /** The label alongside the import progress bar gets some special treatment so... */
140 private JLabel progress_import_label = null;
141 private JPanel bar_area;
142 /** The panel on which buttons are rendered on higher detail modes. */
143 private JPanel button_pane;
144 /** The pane which contains the controls for configuration. */
145 private JPanel control_pane = null;
146 /** The pane which has the card layout as its manager. */
147 private JPanel main_pane = null;
148 /** The pane which contains the progress information. */
149 private JPanel progress_pane = null;
150 /** The pane on the right-hand side - shows the requested options view */
151 private JPanel right = null;
152 /** The simple panel on which all of the available arguments are rendered. */
153 private JPanel sargument_configuration_panel;
154 /** The panel on which buttons are rendered on lower details modes. */
155 private JPanel sbutton_panel;
156 /** A simplified version for lower detail modes containing both the control and progress panes smooshed together. */
157 private JPanel simple_panel;
158 /** The inner panel of the simple pane which is global so that the bar_area can be added and removed from it. */
159 private JPanel sinner_panel;
160 /** The outer panel of the simple pane which is global so that the arguments pane can be added and removed from it. */
161 private JPanel souter_panel;
162 /** The scrolling pane for the log. */
163 private JScrollPane log_scroll;
164 /** The scrolling pane the simple arguments are rendered within. */
165 private JScrollPane sargument_configuration_scroll;
166 /** the scrolling pane the righthand side is inside - only used for import and build options. the log and log list are not inside a scrollpane */
167 private JScrollPane scroll_pane;
168 /** The message log for the entire session. */
169 private JTextArea log_textarea;
170 /** A tree used to display the currently available option views. */
171 private OptionTree tree = null;
172 /** An array used to pass arguments with dictionary calls. */
173 private String args[] = null;
174 /** The homepage address of the current collection */
175 private String homepage = null;
176
177
178 /** The constructor creates important helper classes, and initializes all the components.
179 * @see org.greenstone.gatherer.collection.CollectionManager
180 * @see org.greenstone.gatherer.gui.BuildOptions
181 * @see org.greenstone.gatherer.gui.CreatePane.BuildButtonListener
182 * @see org.greenstone.gatherer.gui.CreatePane.CancelButtonListener
183 * @see org.greenstone.gatherer.gui.CreatePane.OptionTree
184 * @see org.greenstone.gatherer.gui.OptionsPane
185 * @see org.greenstone.gatherer.shell.GBasicProgressMonitor
186 * @see org.greenstone.gatherer.shell.GBuildProgressMonitor
187 * @see org.greenstone.gatherer.shell.GImportProgressMonitor
188 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
189 */
190 public CreatePane() {
191 Collection collection = Gatherer.c_man.getCollection();
192 log_textarea = new JTextArea();
193 log_scroll = new JScrollPane(log_textarea);
194
195 // Create components
196 card_layout = new CardLayout();
197 // Control Pane
198 control_pane = new JPanel();
199 tree = new OptionTree();
200 button_pane = new JPanel();
201
202 // Progress Pane
203 progress_pane = new JPanel(); // One owner of the bar component
204 bar_area = new JPanel(); // This component will be shared about
205
206 progress_copy_label = new JLabel();
207 progress_copy_label.setForeground(Color.black);
208 progress_copy_label.setHorizontalAlignment(JLabel.LEFT);
209 progress_copy_label.setPreferredSize(LABEL_SIZE);
210 progress_copy_label.setMinimumSize(LABEL_SIZE);
211 progress_copy_label.setSize(LABEL_SIZE);
212 Dictionary.registerText(progress_copy_label, "CreatePane.Copy_Progress");
213
214 copy_monitor = new GBasicProgressMonitor();
215 Gatherer.c_man.registerCopyMonitor(copy_monitor);
216
217 progress_import_label = new JLabel();
218 progress_import_label.setForeground(Color.black);
219 progress_import_label.setHorizontalAlignment(JLabel.LEFT);
220 progress_import_label.setPreferredSize(LABEL_SIZE);
221 progress_import_label.setMinimumSize(LABEL_SIZE);
222 progress_import_label.setSize(LABEL_SIZE);
223 Dictionary.registerText(progress_import_label, "CreatePane.Import_Progress");
224
225 import_monitor = new GImportProgressMonitor(); //GBasicProgressMonitor();
226 Gatherer.c_man.registerImportMonitor(import_monitor);
227
228 progress_build_label = new JLabel();
229 progress_build_label.setForeground(Color.black);
230 progress_build_label.setHorizontalAlignment(JLabel.LEFT);
231 progress_build_label.setPreferredSize(LABEL_SIZE);
232 progress_build_label.setMinimumSize(LABEL_SIZE);
233 progress_build_label.setSize(LABEL_SIZE);
234 Dictionary.registerText(progress_build_label, "CreatePane.Build_Progress");
235
236 build_monitor = new GBuildProgressMonitor(import_monitor.getSharedProgress()); //GBasicProgressMonitor();
237 Gatherer.c_man.registerBuildMonitor(build_monitor);
238
239 // And the simple panel
240 simple_panel = new JPanel();
241 sbutton_panel = new JPanel();
242 sinner_panel = new JPanel();
243
244 // Buttons
245 BuildButtonListener bbl = new BuildButtonListener();
246 CancelButtonListener cbl = new CancelButtonListener();
247 PreviewButtonListener pbl = new PreviewButtonListener();
248
249 build_button = new GLIButton();
250 build_button.addActionListener(bbl);
251 build_button.setMnemonic(KeyEvent.VK_B);
252 //build_button.setPreferredSize(BUTTON_SIZE);
253 Dictionary.registerBoth(build_button, "CreatePane.Build_Collection", "CreatePane.Build_Collection_Tooltip");
254
255 cancel_button = new GLIButton();
256 cancel_button.addActionListener(cbl);
257 cancel_button.setEnabled(false);
258 cancel_button.setMnemonic(KeyEvent.VK_C);
259 //cancel_button.setPreferredSize(BUTTON_SIZE);
260 Dictionary.registerBoth(cancel_button, "CreatePane.Cancel_Build", "CreatePane.Cancel_Build_Tooltip");
261
262 preview_button = new GLIButton();
263 preview_button.addActionListener(pbl);
264 if(Gatherer.c_man != null) {
265 preview_button.setEnabled(Gatherer.c_man.built());
266 }
267 else {
268 preview_button.setEnabled(false);
269 }
270 preview_button.setMnemonic(KeyEvent.VK_P);
271 //preview_button.setPreferredSize(BUTTON_SIZE);
272 Dictionary.registerBoth(preview_button, "CreatePane.Preview_Collection", "CreatePane.Preview_Collection_Tooltip");
273
274 simple_build_button = new GLIButton();
275 simple_build_button.addActionListener(bbl);
276 simple_build_button.setMnemonic(KeyEvent.VK_B);
277 //simple_build_button.setPreferredSize(BUTTON_SIZE);
278 Dictionary.registerBoth(simple_build_button, "CreatePane.Build_Collection", "CreatePane.Build_Collection_Tooltip");
279
280 simple_cancel_button = new GLIButton();
281 simple_cancel_button.addActionListener(cbl);
282 simple_cancel_button.setEnabled(false);
283 simple_cancel_button.setMnemonic(KeyEvent.VK_C);
284 //simple_cancel_button.setPreferredSize(BUTTON_SIZE);
285 Dictionary.registerBoth(simple_cancel_button, "CreatePane.Cancel_Build", "CreatePane.Cancel_Build_Tooltip");
286
287 simple_preview_button = new GLIButton();
288 simple_preview_button.addActionListener(pbl);
289 if(Gatherer.c_man != null) {
290 simple_preview_button.setEnabled(Gatherer.c_man.built());
291 }
292 else {
293 simple_preview_button.setEnabled(false);
294 }
295 simple_preview_button.setMnemonic(KeyEvent.VK_P);
296 //simple_preview_button.setPreferredSize(BUTTON_SIZE);
297 Dictionary.registerBoth(simple_preview_button, "CreatePane.Preview_Collection", "CreatePane.Preview_Collection_Tooltip");
298
299 bbl = null;
300 cbl = null;
301 pbl = null;
302 }
303
304 /** This method is invoked at any time there has been a significant change in the collection, such as saving, loading or creating.
305 * @param ready A <strong>boolean</strong> indicating if a collection is currently available.
306 * @see org.greenstone.gatherer.Gatherer
307 * @see org.greenstone.gatherer.collection.CollectionManager
308 * @see org.greenstone.gatherer.gui.BuildOptions
309 * @see org.greenstone.gatherer.gui.OptionsPane
310 */
311 public void collectionChanged(boolean ready) {
312 if(Gatherer.c_man == null || !ready) {
313 return;
314 }
315 Collection current_collection = Gatherer.c_man.getCollection();
316 if (current_collection != previous_collection && !Gatherer.c_man.isImporting()) {
317 this.options_pane = new OptionsPane(current_collection.build_options);
318 if (previous_collection != null) {
319 // clear the log
320 ((AppendLineOnlyFileDocument)log_textarea.getDocument()).destroy();
321 }
322 previous_collection = current_collection;
323
324 }
325 // If we are in simple mode, we have to rebuild the simple arguments list
326 if(Gatherer.config.getMode() < THRESHOLD) {
327 souter_panel.remove(sargument_configuration_scroll);
328 souter_panel.remove(sinner_panel);
329 sargument_configuration_panel = options_pane.buildImport(null);
330 sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
331 sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
332 sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
333 souter_panel.add(sargument_configuration_scroll);
334 souter_panel.add(sinner_panel);
335 }
336 tree.valueChanged(null);
337
338 // now do the preview stuff
339 if (!Gatherer.c_man.built() || Gatherer.config.exec_address == null) {
340 preview_button.setEnabled(false);
341 simple_preview_button.setEnabled(false);
342 } else {
343 preview_button.setEnabled(true);
344 simple_preview_button.setEnabled(true);
345 }
346 }
347
348 public void destroy() {
349 if(document != null) {
350 document.destroy();
351 }
352 }
353
354 /** This method is called to actually layout the components.
355 * @see org.greenstone.gatherer.Configuration
356 * @see org.greenstone.gatherer.Gatherer
357 */
358 public void display() {
359
360 int current_mode = Gatherer.config.getMode();
361
362 // Build control_pane
363 JPanel left = new JPanel();
364 left.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
365 left.setLayout(new BorderLayout());
366 left.add(tree, BorderLayout.CENTER);
367
368 right = new JPanel();
369 right.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
370 right.setLayout(new BorderLayout());
371
372 JPanel options_area = new JPanel();
373 options_area.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createTitledBorder(Dictionary.get("CreatePane.Options_Title"))));
374 options_area.setLayout(new BorderLayout());
375 options_area.add(left, BorderLayout.WEST);
376 options_area.add(right, BorderLayout.CENTER);
377
378 button_pane = new JPanel();
379 button_pane.setBorder(BorderFactory.createEmptyBorder(5,10,10,10));
380 button_pane.setLayout(new GridLayout(1,3));
381 button_pane.add(build_button);
382 button_pane.add(cancel_button);
383 button_pane.add(preview_button);
384
385 control_pane.setLayout(new BorderLayout());
386 control_pane.add(options_area, BorderLayout.CENTER);
387 control_pane.add(button_pane, BorderLayout.SOUTH);
388
389 // Build progress_pane
390 JPanel copy_pane = new JPanel();
391 copy_pane.setLayout(new BorderLayout());
392 copy_pane.add(progress_copy_label, BorderLayout.WEST);
393 copy_pane.add(copy_monitor.getProgress(), BorderLayout.CENTER);
394
395 JPanel import_pane = new JPanel();
396 import_pane.setLayout(new BorderLayout());
397 import_pane.add(progress_import_label, BorderLayout.WEST);
398 import_pane.add(import_monitor.getProgress(), BorderLayout.CENTER);
399
400 JPanel build_pane = new JPanel();
401 build_pane.setLayout(new BorderLayout());
402 build_pane.add(progress_build_label, BorderLayout.WEST);
403 build_pane.add(build_monitor.getProgress(), BorderLayout.CENTER);
404
405 bar_area.setBorder(BorderFactory.createEmptyBorder(10,10,5,10));
406
407 bar_area.setLayout(new GridLayout(2,2,10,5));
408 bar_area.add(import_pane);
409 bar_area.add(build_pane);
410
411 progress_pane.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
412 progress_pane.setLayout(new BorderLayout());
413 progress_pane.add(bar_area, BorderLayout.NORTH);
414 if(current_mode >= THRESHOLD) {
415 progress_pane.add(log_scroll, BorderLayout.CENTER);
416 }
417
418 // Simple panel
419 sbutton_panel.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
420 sbutton_panel.setLayout(new GridLayout(3,1));
421 sbutton_panel.add(simple_build_button);
422 sbutton_panel.add(simple_cancel_button);
423 sbutton_panel.add(simple_preview_button);
424
425 JPanel simple_bar_area = new JPanel(new GridLayout(3,1));
426 simple_bar_area.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
427 simple_bar_area.add(import_monitor.getSharedProgress());
428
429 sinner_panel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
430 sinner_panel.setLayout(new BorderLayout());
431 sinner_panel.add(sbutton_panel, BorderLayout.WEST);
432 sinner_panel.add(simple_bar_area, BorderLayout.CENTER);
433
434 if(options_pane != null) {
435 sargument_configuration_panel = options_pane.buildImport(null);
436 sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
437 }
438 else {
439 sargument_configuration_panel = new JPanel();
440 }
441 sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
442 sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
443 souter_panel = new JPanel();
444 souter_panel.setSize(new Dimension(400,800));
445 souter_panel.setLayout(new GridLayout(2,1));
446 souter_panel.add(sargument_configuration_scroll);
447 souter_panel.add(sinner_panel);
448
449 simple_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
450 simple_panel.setLayout(new BorderLayout());
451 simple_panel.add(souter_panel, BorderLayout.NORTH);
452 if(current_mode < THRESHOLD) {
453 simple_panel.add(log_scroll, BorderLayout.CENTER);
454 }
455
456 // Main pane
457 main_pane = new JPanel(card_layout);
458 if(current_mode < THRESHOLD) { // Simple mode - add first
459 main_pane.add(simple_panel, SIMPLE);
460 }
461 main_pane.add(control_pane, CONTROL);
462 main_pane.add(progress_pane, PROGRESS);
463 if(current_mode >= THRESHOLD) { // Expert mode - add last
464 main_pane.add(simple_panel, SIMPLE);
465 }
466
467 this.setLayout(new BorderLayout());
468 this.add(main_pane, BorderLayout.CENTER);
469 }
470
471 /** This method is called whenever the 'Create' tab is selected from the view bar. It allows this view to perform any preactions required prior to display. In this case this entails gathering up to date information about the status of the collection including number of documents etc.
472 * @see org.greenstone.gatherer.Gatherer
473 * @see org.greenstone.gatherer.collection.CollectionManager
474 * @see org.greenstone.gatherer.gui.CreatePane.OptionTree
475 */
476 public void gainFocus() {
477 if(Gatherer.config.getMode() < THRESHOLD) {
478 card_layout.show(main_pane, SIMPLE);
479 }
480 else if(!processing) {
481 // Move the buttons to control
482 control_pane.add(button_pane, BorderLayout.SOUTH);
483 card_layout.show(main_pane, CONTROL);
484 }
485 else {
486 // Move the buttons to progress
487 progress_pane.add(button_pane, BorderLayout.SOUTH);
488 card_layout.show(main_pane, PROGRESS);
489 }
490 // Refresh the set of controls.
491 TreePath path = tree.getSelectionPath();
492 tree.clearSelection();
493 tree.setSelectionPath(path);
494 }
495
496 /** We are informed when this view pane loses focus so we can update build options. */
497 public void loseFocus() {
498 tree.valueChanged(null);
499 }
500
501 /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
502 * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
503 */
504 public synchronized void message(GShellEvent event) {
505 // Ignore the messages from RecPlug with 'show_progress' set (used for progress bars)
506 if (event.getMessage().startsWith("import.pl> RecPlug - ")) {
507 return;
508 }
509 document.appendLine(event.getMessage());
510 log_textarea.setCaretPosition(document.getLengthToNearestLine());
511 }
512
513 /** Called when the detail mode has changed which in turn may cause several import/build configuration arguments to be available/hidden
514 * @param mode the new mode as an int
515 */
516 public void modeChanged(int mode) {
517 // If we are below the complexity threshold ensure the simple controls are being shown
518 if(Gatherer.config.getMode() < THRESHOLD) {
519 // Update the arguments
520 souter_panel.remove(sargument_configuration_scroll);
521 souter_panel.remove(sinner_panel);
522 if(options_pane != null) {
523 sargument_configuration_panel = options_pane.buildImport(null);
524 sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
525 }
526 else {
527 sargument_configuration_panel = new JPanel();
528 }
529 sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
530 sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
531 souter_panel.add(sargument_configuration_scroll);
532 souter_panel.add(sinner_panel);
533 // Remove the shared components from the expert panels
534 progress_pane.remove(log_scroll);
535 // And add to simple one
536 simple_panel.add(log_scroll, BorderLayout.CENTER);
537 // And bring the card to the front
538 card_layout.show(main_pane, SIMPLE);
539 }
540 // And if we are above the threshold change to the complex controls
541 else {
542 // Remove the shared components from the simple panel
543 simple_panel.remove(log_scroll);
544 // And add then to the expert ones
545 progress_pane.add(log_scroll, BorderLayout.CENTER);
546 // And bring the appropriate card to the front
547 if(!processing) {
548 control_pane.add(button_pane, BorderLayout.SOUTH);
549 card_layout.show(main_pane, CONTROL);
550 }
551 else {
552 progress_pane.add(button_pane, BorderLayout.SOUTH);
553 card_layout.show(main_pane, PROGRESS);
554 }
555 }
556 tree.valueChanged(null); // Ensure tree argument panels are rebuilt
557 }
558
559 /** All implementation of GShellListener must include this method so the listener can be informed when a GShell begins its task. Implementation side-effect, not actually used.
560 * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
561 */
562 public synchronized void processBegun(GShellEvent event) {
563 // We don't care. We'll get a more acurate start from the progress monitors.
564 }
565 /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
566 * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
567 */
568 public synchronized void processComplete(GShellEvent event) {
569 if(event.getStatus() == GShell.OK) {
570 if(event.getType() == GShell.BUILD) {
571 processing = false;
572 build_button.setEnabled(true);
573 cancel_button.setEnabled(false);
574 //preview_button.setEnabled(true);
575 simple_build_button.setEnabled(true);
576 simple_cancel_button.setEnabled(false);
577 //simple_preview_button.setEnabled(true);
578 int status = event.getStatus();
579 document.setSpecialCharacter(OptionsPane.SUCCESSFUL);
580 options_pane.resetFileEntry();
581 build_monitor.reset();
582 import_monitor.reset();
583 if(Gatherer.config.getMode() >= THRESHOLD) {
584 control_pane.add(button_pane, BorderLayout.SOUTH);
585 card_layout.show(main_pane, CONTROL);
586 }
587 }
588 // Otherwise its completed import but still got build to go
589 }
590 else {
591 processing = false;
592 cancel_button.setEnabled(false);
593 build_button.setEnabled(true);
594 // The build may have failed, but a previous index may still be in place
595 //preview_button.setEnabled(Gatherer.c_man.built());
596
597 simple_build_button.setEnabled(true);
598 simple_cancel_button.setEnabled(false);
599 //simple_preview_button.setEnabled(Gatherer.c_man.built());
600 if(event.getStatus() == GShell.CANCELLED) {
601 document.setSpecialCharacter(OptionsPane.CANCELLED);
602 }
603 else {
604 document.setSpecialCharacter(OptionsPane.UNSUCCESSFUL);
605 }
606 options_pane.resetFileEntry();
607 if(Gatherer.config.getMode() >= THRESHOLD) {
608 control_pane.add(button_pane, BorderLayout.SOUTH);
609 card_layout.show(main_pane, CONTROL);
610 }
611 }
612 }
613
614 private void configureHomeURL() {
615 // set up the home page for the current collection
616 Collection current_collection = Gatherer.c_man.getCollection();
617 String extra_args = "";
618 SearchTypeManager st_man = current_collection.cdm.searchtype_manager;
619 if (st_man.isMGPPEnabled()) {
620 // we need some more args on the url
621 String search_types = st_man.getSearchTypes();
622 if (search_types.equals("")) {
623 extra_args = "&ct=1&qt=0&qto=3";
624 } else if (search_types.equals("plain")) {
625 extra_args = "&ct=1&qt=0&qto=1";
626 } else if (search_types.equals("form")) {
627 extra_args = "&ct=1&qt=1&qto=2";
628 } else if (search_types.equals("plain,form")) {
629 extra_args = "&ct=1&qt=0&qto=3";
630 } else if (search_types.equals("form,plain")) {
631 extra_args = "&ct=1&qt=1&qto=3";
632 }
633 }
634 // Remember to add unique timestamp
635 homepage = Gatherer.config.exec_address.toString() + "?a=p&p=about&c=" + current_collection.getName()+"&l="+Gatherer.config.getLanguage()+extra_args + StaticStrings.TIMESTAMP_ARGUMENT + System.currentTimeMillis();
636
637 }
638
639
640 /** This class serves as the listener for actions on the build button. */
641 private class BuildButtonListener
642 implements ActionListener {
643 /** This method causes a call to be made to CollectionManager.importCollection(), which then imports and builds the collection as necessary.
644 * @param event An <strong>ActionEvent</strong> who, thanks to the power of object oriented programming, we don't give two hoots about.
645 * @see org.greenstone.gatherer.Gatherer
646 * @see org.greenstone.gatherer.collection.CollectionManager
647 * @see org.greenstone.gatherer.gui.BuildOptions
648 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
649 */
650 public void actionPerformed(ActionEvent event) {
651 // First we force the build options to be updated if we haven't already.
652 tree.valueChanged(null);
653
654 // Remember that for lower thresholds the above doesn't work, so try this instead
655 if(Gatherer.config.getMode() < THRESHOLD) {
656 options_pane.update(sargument_configuration_panel);
657 }
658
659 // Now go about building.
660 build_button.setEnabled(false);
661 cancel_button.setEnabled(true);
662 preview_button.setEnabled(false);
663
664 simple_build_button.setEnabled(false);
665 simple_cancel_button.setEnabled(true);
666 simple_preview_button.setEnabled(false);
667
668 document = options_pane.createNewLogDocument();
669 log_textarea.setDocument(document);
670 options_pane.log_textarea.setDocument(document);
671 // Change the view.
672 processing = true;
673 if(Gatherer.config.getMode() >= THRESHOLD) {
674 progress_pane.add(button_pane, BorderLayout.SOUTH);
675 card_layout.show(main_pane, PROGRESS);
676 }
677 // Reset the stop flag in all the process monitors, just incase.
678 ((GBuildProgressMonitor)build_monitor).reset();
679 copy_monitor.setStop(false);
680 import_monitor.setStop(false);
681 // Set removeold automatically.
682 if(Gatherer.c_man.ready() && Gatherer.c_man.built()) {
683 Gatherer.c_man.getCollection().build_options.setImportValue("removeold", true, null);
684 }
685 // Call CollectionManagers method to build collection.
686 Gatherer.c_man.importCollection();
687 }
688 }
689 /** This class serves as the listener for actions on the cancel button. */
690 private class CancelButtonListener
691 implements ActionListener {
692 /** This method attempts to cancel the current GShell task. It does this by first telling CollectionManager not to carry out any further action. This it turn tells the GShell to break from the current job immediately, without waiting for the processEnded message, and then kills the thread in an attempt to stop the process. The results of such an action are debatable.
693 * @param event An <strong>ActionEvent</strong> who, thanks to the power of object oriented programming, we don't give two hoots about.
694 * @see org.greenstone.gatherer.Gatherer
695 * @see org.greenstone.gatherer.collection.CollectionManager
696 * @see org.greenstone.gatherer.gui.BuildOptions
697 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
698 */
699 public void actionPerformed(ActionEvent event) {
700 build_button.setEnabled(true);
701 cancel_button.setEnabled(false);
702 preview_button.setEnabled(false);
703
704 simple_build_button.setEnabled(true);
705 simple_cancel_button.setEnabled(false);
706 simple_preview_button.setEnabled(false);
707
708 processing = false;
709 document.setSpecialCharacter(OptionsPane.CANCELLED);
710 if(Gatherer.config.getMode() >= THRESHOLD) {
711 control_pane.add(button_pane, BorderLayout.SOUTH);
712 card_layout.show(main_pane, CONTROL);
713 }
714 // Set the stop flag in all the process monitor.
715 import_monitor.setStop(true);
716 import_monitor.reset();
717 build_monitor.setStop(true);
718 build_monitor.reset();
719 // Set removeold automatically.
720 Gatherer.c_man.getCollection().build_options.setImportValue("removeold", true, null);
721 // Remove the collection lock.
722 //Gatherer.g_man.lockCollection(false, false);
723 }
724 }
725
726 private class PreviewButtonListener
727 implements ActionListener {
728
729 public void actionPerformed(ActionEvent event) {
730 configureHomeURL();
731 Gatherer.self.spawnBrowser(homepage);
732
733 }
734 }
735
736 /** The OptionTree is simply a tree structure that has a root node labelled "Options" and then has a child node for each available options screen. These screens are either combinations of the available import and build arguments, or a message log detailing the shell processes progress. */
737 private class OptionTree
738 extends JTree
739 implements TreeSelectionListener {
740 /** The model behind the tree. */
741 private DefaultTreeModel model = null;
742 /** The previous options view displayed, which is sometimes needed to refresh properly. */
743 private JPanel previous_pane = null;
744 /** The node corresponding to the building options view. */
745 private OptionTreeNode building = null;
746 /** The node corresponding to the importing options view. */
747 private OptionTreeNode importing = null;
748 /** The node corresponding to the log view. */
749 private OptionTreeNode log = null;
750 /** The root node of the options tree, which has no associated options view. */
751 private OptionTreeNode options = null;
752 /** Constructor.
753 * @see org.greenstone.gatherer.gui.CreatePane.OptionTreeNode
754 */
755 public OptionTree() {
756 super();
757
758 ToolTipManager.sharedInstance().registerComponent(this);
759 addTreeSelectionListener(this);
760 getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
761 setCellRenderer(new ToolTipTreeCellRenderer());
762 setRootVisible(false);
763 setToggleClickCount(1);
764
765 // Create tree.
766 building = new OptionTreeNode(Dictionary.get("CreatePane.Build"));
767 building.setToolTipText(Dictionary.get("CreatePane.Build_Tooltip"));
768 importing = new OptionTreeNode(Dictionary.get("CreatePane.Import"));
769 importing.setToolTipText(Dictionary.get("CreatePane.Import_Tooltip"));
770 log = new OptionTreeNode(Dictionary.get("CreatePane.Log"));
771 log.setToolTipText(Dictionary.get("CreatePane.Log_Tooltip"));
772 options = new OptionTreeNode(Dictionary.get("CreatePane.Options"));
773
774 model = new DefaultTreeModel(options);
775 setModel(model);
776 model.insertNodeInto(importing, options, 0);
777 model.insertNodeInto(building, options, 1);
778 model.insertNodeInto(log, options, 2);
779 // Expand the root node
780 expandPath(new TreePath(options));
781 }
782 /** Any implementation of TreeSelectionListener must include this method to allow this listener to know when the selection has changed. Here we swap the options view depending on the selected OptionTreeNode.
783 * @param event A <Strong>TreeSelectionEvent</strong> which contains all the information garnered when the event occured.
784 * @see org.greenstone.gatherer.gui.CreatePane.OptionTreeNode
785 */
786 public void valueChanged(TreeSelectionEvent event) {
787 TreePath path = null;
788 OptionTreeNode node = null;
789 //if(event != null) {
790 //path = event.getPath();
791 path = getSelectionPath();
792 if(path != null) {
793 node = (OptionTreeNode)path.getLastPathComponent();
794 }
795 //}
796 if(previous_pane != null) {
797 //target_pane.remove(previous_pane);
798 options_pane.update(previous_pane);
799 if(scroll_pane != null) {
800 right.remove(scroll_pane);
801 }
802 else {
803 right.remove(previous_pane);
804 }
805 previous_pane = null;
806 scroll_pane = null;
807 }
808 if(node != null && node.equals(building)) {
809 previous_pane = options_pane.buildBuild(null);
810 scroll_pane = new JScrollPane(previous_pane);
811 right.add(scroll_pane, BorderLayout.CENTER);
812 //target_pane.add(previous_pane, BorderLayout.CENTER);
813 }
814 else if(node != null && node.equals(importing)) {
815 previous_pane = options_pane.buildImport(null);
816 scroll_pane = new JScrollPane(previous_pane);
817 right.add(scroll_pane, BorderLayout.CENTER);
818 //target_pane.add(previous_pane, BorderLayout.CENTER);
819 }
820 else {
821 previous_pane = options_pane.buildLog();
822 right.add(previous_pane, BorderLayout.CENTER);
823 right.updateUI(); // we need to repaint the log pane, cos it hasn't changed since last time
824 ///ystem.err.println("I've added the log back to the right pane again.");
825 //target_pane.add(previous_pane, BorderLayout.CENTER);
826 }
827 //scroll_pane.setViewportView(previous_pane);
828 //previous_pane.validate();
829 right.validate();
830 //System.err.println("Current pane size: " + previous_pane.getSize());
831 //System.err.println("While its preferred size is: " + previous_pane.getPreferredSize());
832 }
833 }
834
835 /** The <strong>OptionTree</strong> is built from these nodes, each of which has several methods used in creating the option panes.
836 */
837 private class OptionTreeNode
838 extends DefaultMutableTreeNode
839 implements Comparable {
840 /** The text label given to this node in the tree. */
841 private String title = null;
842 /** a tool tip to be used for this node in the tree */
843 private String tool_tip = null;
844 /** Constructor.
845 * @param title The <strong>String</strong> which serves as this nodes title.
846 */
847 public OptionTreeNode(String title) {
848 super();
849 this.title = title;
850 }
851
852 /** This method compares two nodes for ordering.
853 * @param obj The <strong>Object</strong> to compare to.
854 * @return An <strong>int</strong> of one of the possible values -1, 0 or 1 indicating if this node is less than, equal to or greater than the target node respectively.
855 */
856 public int compareTo(Object obj) {
857 return title.compareTo(obj.toString());
858 }
859
860 /** This method checks if two nodes are equivalent.
861 * @param obj The <strong>Object</strong> to be tested against.
862 * @return A <strong>boolean</strong> which is <i>true</i> if the objects are equal, <i>false</i> otherwise.
863 */
864 public boolean equals(Object obj) {
865 if(compareTo(obj) == 0) {
866 return true;
867 }
868 return false;
869 }
870
871 /** get the tool tip */
872 public String getToolTipText() {
873 return tool_tip;
874 }
875
876 /** set the tool tip */
877 public void setToolTipText(String tip) {
878 tool_tip = tip;
879 }
880
881 /** Method to translate this node into a textual representation.
882 * @return A <strong>String</strong> which in this case is the title.
883 */
884 public String toString() {
885 return title;
886 }
887 }
888
889 // Adds tooltips to the tree nodes
890 private class ToolTipTreeCellRenderer
891 extends DefaultTreeCellRenderer {
892
893 public Component getTreeCellRendererComponent(JTree tree,
894 Object value,
895 boolean sel,
896 boolean expanded,
897 boolean leaf,
898 int row,
899 boolean hasFocus) {
900
901 super.getTreeCellRendererComponent(tree, value, sel,
902 expanded, leaf, row,
903 hasFocus);
904 if (value instanceof OptionTreeNode) {
905 String tip = ((OptionTreeNode) value).getToolTipText();
906 if (tip != null) {
907 setToolTipText(tip);
908 }
909 }
910 return this;
911 }
912 }
913}
Note: See TracBrowser for help on using the repository browser.