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

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

In the previous commit 1. Codec.java change was still related to commit 34241. 2. Fixed my own silly bug: it's windowClosed not windowClose. Because the real method was not overridden, it never got called when the configFileEditor was closed, as a result of which the GLI's GUI interface wasn't getting immediately repainted. 3. Fixed a bug in FileNode.java (nullpointer exception case). 4. Accidentally committed experimental work to export metadata from GLI to csv. This commit undoes the experimental stuff, only some of which is promising and still needs work.

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