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

Last change on this file since 17940 was 17940, checked in by kjdon, 15 years ago

I think I have disabled scheduling for systems specialist mode. now only available for expert mode

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