source: other-projects/FileTransfer-WebSocketPair/testGXTWithGreenstone/src/org/greenstone/gatherer/gui/CreatePane.java@ 33053

Last change on this file since 33053 was 33053, checked in by ak19, 5 years ago

I still had some stuff of Nathan Kelly's (FileTransfer-WebSocketPair) sitting on my USB. Had already commited the Themes folder at the time, 2 years back. Not sure if he wanted this additional folder commited. But I didn't want to delete it and decided it will be better off on SVN. When we use his project, if we find we didn't need this test folder, we can remove it from svn then.

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