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

Last change on this file since 10259 was 10259, checked in by mdewsnip, 19 years ago

Created a new "remote" directory for classes related to using a remote Greenstone server.

  • Property svn:keywords set to Author Date Id Revision
File size: 40.6 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.DebugStream;
47import org.greenstone.gatherer.Configuration;
48import org.greenstone.gatherer.Dictionary;
49import org.greenstone.gatherer.Gatherer;
50import org.greenstone.gatherer.cdm.SearchTypeManager;
51import org.greenstone.gatherer.cdm.CollectionDesignManager;
52import org.greenstone.gatherer.collection.Collection;
53import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
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;
63import org.greenstone.gatherer.util.Utility;
64import org.greenstone.gatherer.util.ZipTools;
65
66/** 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>
67 * @author John Thompson, Greenstone Digital Library, University of Waikato
68 * @version 2.3
69 */
70public class CreatePane
71 extends JPanel
72 implements GShellListener {
73
74 static private Dimension ARGUMENT_SIZE = new Dimension(800,90);
75 /** The threshold for when the simple view is replaced by the complex one. */
76 static private final int THRESHOLD = Configuration.EXPERT_MODE;
77 /** An identifier for the control panel within the card layout. */
78 static private String CONTROL = "Control";
79 /** An identifier for the progress panel within the card layout. */
80 static private String PROGRESS = "Progress";
81 /** An identifier for the simple panel within the card layout. */
82 static private String SIMPLE = "Simple";
83
84 /** Determines the current view that should be shown for this pane. */
85 public boolean processing = false;
86 /** The options pane generates all the various option sheet configuations. */
87 public OptionsPane options_pane = null;
88 private AppendLineOnlyFileDocument document;
89 /** A card layout is used to store the separate configuration and progress panes. */
90 private CardLayout card_layout = null;
91 /** Stores a reference to the current collection. */
92 private Collection previous_collection = null;
93 /** This monitor tracks the build processes progress. */
94 private GShellProgressMonitor build_monitor = null;
95 /** This monitor tracks the import processes progress. */
96 private GShellProgressMonitor import_monitor = null;
97 /** The button for begining the building processes. */
98 private JButton build_button = null;
99 /** The button for stopping the building processes. */
100 private JButton cancel_button = null;
101 /** The button for viewing the collection. */
102 private JButton preview_button = null;
103 private JButton simple_build_button;
104 private JButton simple_cancel_button;
105 private JButton simple_preview_button;
106 /** The radio buttons for chnaging the build type (incremental/full) */
107 private JRadioButton full_build_radio_button;
108 private JRadioButton incremental_build_radio_button;
109 private JRadioButton sfull_build_radio_button;
110 private JRadioButton sincremental_build_radio_button;
111 /** The label displaying the number of documents in this collection. */
112 private JLabel document_count = null;
113 /** The label alongside the build progress bar gets some special treatment so... */
114 private JLabel progress_build_label = null;
115 /** The label alongside the import progress bar gets some special treatment so... */
116 private JLabel progress_import_label = null;
117 private JPanel bar_area;
118 /** The panel on which buttons are rendered on higher detail modes. */
119 private JPanel button_pane;
120 /** The pane which contains the controls for configuration. */
121 private JPanel control_pane = null;
122 /** The pane which has the card layout as its manager. */
123 private JPanel main_pane = null;
124 /** The pane which contains the progress information. */
125 private JPanel progress_pane = null;
126 /** The pane on the right-hand side - shows the requested options view */
127 private JPanel right = null;
128 /** The simple panel on which all of the available arguments are rendered. */
129 private JPanel sargument_configuration_panel;
130 /** The panel on which buttons are rendered on lower details modes. */
131 private JPanel sbutton_panel;
132 /** A simplified version for lower detail modes containing both the control and progress panes smooshed together. */
133 private JPanel simple_panel;
134 /** The inner panel of the simple pane which is global so that the bar_area can be added and removed from it. */
135 private JPanel sinner_panel;
136 /** The outer panel of the simple pane which is global so that the arguments pane can be added and removed from it. */
137 private JPanel souter_panel;
138 /** The scrolling pane for the log. */
139 private JScrollPane log_scroll;
140 /** The scrolling pane the simple arguments are rendered within. */
141 private JScrollPane sargument_configuration_scroll;
142 /** 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 */
143 private JScrollPane scroll_pane;
144 /** The message log for the entire session. */
145 private JTextArea log_textarea;
146 /** A tree used to display the currently available option views. */
147 private OptionTree tree = null;
148 /** An array used to pass arguments with dictionary calls. */
149 private String args[] = null;
150 /** The homepage address of the current collection */
151 private String homepage = null;
152
153
154 /** The constructor creates important helper classes, and initializes all the components.
155 * @see org.greenstone.gatherer.collection.CollectionManager
156 * @see org.greenstone.gatherer.gui.BuildOptions
157 * @see org.greenstone.gatherer.gui.CreatePane.BuildButtonListener
158 * @see org.greenstone.gatherer.gui.CreatePane.CancelButtonListener
159 * @see org.greenstone.gatherer.gui.CreatePane.OptionTree
160 * @see org.greenstone.gatherer.gui.OptionsPane
161 * @see org.greenstone.gatherer.shell.GBasicProgressMonitor
162 * @see org.greenstone.gatherer.shell.GBuildProgressMonitor
163 * @see org.greenstone.gatherer.shell.GImportProgressMonitor
164 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
165 */
166 public CreatePane() {
167 Collection collection = Gatherer.c_man.getCollection();
168 log_textarea = new JTextArea();
169 log_scroll = new JScrollPane(log_textarea);
170
171 // Create components
172 card_layout = new CardLayout();
173 // Control Pane
174 control_pane = new JPanel();
175 tree = new OptionTree();
176 button_pane = new JPanel();
177
178 // Progress Pane
179 progress_pane = new JPanel(); // One owner of the bar component
180 bar_area = new JPanel(); // This component will be shared about
181
182 progress_import_label = new JLabel();
183 Dictionary.registerText(progress_import_label, "CreatePane.Import_Progress");
184
185 import_monitor = new GImportProgressMonitor(); //GBasicProgressMonitor();
186 Gatherer.c_man.registerImportMonitor(import_monitor);
187
188 progress_build_label = new JLabel();
189 Dictionary.registerText(progress_build_label, "CreatePane.Build_Progress");
190
191 build_monitor = new GBuildProgressMonitor(import_monitor.getSharedProgress()); //GBasicProgressMonitor();
192 Gatherer.c_man.registerBuildMonitor(build_monitor);
193
194 // And the simple panel
195 simple_panel = new JPanel();
196 sbutton_panel = new JPanel();
197 sinner_panel = new JPanel();
198
199 //Radio buttons
200 incremental_build_radio_button = new JRadioButton();
201 Dictionary.registerBoth(incremental_build_radio_button, "CreatePane.Incremental_Build", "CreatePane.Incremental_Build_Tooltip");
202 full_build_radio_button = new JRadioButton();
203 Dictionary.registerBoth(full_build_radio_button, "CreatePane.Full_Build", "CreatePane.Full_Build_Tooltip");
204 sincremental_build_radio_button = new JRadioButton();
205 Dictionary.registerBoth(sincremental_build_radio_button, "CreatePane.Incremental_Build", "CreatePane.Incremental_Build_Tooltip");
206 sfull_build_radio_button = new JRadioButton();
207 Dictionary.registerBoth(sfull_build_radio_button, "CreatePane.Full_Build", "CreatePane.Full_Build_Tooltip");
208
209 // Buttons
210 BuildButtonListener bbl = new BuildButtonListener();
211 CancelButtonListener cbl = new CancelButtonListener();
212 PreviewButtonListener pbl = new PreviewButtonListener();
213
214 build_button = new GLIButton();
215 build_button.addActionListener(bbl);
216 build_button.setMnemonic(KeyEvent.VK_B);
217 Dictionary.registerBoth(build_button, "CreatePane.Build_Collection", "CreatePane.Build_Collection_Tooltip");
218
219 cancel_button = new GLIButton();
220 cancel_button.addActionListener(cbl);
221 cancel_button.setEnabled(false);
222 cancel_button.setMnemonic(KeyEvent.VK_C);
223 Dictionary.registerBoth(cancel_button, "CreatePane.Cancel_Build", "CreatePane.Cancel_Build_Tooltip");
224
225 preview_button = new GLIButton();
226 preview_button.addActionListener(pbl);
227 if(Gatherer.c_man != null) {
228 preview_button.setEnabled(Gatherer.c_man.built());
229 }
230 else {
231 preview_button.setEnabled(false);
232 }
233 preview_button.setMnemonic(KeyEvent.VK_P);
234 Dictionary.registerBoth(preview_button, "CreatePane.Preview_Collection", "CreatePane.Preview_Collection_Tooltip");
235
236 simple_build_button = new GLIButton();
237 simple_build_button.addActionListener(bbl);
238 simple_build_button.setMnemonic(KeyEvent.VK_B);
239 Dictionary.registerBoth(simple_build_button, "CreatePane.Build_Collection", "CreatePane.Build_Collection_Tooltip");
240
241 simple_cancel_button = new GLIButton();
242 simple_cancel_button.addActionListener(cbl);
243 simple_cancel_button.setEnabled(false);
244 simple_cancel_button.setMnemonic(KeyEvent.VK_C);
245 Dictionary.registerBoth(simple_cancel_button, "CreatePane.Cancel_Build", "CreatePane.Cancel_Build_Tooltip");
246
247 simple_preview_button = new GLIButton();
248 simple_preview_button.addActionListener(pbl);
249 if(Gatherer.c_man != null) {
250 simple_preview_button.setEnabled(Gatherer.c_man.built());
251 }
252 else {
253 simple_preview_button.setEnabled(false);
254 }
255 simple_preview_button.setMnemonic(KeyEvent.VK_P);
256 Dictionary.registerBoth(simple_preview_button, "CreatePane.Preview_Collection", "CreatePane.Preview_Collection_Tooltip");
257
258 bbl = null;
259 cbl = null;
260 pbl = null;
261 }
262
263
264 public void destroy() {
265 if(document != null) {
266 document.destroy();
267 }
268 }
269
270 /** This method is called to actually layout the components.
271 * @see org.greenstone.gatherer.Configuration
272 * @see org.greenstone.gatherer.Gatherer
273 */
274 public void display() {
275
276 int current_mode = Configuration.getMode();
277
278 //Complete/incremental build options panel
279 //For some reason I need to create seperate objects for each mode. Is there a better way??
280 ButtonGroup build_type_group = new ButtonGroup();
281 build_type_group.add(incremental_build_radio_button);
282 incremental_build_radio_button.setSelected(true); //Have incremental rebuild on by default
283 build_type_group.add(full_build_radio_button);
284 ButtonGroup sbuild_type_group = new ButtonGroup();
285 sbuild_type_group.add(sincremental_build_radio_button);
286 sincremental_build_radio_button.setSelected(true);
287 sbuild_type_group.add(sfull_build_radio_button);
288 JPanel build_type_pane = new JPanel(new GridLayout(2,1));
289 build_type_pane.add(full_build_radio_button);
290 build_type_pane.add(incremental_build_radio_button);
291 JPanel sbuild_type_pane = new JPanel(new GridLayout(2,1));
292 sbuild_type_pane.add(sfull_build_radio_button);
293 sbuild_type_pane.add(sincremental_build_radio_button);
294
295
296
297 // Build control_pane
298 JPanel left = new JPanel();
299 left.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
300 left.setLayout(new BorderLayout());
301 left.add(tree, BorderLayout.CENTER);
302 left.add(build_type_pane, BorderLayout.SOUTH);
303 //left.add(full_build_radio_button, BorderLayout.SOUTH);
304
305 right = new JPanel();
306 right.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
307 right.setLayout(new BorderLayout());
308
309 JPanel options_area = new JPanel();
310 options_area.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createTitledBorder(Dictionary.get("CreatePane.Options_Title"))));
311 options_area.setLayout(new BorderLayout());
312 options_area.add(left, BorderLayout.WEST);
313 options_area.add(right, BorderLayout.CENTER);
314
315 button_pane = new JPanel();
316 button_pane.setBorder(BorderFactory.createEmptyBorder(5,10,10,10));
317 button_pane.setLayout(new GridLayout(1,4));
318 button_pane.add(build_button);
319 button_pane.add(cancel_button);
320 button_pane.add(preview_button);
321
322 control_pane.setLayout(new BorderLayout());
323 control_pane.add(options_area, BorderLayout.CENTER);
324 control_pane.add(button_pane, BorderLayout.SOUTH);
325
326 // Build progress_pane
327 JPanel labels_pane = new JPanel();
328 labels_pane.setLayout(new GridLayout(2,1,0,5));
329 labels_pane.add(progress_import_label);
330 labels_pane.add(progress_build_label);
331
332 JPanel monitors_pane = new JPanel();
333 monitors_pane.setLayout(new GridLayout(2,1,0,5));
334 monitors_pane.add(import_monitor.getProgress());
335 monitors_pane.add(build_monitor.getProgress());
336
337 bar_area.setBorder(BorderFactory.createEmptyBorder(10,10,5,10));
338 bar_area.setLayout(new BorderLayout(5,5));
339 bar_area.add(labels_pane, BorderLayout.WEST);
340 bar_area.add(monitors_pane, BorderLayout.CENTER);
341
342 progress_pane.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
343 progress_pane.setLayout(new BorderLayout());
344 progress_pane.add(bar_area, BorderLayout.NORTH);
345 if(current_mode >= THRESHOLD) {
346 progress_pane.add(log_scroll, BorderLayout.CENTER);
347 }
348
349 // Simple panel
350 sbutton_panel.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
351 sbutton_panel.setLayout(new GridLayout(1,3));
352 sbutton_panel.add(simple_build_button);
353 sbutton_panel.add(simple_cancel_button);
354 sbutton_panel.add(simple_preview_button);
355
356 JPanel simple_bar_area = new JPanel(new GridLayout(2,1));
357 simple_bar_area.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
358 simple_bar_area.add(import_monitor.getSharedProgress());
359 simple_bar_area.add(sbutton_panel);
360
361 sinner_panel.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
362 sinner_panel.setLayout(new BorderLayout());
363 sinner_panel.add(sbuild_type_pane, BorderLayout.WEST);
364 //sinner_panel.add(full_build_radio_button, BorderLayout.WEST);
365 sinner_panel.add(simple_bar_area, BorderLayout.CENTER);
366
367 if(options_pane != null) {
368 sargument_configuration_panel = options_pane.buildImport(null);
369 sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
370 }
371 else {
372 sargument_configuration_panel = new JPanel();
373 }
374 sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
375 sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
376 souter_panel = new JPanel();
377 souter_panel.setSize(new Dimension(400,800));
378 souter_panel.setLayout(new GridLayout(2,1));
379 souter_panel.add(sargument_configuration_scroll);
380 souter_panel.add(sinner_panel);
381
382 simple_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
383 simple_panel.setLayout(new BorderLayout());
384 simple_panel.add(souter_panel, BorderLayout.NORTH);
385 if(current_mode < THRESHOLD) {
386 simple_panel.add(log_scroll, BorderLayout.CENTER);
387 }
388
389 // Main pane
390 main_pane = new JPanel(card_layout);
391 if(current_mode < THRESHOLD) { // Simple mode - add first
392 main_pane.add(simple_panel, SIMPLE);
393 }
394 main_pane.add(control_pane, CONTROL);
395 main_pane.add(progress_pane, PROGRESS);
396 if(current_mode >= THRESHOLD) { // Expert mode - add last
397 main_pane.add(simple_panel, SIMPLE);
398 }
399
400 this.setLayout(new BorderLayout());
401 this.add(main_pane, BorderLayout.CENTER);
402 }
403
404 /** 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.
405 * @see org.greenstone.gatherer.Gatherer
406 * @see org.greenstone.gatherer.collection.CollectionManager
407 * @see org.greenstone.gatherer.gui.CreatePane.OptionTree
408 */
409 public void gainFocus() {
410 if(Configuration.getMode() < THRESHOLD) {
411 card_layout.show(main_pane, SIMPLE);
412 }
413 else if(!processing) {
414 // Move the buttons to control
415 control_pane.add(button_pane, BorderLayout.SOUTH);
416 card_layout.show(main_pane, CONTROL);
417 }
418 else {
419 // Move the buttons to progress
420 progress_pane.add(button_pane, BorderLayout.SOUTH);
421 card_layout.show(main_pane, PROGRESS);
422 }
423 // Refresh the set of controls.
424 TreePath path = tree.getSelectionPath();
425 tree.clearSelection();
426 tree.setSelectionPath(path);
427
428 //Disable the full/incremental buttons if the collection has not been built.
429 if(Gatherer.c_man.built()) {
430 full_build_radio_button.setEnabled(true);
431 incremental_build_radio_button.setEnabled(true);
432 sfull_build_radio_button.setEnabled(true);
433 sincremental_build_radio_button.setEnabled(true);
434 }
435 else {
436 full_build_radio_button.setEnabled(false);
437 incremental_build_radio_button.setEnabled(false);
438 sfull_build_radio_button.setEnabled(false);
439 sincremental_build_radio_button.setEnabled(false);
440 }
441 }
442
443 /** We are informed when this view pane loses focus so we can update build options. */
444 public void loseFocus() {
445 tree.valueChanged(null);
446 }
447
448 /**
449 * Check to see if doing an incremental build is chosen.
450 * If not, the full rebuild option must be chosen.
451 * @return boolean - true if the collection should be rebuilt incrementally.
452 */
453 public boolean isIncremental() {
454 boolean incremental = false;
455
456 //This is horrible. What if the mode is changed, and different options are chosen on different modes??
457 if(Gatherer.c_man.built()) {
458 if(Configuration.getMode() >= THRESHOLD) {
459 incremental = incremental_build_radio_button.isSelected();
460 }
461 else {
462 incremental = sincremental_build_radio_button.isSelected();
463 }
464 }
465 else {
466 incremental = false; //The collection has not yet been built
467 }
468 return incremental;
469 }
470
471 /** All implementation of GShellListener must include this method so the listener can be informed of messages from the GShell.
472 * @param event A <strong>GShellEvent</strong> that contains, amoung other things, the message.
473 */
474 public synchronized void message(GShellEvent event) {
475 // Ignore the messages from RecPlug with 'show_progress' set (used for progress bars)
476 if (event.getMessage().startsWith("import.pl> RecPlug - ")) {
477 return;
478 }
479 document.appendLine(event.getMessage());
480 log_textarea.setCaretPosition(document.getLengthToNearestLine());
481 }
482
483 /** Called when the detail mode has changed which in turn may cause several import/build configuration arguments to be available/hidden
484 * @param mode the new mode as an int
485 */
486 public void modeChanged(int mode) {
487 // If we are below the complexity threshold ensure the simple controls are being shown
488 if(Configuration.getMode() < THRESHOLD) {
489 // Update the arguments
490 souter_panel.remove(sargument_configuration_scroll);
491 souter_panel.remove(sinner_panel);
492 if(options_pane != null) {
493 sargument_configuration_panel = options_pane.buildImport(null);
494 sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
495 }
496 else {
497 sargument_configuration_panel = new JPanel();
498 }
499 sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
500 sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
501 souter_panel.add(sargument_configuration_scroll);
502 souter_panel.add(sinner_panel);
503 // Remove the shared components from the expert panels
504 progress_pane.remove(log_scroll);
505 // And add to simple one
506 simple_panel.add(log_scroll, BorderLayout.CENTER);
507 // And bring the card to the front
508 card_layout.show(main_pane, SIMPLE);
509 }
510 // And if we are above the threshold change to the complex controls
511 else {
512 // Remove the shared components from the simple panel
513 simple_panel.remove(log_scroll);
514 // And add then to the expert ones
515 progress_pane.add(log_scroll, BorderLayout.CENTER);
516 // And bring the appropriate card to the front
517 if(!processing) {
518 control_pane.add(button_pane, BorderLayout.SOUTH);
519 card_layout.show(main_pane, CONTROL);
520 }
521 else {
522 progress_pane.add(button_pane, BorderLayout.SOUTH);
523 card_layout.show(main_pane, PROGRESS);
524 }
525 }
526 tree.valueChanged(null); // Ensure tree argument panels are rebuilt
527 }
528
529 /** 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.
530 * @param event A <strong>GShellEvent</strong> that contains details of the initial state of the <strong>GShell</strong> before task comencement.
531 */
532 public synchronized void processBegun(GShellEvent event) {
533 // We don't care. We'll get a more acurate start from the progress monitors.
534 }
535 /** All implementation of GShellListener must include this method so the listener can be informed when a GShell completes its task.
536 * @param event A <strong>GShellEvent</strong> that contains details of the final state of the <strong>GShell</strong> after task completion.
537 */
538 public synchronized void processComplete(GShellEvent event) {
539 if(event.getStatus() == GShell.OK) {
540 if(event.getType() == GShell.BUILD) {
541 processing = false;
542 build_button.setEnabled(true);
543 cancel_button.setEnabled(false);
544 //preview_button.setEnabled(true);
545 simple_build_button.setEnabled(true);
546 simple_cancel_button.setEnabled(false);
547 //simple_preview_button.setEnabled(true);
548 int status = event.getStatus();
549 document.setSpecialCharacter(OptionsPane.SUCCESSFUL);
550 options_pane.resetFileEntry();
551 build_monitor.reset();
552 import_monitor.reset();
553 if(Configuration.getMode() >= THRESHOLD) {
554 control_pane.add(button_pane, BorderLayout.SOUTH);
555 card_layout.show(main_pane, CONTROL);
556 }
557 }
558 // Otherwise its completed import but still got build to go
559 }
560 else {
561 processing = false;
562 cancel_button.setEnabled(false);
563 build_button.setEnabled(true);
564 // The build may have failed, but a previous index may still be in place
565 //preview_button.setEnabled(Gatherer.c_man.built());
566
567 simple_build_button.setEnabled(true);
568 simple_cancel_button.setEnabled(false);
569 //simple_preview_button.setEnabled(Gatherer.c_man.built());
570 if(event.getStatus() == GShell.CANCELLED) {
571 document.setSpecialCharacter(OptionsPane.CANCELLED);
572 }
573 else {
574 document.setSpecialCharacter(OptionsPane.UNSUCCESSFUL);
575 }
576 options_pane.resetFileEntry();
577 if(Configuration.getMode() >= THRESHOLD) {
578 control_pane.add(button_pane, BorderLayout.SOUTH);
579 card_layout.show(main_pane, CONTROL);
580 }
581 }
582 }
583
584
585 /** This method is invoked at any time there has been a significant change in the collection, such as saving, loading or creating.
586 * @param ready A <strong>boolean</strong> indicating if a collection is currently available.
587 * @see org.greenstone.gatherer.Gatherer
588 * @see org.greenstone.gatherer.collection.CollectionManager
589 * @see org.greenstone.gatherer.gui.BuildOptions
590 * @see org.greenstone.gatherer.gui.OptionsPane
591 */
592 public void refresh(int refresh_reason, boolean ready)
593 {
594 if (Gatherer.c_man == null || !ready) {
595 return;
596 }
597 Collection current_collection = Gatherer.c_man.getCollection();
598 if (current_collection != previous_collection && !Gatherer.c_man.isImporting()) {
599 this.options_pane = new OptionsPane(current_collection.import_options, current_collection.build_options);
600 if (previous_collection != null) {
601 // clear the log
602 Document log_document = log_textarea.getDocument();
603 if (log_document instanceof AppendLineOnlyFileDocument) {
604 ((AppendLineOnlyFileDocument) log_document).destroy();
605 }
606 }
607 previous_collection = current_collection;
608
609 }
610 // If we are in simple mode, we have to rebuild the simple arguments list
611 if(Configuration.getMode() < THRESHOLD) {
612 souter_panel.remove(sargument_configuration_scroll);
613 souter_panel.remove(sinner_panel);
614 sargument_configuration_panel = options_pane.buildImport(null);
615 sargument_configuration_panel = options_pane.buildBuild(sargument_configuration_panel);
616 sargument_configuration_scroll = new JScrollPane(sargument_configuration_panel);
617 sargument_configuration_scroll.setPreferredSize(ARGUMENT_SIZE);
618 souter_panel.add(sargument_configuration_scroll);
619 souter_panel.add(sinner_panel);
620 }
621 tree.valueChanged(null);
622
623 // Validate the preview button
624 if (Gatherer.c_man.built() && Configuration.library_url != null) {
625 preview_button.setEnabled(true);
626 simple_preview_button.setEnabled(true);
627 }
628 else {
629 preview_button.setEnabled(false);
630 simple_preview_button.setEnabled(false);
631 }
632 }
633
634
635 private void configureHomeURL() {
636 // set up the home page for the current collection
637 Collection current_collection = Gatherer.c_man.getCollection();
638 String site = Configuration.site_name; // for GS3 colls
639 String extra_args = "";
640 SearchTypeManager st_man = current_collection.cdm.searchtype_manager;
641 if (!Gatherer.GS3 && st_man.isMGPPEnabled()) {
642 // we need some more args on the url
643 String search_types = st_man.getSearchTypes();
644 if (search_types.equals("")) {
645 extra_args = "&ct=1&qt=0&qto=3";
646 } else if (search_types.equals("plain")) {
647 extra_args = "&ct=1&qt=0&qto=1";
648 } else if (search_types.equals("form")) {
649 extra_args = "&ct=1&qt=1&qto=2";
650 } else if (search_types.equals("plain,form")) {
651 extra_args = "&ct=1&qt=0&qto=3";
652 } else if (search_types.equals("form,plain")) {
653 extra_args = "&ct=1&qt=1&qto=3";
654 }
655 }
656 // Remember to add unique timestamp
657 if (Gatherer.GS3) {
658 homepage = Configuration.library_url.toString() + Configuration.getServletPath()+ "?a=p&sa=about&c=" + current_collection.getName()+"&l="+Configuration.getLanguage(); //+extra_args + StaticStrings.TIMESTAMP_ARGUMENT + System.currentTimeMillis();
659 } else {
660 homepage = Configuration.library_url.toString() + "?a=p&p=about&c=" + current_collection.getName()+"&l="+Configuration.getLanguage()+extra_args + StaticStrings.TIMESTAMP_ARGUMENT + System.currentTimeMillis();
661 }
662 }
663
664
665 /** This class serves as the listener for actions on the build button. */
666 private class BuildButtonListener
667 implements ActionListener {
668 /**
669 * This method checks to see what needs to be done for a build, and starts the process off.
670 * A complete build proccess is started by {@link CollectionManager.importCollection()}, which then imports and builds the collection.
671 * However, this doesn't always happen, as sometimes an incremental build will do :-)
672 * @param event An <strong>ActionEvent</strong> who, thanks to the power of object oriented programming, we don't give two hoots about.
673 * @see org.greenstone.gatherer.Gatherer
674 * @see org.greenstone.gatherer.collection.CollectionManager
675 * @see org.greenstone.gatherer.gui.BuildOptions
676 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
677 */
678 public void actionPerformed(ActionEvent event) {
679 Collection collection = Gatherer.c_man.getCollection();
680 String collection_name = collection.getName();
681 if(!collection.getMetadataChanged() && !collection.getFilesChanged() && isIncremental()) {
682 //Only design options have changes, and we want to be smart in the way we handle them.
683 int rebuildTypeRequired = CollectionDesignManager.getRebuildTypeRequired();
684
685 if(rebuildTypeRequired == CollectionDesignManager.UPDATE_COLLECT_CFG && Gatherer.isGsdlRemote) {
686 //Special case when the GLI is an applet: Upload the collect.cfg to server
687 //This is already handled by CollectionDesignManager.save()
688 DebugStream.println("Just want to upload collect.cfg, but this has already been done");
689 }
690 else if(rebuildTypeRequired == CollectionDesignManager.BUILDCOL) {
691 //First upload the collect.cfg file
692 ZipTools.zipup(Gatherer.getCollectDirectoryPath(), collection_name, Utility.CONFIG_FILE, null, "", "");
693 RemoteGreenstoneServer.upload_url_zip(collection_name, "etc", "", null);
694
695 //Just run the buildcol command.
696 DebugStream.println("Just want to run buildcol.pl");
697 prepareForBuild();
698 Gatherer.c_man.buildCollection();
699 }
700 else if(rebuildTypeRequired == CollectionDesignManager.ALL) {
701 //Do a usual build.
702 DebugStream.println("Want to do a complete build");
703 prepareForBuild();
704 Gatherer.c_man.importCollection(); //This starts the building process.
705 }
706 else {
707 //Nothing at all needs doing.
708 //This is bad HCI. Maybe should disable the build button in this situation?
709 System.err.println("Want to build the collection but nothing needs doing.");
710 }
711 }
712 else {
713 //Do a complete build.
714 prepareForBuild();
715 Gatherer.c_man.importCollection(); //This starts the building process.
716 }
717 //Re-setting the rebuildTypeRequired is handled by CollectionManager.processComplete(GShellEvent)
718 }
719
720 /**
721 * This does some stuff that is needed before a collection can be built.
722 * For example, buttons are enabled/disabled, and certain flags are set.
723 * This is called from {@link actionPerformed(ActionEvent)}
724 */
725 private void prepareForBuild() {
726 // First we force the build options to be updated if we haven't already.
727 tree.valueChanged(null);
728
729 // Remember that for lower thresholds the above doesn't work, so try this instead
730 if(Configuration.getMode() < THRESHOLD) {
731 options_pane.update(sargument_configuration_panel);
732 }
733
734 // Now go about building.
735 build_button.setEnabled(false);
736 cancel_button.setEnabled(true);
737 preview_button.setEnabled(false);
738
739 simple_build_button.setEnabled(false);
740 simple_cancel_button.setEnabled(true);
741 simple_preview_button.setEnabled(false);
742
743 document = options_pane.createNewLogDocument();
744 log_textarea.setDocument(document);
745 options_pane.log_textarea.setDocument(document);
746 // Change the view.
747 processing = true;
748 if(Configuration.getMode() >= THRESHOLD) {
749 progress_pane.add(button_pane, BorderLayout.SOUTH);
750 card_layout.show(main_pane, PROGRESS);
751 }
752 // Reset the stop flag in all the process monitors, just incase.
753 ((GBuildProgressMonitor)build_monitor).reset();
754 import_monitor.setStop(false);
755 // Set removeold automatically.
756 if(Gatherer.c_man.ready() && Gatherer.c_man.built()) {
757 Gatherer.c_man.getCollection().import_options.setValue("removeold", true, null);
758 }
759 }
760 }
761
762
763 /** This class serves as the listener for actions on the cancel button. */
764 private class CancelButtonListener
765 implements ActionListener {
766 /** 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.
767 * @param event An <strong>ActionEvent</strong> who, thanks to the power of object oriented programming, we don't give two hoots about.
768 * @see org.greenstone.gatherer.Gatherer
769 * @see org.greenstone.gatherer.collection.CollectionManager
770 * @see org.greenstone.gatherer.gui.BuildOptions
771 * @see org.greenstone.gatherer.shell.GShellProgressMonitor
772 */
773 public void actionPerformed(ActionEvent event) {
774 build_button.setEnabled(false);
775 cancel_button.setEnabled(false);
776 preview_button.setEnabled(false);
777
778 simple_build_button.setEnabled(false);
779 simple_cancel_button.setEnabled(false);
780 simple_preview_button.setEnabled(false);
781
782 processing = false;
783 document.setSpecialCharacter(OptionsPane.CANCELLED);
784 if(Configuration.getMode() >= THRESHOLD) {
785 control_pane.add(button_pane, BorderLayout.SOUTH);
786 card_layout.show(main_pane, CONTROL);
787 }
788 // Set the stop flag in all the process monitor.
789 import_monitor.setStop(true);
790 import_monitor.reset();
791 build_monitor.setStop(true);
792 build_monitor.reset();
793 // Set removeold automatically.
794 Gatherer.c_man.getCollection().import_options.setValue("removeold", true, null);
795 // Remove the collection lock.
796 //Gatherer.g_man.lockCollection(false, false);
797 }
798 }
799
800 private class PreviewButtonListener
801 implements ActionListener {
802
803 public void actionPerformed(ActionEvent event) {
804 Gatherer.c_man.getCollection().cdm.save(); // save the config file just in case
805 configureHomeURL();
806 Gatherer.self.spawnBrowser(homepage);
807
808 }
809 }
810
811 /** 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. */
812 private class OptionTree
813 extends JTree
814 implements TreeSelectionListener {
815 /** The model behind the tree. */
816 private DefaultTreeModel model = null;
817 /** The previous options view displayed, which is sometimes needed to refresh properly. */
818 private JPanel previous_pane = null;
819 /** The node corresponding to the building options view. */
820 private OptionTreeNode building = null;
821 /** The node corresponding to the importing options view. */
822 private OptionTreeNode importing = null;
823 /** The node corresponding to the log view. */
824 private OptionTreeNode log = null;
825 /** The root node of the options tree, which has no associated options view. */
826 private OptionTreeNode options = null;
827 /** Constructor.
828 * @see org.greenstone.gatherer.gui.CreatePane.OptionTreeNode
829 */
830 public OptionTree() {
831 super();
832
833 ToolTipManager.sharedInstance().registerComponent(this);
834 addTreeSelectionListener(this);
835 getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
836 setCellRenderer(new ToolTipTreeCellRenderer());
837 setRootVisible(false);
838 setToggleClickCount(1);
839
840 // Create tree.
841 building = new OptionTreeNode(Dictionary.get("CreatePane.Build"));
842 building.setToolTipText(Dictionary.get("CreatePane.Build_Tooltip"));
843 importing = new OptionTreeNode(Dictionary.get("CreatePane.Import"));
844 importing.setToolTipText(Dictionary.get("CreatePane.Import_Tooltip"));
845 log = new OptionTreeNode(Dictionary.get("CreatePane.Log"));
846 log.setToolTipText(Dictionary.get("CreatePane.Log_Tooltip"));
847 options = new OptionTreeNode(Dictionary.get("CreatePane.Options"));
848
849 model = new DefaultTreeModel(options);
850 setModel(model);
851 model.insertNodeInto(importing, options, 0);
852 model.insertNodeInto(building, options, 1);
853 model.insertNodeInto(log, options, 2);
854 // Expand the root node
855 expandPath(new TreePath(options));
856 }
857 /** 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.
858 * @param event A <Strong>TreeSelectionEvent</strong> which contains all the information garnered when the event occured.
859 * @see org.greenstone.gatherer.gui.CreatePane.OptionTreeNode
860 */
861 public void valueChanged(TreeSelectionEvent event) {
862 TreePath path = null;
863 OptionTreeNode node = null;
864 //if(event != null) {
865 //path = event.getPath();
866 path = getSelectionPath();
867 if(path != null) {
868 node = (OptionTreeNode)path.getLastPathComponent();
869 }
870 //}
871 if(previous_pane != null) {
872 //target_pane.remove(previous_pane);
873 options_pane.update(previous_pane);
874 if(scroll_pane != null) {
875 right.remove(scroll_pane);
876 }
877 else {
878 right.remove(previous_pane);
879 }
880 previous_pane = null;
881 scroll_pane = null;
882 }
883 if(node != null && node.equals(building)) {
884 previous_pane = options_pane.buildBuild(null);
885 scroll_pane = new JScrollPane(previous_pane);
886 right.add(scroll_pane, BorderLayout.CENTER);
887 //target_pane.add(previous_pane, BorderLayout.CENTER);
888 }
889 else if(node != null && node.equals(importing)) {
890 previous_pane = options_pane.buildImport(null);
891 scroll_pane = new JScrollPane(previous_pane);
892 right.add(scroll_pane, BorderLayout.CENTER);
893 //target_pane.add(previous_pane, BorderLayout.CENTER);
894 }
895 else {
896 if (options_pane != null) {
897 previous_pane = options_pane.buildLog();
898 right.add(previous_pane, BorderLayout.CENTER);
899 right.updateUI(); // we need to repaint the log pane, cos it hasn't changed since last time
900 ///ystem.err.println("I've added the log back to the right pane again.");
901 //target_pane.add(previous_pane, BorderLayout.CENTER);
902 }
903 }
904 //scroll_pane.setViewportView(previous_pane);
905 //previous_pane.validate();
906 right.validate();
907 //System.err.println("Current pane size: " + previous_pane.getSize());
908 //System.err.println("While its preferred size is: " + previous_pane.getPreferredSize());
909 }
910 }
911
912 /** The <strong>OptionTree</strong> is built from these nodes, each of which has several methods used in creating the option panes.
913 */
914 private class OptionTreeNode
915 extends DefaultMutableTreeNode
916 implements Comparable {
917 /** The text label given to this node in the tree. */
918 private String title = null;
919 /** a tool tip to be used for this node in the tree */
920 private String tool_tip = null;
921 /** Constructor.
922 * @param title The <strong>String</strong> which serves as this nodes title.
923 */
924 public OptionTreeNode(String title) {
925 super();
926 this.title = title;
927 }
928
929 /** This method compares two nodes for ordering.
930 * @param obj The <strong>Object</strong> to compare to.
931 * @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.
932 */
933 public int compareTo(Object obj) {
934 return title.compareTo(obj.toString());
935 }
936
937 /** This method checks if two nodes are equivalent.
938 * @param obj The <strong>Object</strong> to be tested against.
939 * @return A <strong>boolean</strong> which is <i>true</i> if the objects are equal, <i>false</i> otherwise.
940 */
941 public boolean equals(Object obj) {
942 if(compareTo(obj) == 0) {
943 return true;
944 }
945 return false;
946 }
947
948 /** get the tool tip */
949 public String getToolTipText() {
950 return tool_tip;
951 }
952
953 /** set the tool tip */
954 public void setToolTipText(String tip) {
955 tool_tip = tip;
956 }
957
958 /** Method to translate this node into a textual representation.
959 * @return A <strong>String</strong> which in this case is the title.
960 */
961 public String toString() {
962 return title;
963 }
964 }
965
966 // Adds tooltips to the tree nodes
967 private class ToolTipTreeCellRenderer
968 extends DefaultTreeCellRenderer {
969
970 public Component getTreeCellRendererComponent(JTree tree,
971 Object value,
972 boolean sel,
973 boolean expanded,
974 boolean leaf,
975 int row,
976 boolean hasFocus) {
977
978 super.getTreeCellRendererComponent(tree, value, sel,
979 expanded, leaf, row,
980 hasFocus);
981 if (value instanceof OptionTreeNode) {
982 String tip = ((OptionTreeNode) value).getToolTipText();
983 if (tip != null) {
984 setToolTipText(tip);
985 }
986 }
987 return this;
988 }
989 }
990}
Note: See TracBrowser for help on using the repository browser.