source: main/trunk/gli/src/org/greenstone/gatherer/gui/GUIManager.java@ 34284

Last change on this file since 34284 was 34284, checked in by ak19, 4 years ago

After testing on client-GLI, rolling back uploading the converted or exported meta.csv file to the remote dir if created anywhere inside the collection folder other than the import dir.

  • Property svn:keywords set to Author Date Id Revision
File size: 49.9 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.datatransfer.*;
41import java.awt.event.*;
42import java.io.File;
43import java.lang.*;
44import java.net.*;
45import java.util.*;
46import javax.swing.*;
47import javax.swing.event.*;
48import javax.swing.filechooser.*;
49import javax.swing.plaf.*;
50import javax.swing.text.*;
51import org.greenstone.gatherer.Configuration;
52import org.greenstone.gatherer.DebugStream;
53import org.greenstone.gatherer.Dictionary;
54import org.greenstone.gatherer.Gatherer;
55import org.greenstone.gatherer.collection.Collection;
56import org.greenstone.gatherer.collection.CollectionManager;
57import org.greenstone.gatherer.file.FileOpenActionListener;
58import org.greenstone.gatherer.file.WorkspaceTree;
59import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame;
60import org.greenstone.gatherer.gui.tree.DragTree;
61import org.greenstone.gatherer.metadata.FilenameEncoding;
62import org.greenstone.gatherer.metadata.MetadataSet;
63import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
64import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
65import org.greenstone.gatherer.util.JarTools;
66import org.greenstone.gatherer.util.StaticStrings;
67import org.greenstone.gatherer.util.Utility;
68
69import org.greenstone.gatherer.metadata.MetadataToCSV;
70
71/** The GUIManager is in charge of creating the Gatherer window frame then filling it with the goodness of the view panes. GUIManager not only creates these panes, but allows some messaging between them. Furthermore GUIManager includes functionality from menu driven choices, simply as it was easier to put it here once and have it accessible from all pane children. */
72public class GUIManager
73 extends JFrame
74 implements ActionListener, ChangeListener, WindowFocusListener{
75 /** The download pane contains controls for downloading internet sites. */
76 public DownloadPane download_pane = null;
77 /** The gather pane is more like a file manager where you drag files from one tree to another. */
78 public GatherPane gather_pane = null;
79 /** The enrich pane is used to assign, edit and remove metadata from files within the collection. */
80 public EnrichPane enrich_pane = null;
81 /** The design pane allows you to edit the design of the library in terms of the collection configuration file. - the stuff that requires rebuilding */
82 public DesignPane design_pane = null;
83 /** The create pane contains scripting options for importing and building collections into libraries. */
84 public CreatePane create_pane = null;
85 /** The format pane allows you to edit the design of the library in terms of the collection configuration file. - the stuff that doesn't require rebuilding */
86 public FormatPane format_pane = null;
87
88 public FileOpenActionListener foa_listener = new FileOpenActionListener();
89
90 /** A reference to the currently instantiated help window, if any. */
91 private HelpFrame help = null;
92 /** The menu bar. */
93 public MenuBar menu_bar = null;
94 public MetaAuditFrame meta_audit;
95 /** Are certain panes currently locked? */
96 private boolean locked = false;
97 /** The size of the Gatherer window. */
98 private Dimension size = null;
99 /** The panel within the window that other components are placed on. */
100 private JPanel content_pane = null;
101 /** The last view pane selected. */
102 private JPanel previous_pane;
103 /** The main tab pane containing the different views, available here to trap view change events. */
104 private JTabbedPane tab_pane = null;
105 /** A threaded tab changer to try and avoid NPE on exit. */
106 private TabUpdater tab_updater = null;
107
108 final static String newline = "\n";
109 final static String space = " ";
110
111
112 /**Constructor. Enable window events and arranges all other components.
113 * @param size The intial <strong>Dimension</strong> of the screen.
114 */
115 public GUIManager(Dimension size) {
116 super();
117 this.setComponentOrientation(Dictionary.getOrientation());
118 // Initialization
119 this.help = new HelpFrame();
120 this.size = size;
121
122 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
123
124 // Add a focus listener to ourselves. Thus if we gain focus when a Modal Dialog should instead have it, we can try to bring the modal dialog to the fore.
125 this.addFocusListener(new GLIGUIFocusListener());
126
127 this.addWindowFocusListener(this);
128
129 // Make the Tool tip hang around for a rediculous amount of time.
130 ToolTipManager.sharedInstance().setDismissDelay(10000);
131
132 // Set up some other UI stuff. (fonts handled in Gatherer.main())
133 UIManager.put("FileChooser.lookInLabelText", Dictionary.get("SaveCollectionBox.Look_In"));
134 UIManager.put("FileChooser.filesOfTypeLabelText", Dictionary.get("SaveCollectionBox.Files_Of_Type"));
135 UIManager.put("FileChooser.fileNameLabelText", Dictionary.get("SaveCollectionBox.File_Name"));
136
137 // JOptionPane options
138 // http://www.java2s.com/Tutorial/Java/0240__Swing/SettingJOptionPanebuttonlabelstoFrench.htm
139 UIManager.put("OptionPane.cancelButtonText", Dictionary.get("General.Cancel"));
140 UIManager.put("OptionPane.noButtonText", Dictionary.get("General.No"));
141 UIManager.put("OptionPane.okButtonText", Dictionary.get("General.OK"));
142 UIManager.put("OptionPane.yesButtonText", Dictionary.get("General.Yes"));
143 }
144
145
146 public void windowGainedFocus(WindowEvent e)
147 {
148 }
149
150
151 public void windowLostFocus(WindowEvent e)
152 {
153 // Save the loaded collection
154 if (Gatherer.c_man != null && Gatherer.c_man.ready() && Gatherer.c_man.getCollection().cdm != null) {
155 Gatherer.c_man.saveCollection();
156 }
157 }
158
159
160 private class GLIGUIFocusListener
161 extends FocusAdapter {
162 public void focusGained(FocusEvent e) {
163 if (ModalDialog.current_modal != null) {
164 ModalDialog.current_modal.makeVisible();
165 ModalDialog.current_modal.toFront();
166 }
167 }
168 }
169
170 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured. In this case we are listening to actions from the menu-bar, and should react appropriately.
171 * @param event An <strong>ActionEvent</strong> containing information about the action that has occured.
172 */
173 public void actionPerformed(ActionEvent event) {
174 Object esrc = event.getSource();
175 // *************
176 // File Options.
177 // *************
178 if (esrc == menu_bar.file_associations) {
179 Gatherer.assoc_man.edit();
180 }
181 else if (esrc == menu_bar.file_close) {
182 saveThenCloseCurrentCollection();
183 }
184 else if (esrc == menu_bar.file_delete) {
185 //new DeleteCollectionTask().start();
186 SwingUtilities.invokeLater(new DeleteCollectionTask());
187 }
188 else if (esrc == menu_bar.file_cdimage) {
189 WriteCDImagePrompt wcdip = new WriteCDImagePrompt();
190 wcdip.display();
191 wcdip.destroy();
192 wcdip = null;
193 }
194 else if (esrc == menu_bar.file_exportas) {
195 ExportAsPrompt eap = new ExportAsPrompt();
196 TestingPreparation.setNamesRecursively(eap);
197 eap.display();
198 eap.destroy();
199 eap = null;
200 }
201 else if (esrc == menu_bar.file_exportmeta || esrc == menu_bar.file_convertmeta) {
202 String currCollName = Gatherer.c_man.getCollection().getName();
203 String collection_directory_path = CollectionManager.getCollectionDirectoryPath(currCollName);
204
205 String importDir = collection_directory_path + "import";
206
207 boolean convertMode = false;
208 String startDir = collection_directory_path;
209 if(esrc == menu_bar.file_convertmeta) {
210 startDir = importDir;
211 convertMode = true;
212 }
213
214 File csvFile = MetadataToCSV.chooseMetaCSVFile(startDir, convertMode, this);
215 if(csvFile != null) {
216 MetadataToCSV toCSV = new MetadataToCSV(collection_directory_path, csvFile);
217
218 boolean success = false;
219 if(esrc == menu_bar.file_convertmeta) {
220 success = toCSV.convertMetaXMLToCSV(csvFile, this);
221 } else {
222 success = toCSV.exportMetaXMLToCSV(csvFile);
223 }
224
225 // refresh coll view if meta.csv was created somewhere inside this coll's import folder
226 // And for remote case, also upload any new file that's inside
227 // the collection's import dir to the remote server
228 if(success && csvFile.exists() && csvFile.getAbsolutePath().startsWith(importDir)) {
229 if(Gatherer.isGsdlRemote) {
230 Gatherer.remoteGreenstoneServer.uploadFilesIntoCollection(currCollName, new File[] {csvFile}, csvFile.getParentFile());
231 }
232 Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
233 }
234 }
235
236 }
237 else if (esrc == menu_bar.file_exit) {
238 exit();
239 }
240 else if (esrc == menu_bar.file_new) {
241 //new NewCollectionTask().start();
242 SwingUtilities.invokeLater(new NewCollectionTask());
243 }
244 else if (esrc == menu_bar.file_open) {
245 //new OpenCollectionTask().start(); // will cause an EDT access violation exception
246 // since the GUI stuff of opening a collection is not done in a Swing thread
247 SwingUtilities.invokeLater(new OpenCollectionTask());
248 }
249 else if (esrc == menu_bar.file_options) {
250 new Preferences();
251 }
252 else if (esrc == menu_bar.file_save) {
253 // Very important: make sure metadata values are saved too
254 enrich_pane.stopEditingAndRebuild();
255 // Make sure all the metadata has been saved to file
256 MetadataXMLFileManager.saveMetadataXMLFiles();
257
258 Gatherer.c_man.saveCollection();
259 }
260
261 // *************
262 // Edit Options.
263 // *************
264 else if(esrc == menu_bar.edit_copy) {
265 try {
266 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
267 // Get the component with selected text as a JTextComponent
268 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();//getFocusOwner();
269 text.copy();
270 }
271 catch (Exception cce) {
272 // If the component is not a text component ignore the copy command
273 DebugStream.println(cce.toString());
274 }
275 }
276 else if(esrc == menu_bar.edit_cut) {
277 try {
278 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
279 // Get the component with selected text as a JTextComponent
280 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
281 // Cut the text to the clipboard
282 text.cut();
283 }
284 catch (ClassCastException cce) {
285 // If the component is not a text component ignore the cut command
286 DebugStream.println(cce.toString());
287 }
288 }
289 else if(esrc == menu_bar.edit_paste) {
290 try {
291 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
292 // Get the component with selected text as a JTextComponent
293 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
294 // Cut the text to the clipboard
295 text.paste();
296 }
297 catch (ClassCastException cce) {
298 // If the component is not a text component ignore the paste command
299 DebugStream.println(cce.toString());
300 }
301 }
302 else if(esrc == menu_bar.edit_config) {
303 if(Gatherer.c_man.getCollection() != null) {
304 // Before we open the current collection's collectionConfig.xml for editing,
305 // need to make sure any presently unsaved edits are saved into collConfig
306 // so they are reflected in this config file when loaded into the editor for editing.
307 // A simple Gatherer.c_man.saveCollection() is not sufficient: it won't save ongoing
308 // edits in the currently selected GLI Pane (where relevant to colcfg)
309
310 // Whenever a user swaps from one GLI pane to another, loseFocus() is called on the pane
311 // and for some GLI Panes, this triggers a collection save, but notably also triggers a
312 // loseFocus() on the pane's editing fields/controls, which saves any ongoing mods in that
313 // pane to the collectionConfiguration file.
314 // - See loseFocus() of BaseConfigPane.java (that only SOME gli Pane's inherit from)
315 // and also apparent in GUIManager.windowLostFocus().
316 // - And for implementations of Control.loseFocus(), see for example via
317 // CollectionManager.loadDesignDetails() -> GeneralManager (for Format > General tab)
318 // which leads to GeneralManager.loseFocus() which gets "Called to store the current
319 // value of the components" - of its Controls. Exactly the behaviour we want!
320
321 // Not all GLI Panes inherit from BaseConfigPane, but then, not all GLI Panes
322 // make changes to the collection Config file; e.g. the Gather pane makes changes to
323 // the file system, Enrich makes changes to metadata.xml files and *.mds metadata sets
324 // files. But Design and Format panes make changes to collectionConfig.xml.
325 // In theory Create pane ought to as well, e.g. can set import options which also exists
326 // as ImportOptions in collectionConfig.xml, but they're not linked (yet) and Create pane
327 // doesn't inherit from BaseConfigPane. CreatePane's loseFocus() also don't call
328 // for the the collection to be saved.
329
330 // What all this means is that when we prepare to open the collectionConfig.xml,
331 // we want a collection save but want also the current state of GLI edits to be saved
332 // into collConfig before we display the collConfig file for editing.
333 // To trigger this behaviour we want to call loseFocus() on the current pane, called
334 // "previous_pane". That method may or may not force a save to collConfig,
335 // depending on whether it is warranted for that pane, but in such cases it will also
336 // cascade the loseFocus() call to the controls in that pane, who will save their current
337 // values into the colcfg in memory before this gets saved to the colCfg.xml file.
338
339 if(previous_pane != null) {
340 doLoseFocus();
341 }
342 //Gatherer.c_man.saveCollection(); //shouldn't have to do this, in theory. See above comment
343
344 ConfigFileEditor configEditor = new ConfigFileEditor();
345 configEditor.setVisible(true);
346 configEditor.setSize(900,700);
347 }
348 }
349
350 // *************
351 // Help Options.
352 // *************
353 else if (esrc == menu_bar.help_general) {
354 HelpFrame.setView("introduction");
355 }
356 else if (esrc == menu_bar.help_download) {
357 HelpFrame.setView("themirrorview");
358 }
359 else if (esrc == menu_bar.help_gather) {
360 HelpFrame.setView("collectingfiles");
361 }
362 else if (esrc == menu_bar.help_enrich) {
363 HelpFrame.setView("enrichingacollection");
364 }
365 else if (esrc == menu_bar.help_design) {
366 HelpFrame.setView("designingacollection");
367 }
368 else if (esrc == menu_bar.help_create) {
369 HelpFrame.setView("producingthecollection");
370 }
371 else if (esrc == menu_bar.help_format) {
372 HelpFrame.setView("formattingacollection");
373 }
374 else if (esrc == menu_bar.help_about) {
375 new AboutDialog(this);
376 }
377 }
378
379
380 /** Any actions that should happen after the display of the Gatherer window can be called here. Currently only updates the browser pane if it is active to work around bug in Mozilla renderer implementation.
381 */
382 public void afterDisplay() {
383 if (download_pane != null) {
384 download_pane.afterDisplay();
385 }
386 enrich_pane.afterDisplay();
387 }
388
389
390 public void closeCurrentCollection()
391 {
392 tab_pane.setSelectedComponent(gather_pane);
393 Gatherer.c_man.closeCollection();
394 FilenameEncoding.closeCollection(); // clear filename-to-encodings map
395 }
396
397
398 public void saveThenCloseCurrentCollection()
399 {
400 Gatherer.c_man.saveCollection();
401 closeCurrentCollection();
402 }
403
404
405 /** This is called when we're absolutely finished with the GLI. It is *not* called when the applet is suspended.
406 */
407 public void destroy()
408 {
409 // Destroying create pane ensures the latest log has been closed
410 if (create_pane != null) {
411 create_pane.destroy();
412 }
413
414 // Deal to help
415 if (help != null) {
416 help.destroy();
417 help = null;
418 }
419 }
420
421
422 /** Enabled events on the window to be trapped, creates all the visual components, then builds the tab and other layouts.
423 */
424 public void display() {
425 content_pane = (JPanel) this.getContentPane();
426 content_pane.setComponentOrientation(Dictionary.getOrientation());
427
428 // Enable window-type events to be fired.
429 enableEvents(AWTEvent.WINDOW_EVENT_MASK);
430 // Initialise and layout sub-components, plus other window dressing.
431 try {
432 this.setSize(size);
433
434 // Set the title
435 String collection_title = null;
436 String collection_name = null;
437 if (Gatherer.c_man.ready()) {
438 Collection collection = Gatherer.c_man.getCollection();
439 collection_title = collection.getTitle();
440 collection_name = collection.getGroupQualifiedName(true);
441 collection = null;
442 }
443 setTitle(collection_title, collection_name);
444 collection_title = null;
445 collection_name = null;
446
447 // Pretty corner icon
448 String gsmall_image = "gatherer.png";
449 if (Configuration.fedora_info.isActive()) {
450 gsmall_image = "fli-" + gsmall_image;
451 }
452 if(Gatherer.isGsdlRemote) {
453 gsmall_image = "client-" + gsmall_image;
454 }
455 this.setIconImage(JarTools.getImage(gsmall_image).getImage());
456 // BorderLayout for the main screen. I'll try my best to avoid these in subcomponents as they're space greedy.
457 content_pane.setLayout(new BorderLayout());
458 // Create the menu-bar and stick it up the top.
459 menu_bar = new MenuBar(new MenuListenerImpl());
460 menu_bar.setComponentOrientation(Dictionary.getOrientation());
461
462 //feedback changes
463 //content_pane.add(menu_bar, BorderLayout.NORTH);
464 this.setJMenuBar(menu_bar);
465 // end feedback changes
466
467 // Create the tabbed pane and plop it in the center where it will
468 // expand to consume all available space like any good gas would.
469 tab_pane = new JTabbedPane();
470 tab_pane.setComponentOrientation(Dictionary.getOrientation());
471 tab_pane.addChangeListener(this);
472 tab_pane.setFont(Configuration.getFont("general.font", false));
473
474 if (Configuration.get("workflow.download", true) && Gatherer.isDownloadEnabled) {
475 download_pane = new DownloadPane();
476 // "GUI.Download_Tooltip" is used automatically
477 tab_pane.addTab(Dictionary.get("GUI.Download"), JarTools.getImage("download.gif"), download_pane, Dictionary.get("GUI.Download_Tooltip"));
478 tab_pane.setEnabledAt(tab_pane.indexOfComponent(download_pane), Configuration.get("workflow.download", false));
479 }
480
481 gather_pane = new GatherPane();
482 gather_pane.display();
483 if (Configuration.get("workflow.gather", true)) {
484 // "GUI.Gather_Tooltip" is used automatically
485 tab_pane.addTab(Dictionary.get("GUI.Gather"), JarTools.getImage("gather.gif"), gather_pane, Dictionary.get("GUI.Gather_Tooltip"));
486 tab_pane.setEnabledAt(tab_pane.indexOfComponent(gather_pane), Configuration.get("workflow.gather", false));
487 }
488
489 enrich_pane = new EnrichPane();
490 enrich_pane.display();
491 if (Configuration.get("workflow.enrich", true)) {
492 // "GUI.Enrich_Tooltip" is used automatically
493 tab_pane.addTab(Dictionary.get("GUI.Enrich"), JarTools.getImage("enrich.gif"), enrich_pane, Dictionary.get("GUI.Enrich_Tooltip"));
494 tab_pane.setEnabledAt(tab_pane.indexOfComponent(enrich_pane), false);
495 }
496
497 design_pane = new DesignPane();
498 design_pane.display();
499 if (Configuration.get("workflow.design", true)) {
500 // "GUI.Design_Tooltip" is used automatically
501 if (Configuration.fedora_info.isActive()) {
502 tab_pane.addTab("Plugins", JarTools.getImage("design.gif"), design_pane, Dictionary.get("GUI.Design_Tooltip"));
503 }
504 else {
505 tab_pane.addTab(Dictionary.get("GUI.Design"), JarTools.getImage("design.gif"), design_pane, Dictionary.get("GUI.Design_Tooltip"));
506 }
507
508 tab_pane.setEnabledAt(tab_pane.indexOfComponent(design_pane), false);
509 }
510
511 create_pane = new CreatePane();
512 create_pane.setComponentOrientation(Dictionary.getOrientation());
513 create_pane.display();
514 if (Configuration.get("workflow.create", true)) {
515 // "GUI.Create_Tooltip" is used automatically
516 tab_pane.addTab(Dictionary.get("GUI.Create"), JarTools.getImage("create.gif"), create_pane, Dictionary.get("GUI.Create_Tooltip"));
517 tab_pane.setEnabledAt(tab_pane.indexOfComponent(create_pane), false);
518 }
519
520 format_pane = new FormatPane();
521 format_pane.setComponentOrientation(Dictionary.getOrientation());
522 format_pane.display();
523 if (Configuration.get("workflow.format", true)) {
524 tab_pane.addTab(Dictionary.get("GUI.Format"), JarTools.getImage("format.gif"), format_pane, Dictionary.get("GUI.Format_Tooltip"));
525 tab_pane.setEnabledAt(tab_pane.indexOfComponent(format_pane), false);
526 }
527
528 // The MetaAuditFrame must be created after the gather/enrich panes but before they get focus
529 meta_audit = new MetaAuditFrame();
530 meta_audit.setComponentOrientation(Dictionary.getOrientation());
531 // Select the collect pane if it is available
532 if (tab_pane.indexOfComponent(gather_pane) != -1) {
533 tab_pane.setSelectedComponent(gather_pane);
534 }
535 // Otherwise find the first tab that is enabled and select that.
536 else {
537 for (int i = 0; i < tab_pane.getTabCount(); i++) {
538 if (tab_pane.isEnabledAt(i)) {
539 tab_pane.setSelectedIndex(i);
540 break;
541 }
542 }
543 }
544
545 content_pane.add(tab_pane, BorderLayout.CENTER);
546
547 // Add an extra progress bar at the bottom of every screen when using a remote Greenstone server
548 if (Gatherer.isGsdlRemote) {
549 JPanel remote_greenstone_server_progress_panel = new JPanel();
550 //remote_greenstone_server_progress_panel.setComponentOrientation(Dictionary.getOrientation());
551 JLabel remote_greenstone_server_progress_label = new JLabel(Dictionary.get("RemoteGreenstoneServer.Progress"));
552 //remote_greenstone_server_progress_label.setComponentOrientation(Dictionary.getOrientation());
553 remote_greenstone_server_progress_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
554 remote_greenstone_server_progress_panel.setLayout(new BorderLayout());
555 remote_greenstone_server_progress_panel.add(remote_greenstone_server_progress_label, BorderLayout.LINE_START);
556 remote_greenstone_server_progress_panel.add(Gatherer.remoteGreenstoneServer.getProgressBar(), BorderLayout.CENTER);
557 content_pane.add(remote_greenstone_server_progress_panel, BorderLayout.SOUTH);
558 }
559
560 // Call refresh to update all controls to reflect current collection status.
561 refresh(-1, Gatherer.c_man.ready());
562 }
563 catch (Exception e) {
564 DebugStream.printStackTrace(e);
565 // The GUI failing to build is an app killer
566 e.printStackTrace();
567 System.exit(1);
568 }
569 }
570
571 public void exit()
572 {
573 exit(0);
574 }
575
576 // some cases we have already saved the collection, but don't want to
577 // override the general.open_collection value here
578 public void exitNoCollectionSave(int exit_status) {
579 // Store the current position and size of the GLI for next time
580 Configuration.setBounds("general.bounds", true, getBounds());
581
582 // Save configuration
583 Configuration.save();
584
585 // Hide the main window
586 setVisible(false);
587
588 // If we're running as an applet we don't quit here (we quit when the browser calls GathererApplet.destroy())
589 if (!Gatherer.isApplet) {
590 Gatherer.exit(exit_status);
591 }
592
593 }
594 /** This method ensures that all the things needing saving are saved before Gatherer.exit() is called.
595 */
596 public void exit(int exit_status)
597 {
598 boolean collection_open = false;
599 // If we have a collection open remember it for next time, then save it and close it
600 if (Gatherer.c_man.ready()) {
601 // but we no longer remember open collections for remote GLI, as this causes problems
602 // in applets when other users on a machine want to use an applet and GLI wants to load
603 // a collection left open from a previous session and *requires* the old user to authenticate
604 if(Gatherer.isGsdlRemote) {
605 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
606 true, "");
607 } else {
608 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
609 true, CollectionManager.getLoadedCollectionColFilePath());
610 }
611 saveThenCloseCurrentCollection();
612 collection_open = true;
613 }
614 else {
615 // if there was no open collection, then write out the collect dir path for next time
616 // IF this is not the default collect directory and not a remote GLI/applet
617 if(Gatherer.isGsdlRemote || Gatherer.getCollectDirectoryPath().equals(
618 Gatherer.getDefaultGSCollectDirectoryPath(true))) {
619 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
620 true, "");
621 } else {
622 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
623 true, Gatherer.getCollectDirectoryPath());
624 }
625 }
626
627
628 // Basically, if GLI coldir != gsdlsite_colhome, we ask them if they want to save GLI coldir as gsdlsite_colhome
629 // If gsdlsite_colhome = "" (meaning default GS coldir) and GLI is also set to defaultGScoldir, no saving necessary.
630 // We ONLY do this for the local included apache web server, since the issue revolves around gsdlsite.cfg containing
631 // the global collecthome when using the apache web server. This is not an issue for remote GS or server.exe (the latter
632 // has separate config files specifying collecthome for when GLI is running whereas when just the server.exe is running).
633 if(!Gatherer.isGsdlRemote && !Gatherer.isPersistentServer()) {
634
635 String defaultColDir = Gatherer.getDefaultGSCollectDirectoryPath(false); // no filesep at end
636 String gliColDir = Gatherer.getCollectDirectoryPath();
637 String serverColDir = Gatherer.gsdlsite_collecthome;
638
639 boolean showSettingsDlg = true;
640 // if collectdir was changed during GLI session (to something different from what's in gsdlsite), need to ask what to store
641 String gsdlsiteColdir = Gatherer.gsdlsite_collecthome.replace("\"", "");
642 if(gliColDir.equals(gsdlsiteColdir+File.separator)) {
643 showSettingsDlg = false;
644 } else if(gsdlsiteColdir.equals("") // both set to default coldir
645 && gliColDir.equals(defaultColDir+File.separator)) {
646 showSettingsDlg = false;
647 }
648 if(showSettingsDlg) {
649
650 // else we will be showing the Collect Directory Settings Dialog
651 if(gliColDir.endsWith(File.separator)) {
652 gliColDir = gliColDir.substring(0, gliColDir.length()-1);
653 }
654
655 if(serverColDir.equals("")) {
656 serverColDir = defaultColDir;
657 }
658 collectDirSettingsDialog(defaultColDir, serverColDir, gliColDir, collection_open);
659 }
660 }
661
662 // Store the current position and size of the GLI for next time
663 Configuration.setBounds("general.bounds", true, getBounds());
664
665 // Save configuration
666 Configuration.save();
667
668 // Hide the main window
669 setVisible(false);
670
671 // If we're running as an applet we don't quit here (we quit when the browser calls GathererApplet.destroy())
672 if (!Gatherer.isApplet) {
673 Gatherer.exit(exit_status);
674 }
675 }
676
677 public void collectDirSettingsDialog(final String defaultColDir,
678 final String from, final String to, final boolean collection_open)
679 {
680 final JDialog colHomeDialog
681 = new JDialog(this, Dictionary.get("GUI.CollectHome.title"), true); // this = Gatherer.g_man
682 colHomeDialog.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
683
684
685 JRadioButton gliYes = new JRadioButton(Dictionary.get("General.Yes"), true);
686 // the default selection for GLI, collecthome=to
687 JRadioButton serverYes = new JRadioButton(Dictionary.get("General.Yes")); // not selected for the server
688 JRadioButton gliNo = null;
689 JRadioButton gliThirdOption = null;
690 JRadioButton serverNo = null;
691 JRadioButton serverThirdOption = null;
692
693 if(from.equals(defaultColDir)) {
694 gliNo = new JRadioButton(Dictionary.get("GUI.CollectHome.resetToDefault"));
695 serverNo = new JRadioButton(Dictionary.get("GUI.CollectHome.leaveAtDefault"), true);
696 // default selection for server, collecthome=from
697 } else {
698 gliNo = new JRadioButton(Dictionary.get("General.No"));
699 serverNo = new JRadioButton(Dictionary.get("General.No"), true); // default selection for server
700 if(!to.equals(defaultColDir)) { // neither from nor to is the default GS collect dir, so give them that as the third option
701 gliThirdOption = new JRadioButton(Dictionary.get("GUI.CollectHome.reset"));
702 serverThirdOption = new JRadioButton(Dictionary.get("GUI.CollectHome.reset"));
703 }
704 }
705
706 JPanel gliPanel = new JPanel(); // flowlayout by default
707 ButtonGroup gliGroup = new ButtonGroup();
708 JPanel serverPanel = new JPanel(); // flowlayout by default
709 ButtonGroup serverGroup = new ButtonGroup();
710
711 gliGroup.add(gliYes);
712 gliPanel.add(gliYes);
713 serverGroup.add(serverYes);
714 serverPanel.add(serverYes);
715
716 gliGroup.add(gliNo);
717 gliPanel.add(gliNo);
718 serverGroup.add(serverNo);
719 serverPanel.add(serverNo);
720
721 if(gliThirdOption != null) {
722 gliThirdOption = new JRadioButton("Reset to default");
723 serverThirdOption = new JRadioButton("Reset to default");
724
725 gliGroup.add(gliThirdOption);
726 gliPanel.add(gliThirdOption);
727 serverGroup.add(serverThirdOption);
728 serverPanel.add(serverThirdOption);
729 }
730
731 // vars need to be final to use them in the actionlistener below
732 final JRadioButton gli_yes = gliYes;
733 final JRadioButton gli_no = gliNo;
734 final JRadioButton gli_optional = gliThirdOption;
735 final JRadioButton server_yes = serverYes;
736 final JRadioButton server_no = serverNo;
737 final JRadioButton server_optional = serverThirdOption;
738
739 JButton okButton = new JButton(Dictionary.get("General.OK"));
740 okButton.addActionListener(new ActionListener() {
741 public void actionPerformed(ActionEvent e) {
742 // store the option chosen for GLI
743 String gliColDir = to;
744 if(gli_optional != null && gli_optional.isSelected()) {
745 // defaultColDir
746 gliColDir = "";
747 } else if(gli_yes.isSelected()) {
748 gliColDir = to;
749 } else if (gli_no.isSelected()) {
750 gliColDir = from;
751 }
752 if(defaultColDir.equals(gliColDir)) {
753 gliColDir = "";
754 }
755 if(!(collection_open && gli_yes.isSelected())) { // don't overwrite open collections
756 Configuration.setString(
757 "general.open_collection"+Configuration.gliPropertyNameSuffix(),
758 true, gliColDir);
759 }
760
761 // store the option chosen for the server's settings
762 String serverColDir = from;
763 if(server_optional != null && server_optional.isSelected()) {
764 // defaultColDir
765 serverColDir = null;
766 } else if(server_yes.isSelected()) {
767 serverColDir = to;
768 } else if (server_no.isSelected()) {
769 serverColDir = from;
770 }
771 if(serverColDir != null && defaultColDir.equals(serverColDir)) {
772 serverColDir = null;
773 }
774
775 if(serverColDir != null) {
776 serverColDir = serverColDir.replace("\"","");
777 serverColDir = "\""+serverColDir+"\"";
778 }
779
780 Gatherer.gsdlsite_collecthome = Utility.updatePropertyConfigFile(
781 Gatherer.getGsdlSiteConfigFile(), "collecthome", serverColDir);
782
783 colHomeDialog.dispose();
784 }
785 });
786
787 //String[] dirs = {from, to};
788 //JLabel message = new JLabel(Dictionary.get("GUI.CollectHome.message", dirs));
789 JLabel message = new JLabel(Dictionary.get("GUI.CollectHome.message"));
790 JLabel fromDirLine = new JLabel(Dictionary.get("GUI.CollectHome.dir", from));
791 fromDirLine.setBorder(BorderFactory.createEmptyBorder(0,25,0,0)); // padding
792 JLabel toLine = new JLabel(Dictionary.get("GUI.CollectHome.to"));
793 JLabel toDirLine = new JLabel(Dictionary.get("GUI.CollectHome.dir", to));
794 toDirLine.setBorder(BorderFactory.createEmptyBorder(0,25,0,0)); // padding
795 JLabel gliOption = new JLabel(Dictionary.get("GUI.CollectHome.gli"));
796 JLabel serverOption = new JLabel(Dictionary.get("GUI.CollectHome.server"));
797
798 JPanel mainPanel = new JPanel();
799 mainPanel.setLayout(new GridLayout(9, 1));
800 mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); // padding
801 mainPanel.add(message);
802 mainPanel.add(fromDirLine);
803 mainPanel.add(toLine);
804 mainPanel.add(toDirLine);
805 mainPanel.add(gliOption);
806 mainPanel.add(gliPanel);
807 mainPanel.add(serverOption);
808 mainPanel.add(serverPanel);
809 mainPanel.add(okButton);
810 Container c = colHomeDialog.getContentPane();
811 c.setLayout(new BorderLayout());
812 c.add(mainPanel, BorderLayout.CENTER);
813 colHomeDialog.getRootPane().setDefaultButton(okButton);
814
815 colHomeDialog.pack();
816 colHomeDialog.setVisible(true);
817 }
818
819
820 /** This method is called when the collection is being built, and is used to disable all controls in all pane which could change the state of the collection.
821 */
822 public void lockCollection(boolean import_stage, boolean lock)
823 {
824 locked = lock;
825
826 if (import_stage) {
827 int gather_pos = tab_pane.indexOfComponent(gather_pane);
828 if (gather_pos != -1) {
829 tab_pane.setEnabledAt(gather_pos, !lock);
830 }
831 int enrich_pos = tab_pane.indexOfComponent(enrich_pane);
832 if (enrich_pos != -1) {
833 tab_pane.setEnabledAt(enrich_pos, !lock);
834 }
835 }
836
837 int design_pos = tab_pane.indexOfComponent(design_pane);
838 if (design_pos != -1) {
839 tab_pane.setEnabledAt(design_pos, !lock);
840 }
841 }
842
843
844 public void modeChanged(int mode) {
845 // Set the title
846 String collection_title = null;
847 String collection_name = null;
848 if (Gatherer.c_man.ready()) {
849 Collection collection = Gatherer.c_man.getCollection();
850 collection_title = collection.getTitle();
851 collection_name = collection.getGroupQualifiedName(true);
852 collection = null;
853 }
854 setTitle(collection_title, collection_name);
855 collection_title = null;
856 collection_name = null;
857 // Now pass on the message to anyone who cares
858 if (download_pane != null) {
859 download_pane.modeChanged(mode);
860 }
861 if (gather_pane != null) {
862 gather_pane.modeChanged(mode);
863 }
864 if (enrich_pane != null) {
865 enrich_pane.modeChanged(mode);
866 }
867 if (design_pane != null) {
868 design_pane.modeChanged(mode);
869 }
870 if (create_pane != null) {
871 create_pane.modeChanged(mode);
872 }
873 if (format_pane != null) {
874 format_pane.modeChanged(mode);
875 }
876 }
877
878
879 public void refresh(int refresh_reason, boolean collection_loaded)
880 {
881 // Set the collection information in the title bar
882 if (collection_loaded) {
883 Collection collection = Gatherer.c_man.getCollection();
884 setTitle(collection.getTitle(), collection.getGroupQualifiedName(true));
885 }
886 else {
887 setTitle(null, null);
888 }
889
890 // Update the menu bar
891 menu_bar.refresh(refresh_reason, collection_loaded);
892
893 // Update the loaded panes
894 if (download_pane != null) {
895 download_pane.refresh(refresh_reason, collection_loaded);
896 }
897 if (gather_pane != null) {
898 gather_pane.refresh(refresh_reason, collection_loaded);
899 }
900 if (enrich_pane != null) {
901 enrich_pane.refresh(refresh_reason, collection_loaded);
902 }
903 if (design_pane != null) {
904 design_pane.refresh(refresh_reason, collection_loaded);
905 }
906 if (create_pane != null) {
907 create_pane.refresh(refresh_reason, collection_loaded);
908 }
909 if (format_pane != null) {
910 format_pane.refresh(refresh_reason, collection_loaded);
911 }
912
913 // Now enable tabs as necessary. Do this on event queue to prevent crazy NPEs
914 if (!locked) {
915 if (tab_updater == null) {
916 tab_updater = new TabUpdater(tab_pane, collection_loaded);
917 }
918 else {
919 tab_updater.setReady(collection_loaded);
920 }
921 SwingUtilities.invokeLater(tab_updater);
922 }
923 }
924
925
926 public void refreshCollectionTree(int refresh_reason)
927 {
928 if (gather_pane != null) {
929 gather_pane.refreshCollectionTree(refresh_reason);
930 }
931 }
932
933
934 public void refreshWorkspaceTree(int refresh_reason)
935 {
936 if (gather_pane != null) {
937 gather_pane.refreshWorkspaceTree(refresh_reason);
938 }
939 }
940
941 public void refreshWorkspaceTreeGreenstoneCollections()
942 {
943 refreshWorkspaceTree(WorkspaceTree.LIBRARY_CONTENTS_CHANGED);
944 }
945
946 /** Specifies whether a certain tab is enabled or not. */
947 private void setTabEnabled(String rawname, boolean state) {
948 // Retrieve the dictionary based name.
949 String name = Dictionary.get("GUI." + rawname);
950 int index = tab_pane.indexOfTab(name);
951 // Of course we may not have this tab available.
952 if(index != -1) {
953 // Some tabs are also dependant on if a collection is ready
954 Component component = tab_pane.getComponentAt(index);
955 if(component == enrich_pane || component == design_pane || component == create_pane || component == format_pane) {
956 tab_pane.setEnabledAt(index, state && Gatherer.c_man != null && Gatherer.c_man.ready());
957 }
958 else {
959 tab_pane.setEnabledAt(index, state);
960 }
961 // If this was the currently selected tab and it is now disabled, change the view to the first enabled tab.
962 if(tab_pane.getSelectedIndex() == index && !state) {
963 boolean found = false;
964 for(int i = 0; !found && i < tab_pane.getTabCount(); i++) {
965 if(tab_pane.isEnabledAt(i)) {
966 tab_pane.setSelectedIndex(i);
967 found = true;
968 }
969 }
970 // If there are no tabs enabled, which should be impossible, then select the first tab
971 if(!found) {
972 tab_pane.setSelectedIndex(0);
973 }
974 }
975 }
976 }
977
978 /** Change the string shown in the title bar of the main gui frame. If either value is null, the 'No Collection' string is shown instead.
979 * @param title
980 * @param name
981 */
982 public void setTitle(String title, String name) {
983
984 // Finally display the collection name in the title bar.
985 StringBuffer title_buffer = new StringBuffer(Configuration.getApplicationTitle());
986 title_buffer.append(StaticStrings.SPACE_CHARACTER);
987 title_buffer.append(Gatherer.PROGRAM_VERSION);
988 title_buffer.append(StaticStrings.SPACE_CHARACTER);
989 title_buffer.append(StaticStrings.SPACE_CHARACTER);
990 // Server version information
991 title_buffer.append(Gatherer.getServerVersionAsString());
992 title_buffer.append(StaticStrings.SPACE_CHARACTER);
993 title_buffer.append(StaticStrings.SPACE_CHARACTER);
994 // Describe the current user mode
995 title_buffer.append(StaticStrings.MODE_STR);
996 title_buffer.append(Configuration.getModeAsString());
997 title_buffer.append(StaticStrings.SPACE_CHARACTER);
998 title_buffer.append(StaticStrings.SPACE_CHARACTER);
999 // Now for the current collection
1000 title_buffer.append(StaticStrings.COLLECTION_STR);
1001 if (title != null && name != null) {
1002 title_buffer.append(title);
1003 title_buffer.append(StaticStrings.SPACE_CHARACTER);
1004 title_buffer.append(StaticStrings.OPEN_PARENTHESIS_CHARACTER);
1005 title_buffer.append(name);
1006 title_buffer.append(StaticStrings.CLOSE_PARENTHESIS_CHARACTER);
1007 }
1008 else {
1009 title_buffer.append(Dictionary.get("Collection.No_Collection"));
1010 }
1011 this.setTitle(title_buffer.toString());
1012 title_buffer = null;
1013 }
1014
1015
1016 private class OpenCollectionTask
1017 implements Runnable //extends Thread -> If this extends Thread, it will cause an EDT access
1018 // violation since the GUI stuff in run() is not done in the Swing Event Dispatch Thread/EDT.
1019 {
1020 public void run()
1021 {
1022 String collection_file_path = showOpenCollectionDialog();
1023
1024 // User has selected a collection to open
1025 if (collection_file_path != null) {
1026 // If there is already a collection open, save and close it
1027 if (Gatherer.c_man.ready()) {
1028 saveThenCloseCurrentCollection();
1029 }
1030
1031 // Open the selected collection
1032 Gatherer.c_man.loadCollection(collection_file_path);
1033 }
1034 }
1035 }
1036
1037
1038 /** When the load collection option is chosen this method is called to produce the modal file load prompt.
1039 */
1040 private String showOpenCollectionDialog()
1041 {
1042 OpenCollectionDialog dialog = new OpenCollectionDialog();
1043 TestingPreparation.setNamesRecursively(dialog);
1044
1045 dialog.setComponentOrientation(Dictionary.getOrientation());
1046 if (dialog.display() == OpenCollectionDialog.OK_OPTION) {
1047 return dialog.getFileName();
1048 }
1049
1050 // User must have cancelled the action
1051 return null;
1052 }
1053
1054
1055 /** When called this method causes the MetadataAuditTable to display a nice dialog box which contains all the metadata assigned in the collection.
1056 */
1057 public void showMetaAuditBox() {
1058 wait(true);
1059 meta_audit.display();
1060 wait(false);
1061 }
1062
1063
1064 private class NewCollectionTask
1065 implements Runnable //extends Thread
1066 {
1067 public void run()
1068 {
1069 // Create the collection details prompt from new collection prompt
1070 NewCollectionDetailsPrompt ncd_prompt = new NewCollectionDetailsPrompt();
1071 //TestingPreparation.setNamesRecursively(ncd_prompt);
1072 // 1. names have to be set in NewCollectionDetailsPrompt, as it makes itself visible
1073 // and for testing we have to have run setName() on its components before the dialog goes visible
1074 // 2. For whatever reason, the NewCollectionDetailsPrompt dialog's own name is set
1075 // to "col" and it's not possible to change it at any point before or after
1076 // creating the dialog, and whether from inside or outside the dialog's own class
1077
1078 // Create the new collection (if not cancelled) in a new thread.
1079 if (!ncd_prompt.isCancelled()) {
1080 // If there is already a collection open, save and close it.
1081 if (Gatherer.c_man.ready()) {
1082 saveThenCloseCurrentCollection();
1083 }
1084
1085 // Create new collection.
1086 Gatherer.c_man.createCollection(ncd_prompt.getDescription(), Configuration.getEmail(), ncd_prompt.getName(), ncd_prompt.getTitle(), ncd_prompt.getBase(), new ArrayList());
1087 ncd_prompt.dispose();
1088 }
1089
1090 // Done
1091 ncd_prompt = null;
1092 }
1093 }
1094
1095
1096 private class DeleteCollectionTask
1097 implements Runnable //extends Thread
1098 {
1099 public void run()
1100 {
1101 // The rest is handled by the DeleteCollectionPrompt
1102 DeleteCollectionPrompt dc_prompt = new DeleteCollectionPrompt();
1103 TestingPreparation.setNamesRecursively(dc_prompt);
1104 if (dc_prompt.display()) {
1105 //closeCurrentCollection();
1106 }
1107 dc_prompt.destroy();
1108 dc_prompt = null;
1109 }
1110 }
1111
1112 // Want to triger loseFocus() on GLI Panes at will when Menu > Edit > collectionConfig.xml clicked.
1113 // And when done editing, want to trigger doRegainFocs().
1114 // loseFocus() on GLI Panes is not universally inherited from a common base class
1115 // But loseFocus() is important as it forces saves as-is of user entered values in gui fields
1116 // When alling doLoseFocus() on GLI > Edit > collConfig.xml, we force a save of the current state
1117 // of the current pane (called "previous_pane").
1118 // Else a save is only triggered when another GLI Pane is clicked. We can't expect a user to
1119 // remember to click other panes whenever they want to edit the collConfig.xml.
1120 private void doLoseFocus() {
1121 if (previous_pane != null) {
1122 if (previous_pane == gather_pane) {
1123 gather_pane.loseFocus();
1124 }
1125 else if (previous_pane == enrich_pane) {
1126 enrich_pane.loseFocus();
1127 }
1128 else if (previous_pane == design_pane) {
1129 design_pane.loseFocus();
1130 }
1131 else if (previous_pane == create_pane) {
1132 create_pane.loseFocus();
1133 }
1134 else if (previous_pane == format_pane) {
1135 format_pane.loseFocus();
1136 }
1137 }
1138 }
1139 public void doRegainFocus() {
1140 if (previous_pane != null) {
1141 if (previous_pane == gather_pane) {
1142 gather_pane.gainFocus();
1143 }
1144 else if (previous_pane == enrich_pane) {
1145 enrich_pane.gainFocus();
1146 }
1147 else if (previous_pane == design_pane) {
1148 design_pane.gainFocus();
1149 }
1150 else if (previous_pane == create_pane) {
1151 create_pane.gainFocus();
1152 }
1153 else if (previous_pane == format_pane) {
1154 format_pane.gainFocus();
1155 }
1156 }
1157 }
1158
1159 /** Any implementation of ChangeListener must include this method so we can be informed when the state of one of the registered objects changes. In this case we are listening to view changes within the tabbed pane.
1160 * @param event A ChangeEvent containing information about the event that fired this call.
1161 */
1162 public void stateChanged(ChangeEvent event)
1163 {
1164 if (previous_pane != null) {
1165 if (previous_pane == gather_pane) {
1166 gather_pane.loseFocus();
1167 }
1168 else if (previous_pane == enrich_pane) {
1169 enrich_pane.loseFocus();
1170 }
1171 else if (previous_pane == design_pane) {
1172 design_pane.loseFocus();
1173 }
1174 else if (previous_pane == create_pane) {
1175 create_pane.loseFocus();
1176 }
1177 else if (previous_pane == format_pane) {
1178 format_pane.loseFocus();
1179 }
1180 }
1181
1182 menu_bar.tabSelected(tab_pane.getSelectedIndex());
1183 int selected_index = tab_pane.getSelectedIndex();
1184 if (selected_index == tab_pane.indexOfComponent(download_pane)) {
1185 download_pane.gainFocus();
1186 }
1187 else if (selected_index == tab_pane.indexOfComponent(gather_pane)) {
1188 gather_pane.gainFocus();
1189 }
1190 else if (selected_index == tab_pane.indexOfComponent(enrich_pane)) {
1191 enrich_pane.gainFocus();
1192 }
1193 else if (selected_index == tab_pane.indexOfComponent(design_pane)) {
1194 design_pane.gainFocus();
1195 }
1196 else if (selected_index == tab_pane.indexOfComponent(create_pane)) {
1197 create_pane.gainFocus();
1198 }
1199 else if (selected_index == tab_pane.indexOfComponent(format_pane)) {
1200 format_pane.gainFocus();
1201 }
1202
1203 previous_pane = (JPanel) tab_pane.getSelectedComponent();
1204
1205 }
1206
1207
1208 private MouseListener mouse_blocker_listener = new MouseAdapter() {};
1209
1210 public void updateUI()
1211 {
1212 SwingUtilities.invokeLater(new Runnable() {
1213 public void run() {
1214 JPanel pane = (JPanel) getContentPane();
1215 pane.updateUI();
1216 // Also update all of the tabs according to workflow.
1217 workflowUpdate("Download", Configuration.get("workflow.download", false));
1218 workflowUpdate("Gather", Configuration.get("workflow.gather", false));
1219 workflowUpdate("Enrich", Configuration.get("workflow.enrich", false));
1220 workflowUpdate("Design", Configuration.get("workflow.design", false));
1221 workflowUpdate("Create", Configuration.get("workflow.create", false));
1222 workflowUpdate("Format", Configuration.get("workflow.format", false));
1223 }
1224 });
1225 }
1226
1227 public void wait(boolean waiting) {
1228 Component glass_pane = getGlassPane();
1229 if(waiting) {
1230 // Show wait cursor.
1231 glass_pane.addMouseListener(mouse_blocker_listener);
1232 glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1233 glass_pane.setVisible(true);
1234 }
1235 else {
1236 // Hide wait cursor.
1237 glass_pane.setVisible(false);
1238 glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1239 glass_pane.removeMouseListener(mouse_blocker_listener);
1240 }
1241 glass_pane = null;
1242 }
1243
1244 public void workflowUpdate(String raw, boolean state) {
1245 WorkflowUpdater task = new WorkflowUpdater(raw, state);
1246 SwingUtilities.invokeLater(task);
1247 task = null;
1248 }
1249
1250
1251 /**Overridden from JFrame so we can exit safely when window is closed (or destroyed).
1252 * @param event A <strong>WindowEvent</strong> containing information about the event that fired this call.
1253 */
1254 protected void processWindowEvent(WindowEvent event) {
1255 if(event.getID() == WindowEvent.WINDOW_CLOSING) {
1256 exit();
1257 }
1258 }
1259
1260
1261 /** Listens to actions upon the menu bar, and if it detects a click over the help menu brings the help window to the front if it has become hidden.
1262 */
1263 private class MenuListenerImpl
1264 implements MenuListener {
1265 /** Called whenever a popup menu is hidden, but we don't care.
1266 * @param e Some <strong>MenuEvent</strong> that we could care less about.
1267 */
1268 public void menuCanceled(MenuEvent e) {
1269 }
1270 /** Called whenever a menu header (ie button) becomes unselected, but we don't care.
1271 * @param e Some <strong>MenuEvent</strong> that we could care less about.
1272 */
1273 public void menuDeselected(MenuEvent e) {
1274 }
1275 /** This method, when a menu is first opened, is the only one we respond to by bringing the help window to the front if possible, but only if there is a help window and the help menu is the one opening.
1276 * @param e The <strong>MenuEvent</strong> whose source is checked.
1277 */
1278 public void menuSelected(MenuEvent e) {
1279 if(e.getSource() == menu_bar.help) {
1280 if(menu_bar.help.isSelected()) {
1281 menu_bar.help.doClick(10);
1282 }
1283 }
1284 else if(e.getSource() == menu_bar.edit) { // someone clicked the toplevel Edit menu
1285 // gray out the Edit Config File menu if there's no collection currently open.
1286 if(Gatherer.c_man.getCollection() == null) {
1287 menu_bar.edit_config.setEnabled(false);
1288 }
1289 else { // don't forget to reenable the Edit ConfigXML menu item when applicable
1290 menu_bar.edit_config.setEnabled(true);
1291 }
1292 }
1293
1294 }
1295 }
1296
1297 private class TabUpdater
1298 implements Runnable {
1299 private boolean ready = false;
1300 private int download_pos = -1;
1301 private int enrich_pos = -1;
1302 private int design_pos = -1;
1303 private int create_pos = -1;
1304 private int format_pos = -1;
1305 private int export_pos = -1;
1306 private JTabbedPane tab_pane = null;
1307
1308 public TabUpdater(JTabbedPane tab_pane, boolean ready) {
1309 this.ready = ready;
1310 this.tab_pane = tab_pane;
1311 download_pos = tab_pane.indexOfComponent(download_pane);
1312 enrich_pos = tab_pane.indexOfComponent(enrich_pane);
1313 design_pos = tab_pane.indexOfComponent(design_pane);
1314 create_pos = tab_pane.indexOfComponent(create_pane);
1315 format_pos = tab_pane.indexOfComponent(format_pane);
1316 }
1317
1318 public void run()
1319 {
1320 if (download_pos != -1) {
1321 if (ready) {
1322 tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", false));
1323 }
1324 else {
1325 tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", true));
1326 }
1327 }
1328 if (enrich_pos != -1) {
1329 tab_pane.setEnabledAt(enrich_pos, ready && Configuration.get("workflow.enrich", false));
1330 }
1331 if (design_pos != -1) {
1332 tab_pane.setEnabledAt(design_pos, ready && Configuration.get("workflow.design", false) && Configuration.getMode() > Configuration.ASSISTANT_MODE);
1333 }
1334 if (create_pos != -1) {
1335 tab_pane.setEnabledAt(create_pos, ready && Configuration.get("workflow.create", false));
1336 }
1337 if (format_pos != -1) {
1338 tab_pane.setEnabledAt(format_pos, ready && Configuration.get("workflow.format", false) && Configuration.getMode() > Configuration.ASSISTANT_MODE);
1339 }
1340 }
1341
1342 public void setReady(boolean ready) {
1343 this.ready = ready;
1344 }
1345 }
1346
1347 private class WorkflowUpdater
1348 implements Runnable {
1349 private boolean state;
1350 private String raw;
1351 public WorkflowUpdater(String raw, boolean state) {
1352 this.raw = raw;
1353 this.state = state;
1354 }
1355 public void run() {
1356 setTabEnabled(raw, state);
1357 }
1358 }
1359}
Note: See TracBrowser for help on using the repository browser.