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

Last change on this file since 13582 was 13582, checked in by mdewsnip, 17 years ago

Removed some unnecessary package imports.

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