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

Last change on this file since 12805 was 12805, checked in by mdewsnip, 18 years ago

All instances of saving the collection now go through CollectionManager.saveCollection().

  • Property svn:keywords set to Author Date Id Revision
File size: 33.1 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.MetadataSet;
62import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
63import org.greenstone.gatherer.util.JarTools;
64import org.greenstone.gatherer.util.StaticStrings;
65import org.greenstone.gatherer.util.Utility;
66
67/** 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. */
68public class GUIManager
69 extends JFrame
70 implements ActionListener, ChangeListener, WindowFocusListener{
71 /** The download pane contains controls for downloading internet sites. */
72 public DownloadPane download_pane = null;
73 /** The gather pane is more like a file manager where you drag files from one tree to another. */
74 public GatherPane gather_pane = null;
75 /** The enrich pane is used to assign, edit and remove metadata from files within the collection. */
76 public EnrichPane enrich_pane = null;
77 /** The design pane allows you to edit the design of the library in terms of the collection configuration file. - the stuff that requires rebuilding */
78 public DesignPane design_pane = null;
79 /** The create pane contains scripting options for importing and building collections into libraries. */
80 public CreatePane create_pane = null;
81 /** 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 */
82 public FormatPane format_pane = null;
83
84 public FileOpenActionListener foa_listener = new FileOpenActionListener();
85
86
87 /** A reference to the currently instantiated help window, if any. */
88 private HelpFrame help = null;
89 /** The menu bar. */
90 public MenuBar menu_bar = null;
91 public MetaAuditFrame meta_audit;
92 /** Are certain panes currently locked? */
93 private boolean locked = false;
94 /** The size of the Gatherer window. */
95 private Dimension size = null;
96 /** The panel within the window that other components are placed on. */
97 private JPanel content_pane = null;
98 /** The last view pane selected. */
99 private JPanel previous_pane;
100 /** The main tab pane containing the different views, available here to trap view change events. */
101 private JTabbedPane tab_pane = null;
102 /** A threaded tab changer to try and avoid NPE on exit. */
103 private TabUpdater tab_updater = null;
104
105
106
107
108
109 final static String newline = "\n";
110 final static String space = " ";
111
112
113 /**Constructor. Enable window events and arranges all other components.
114 * @param size The intial <strong>Dimension</strong> of the screen.
115 */
116 public GUIManager(Dimension size) {
117 super();
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
138
139 public void windowGainedFocus(WindowEvent e)
140 {
141 }
142
143
144 public void windowLostFocus(WindowEvent e)
145 {
146 // Save the loaded collection
147 if (Gatherer.c_man != null && Gatherer.c_man.ready() && Gatherer.c_man.getCollection().cdm != null) {
148 Gatherer.c_man.saveCollection();
149 }
150 }
151
152
153 private class GLIGUIFocusListener
154 extends FocusAdapter {
155 public void focusGained(FocusEvent e) {
156 if (ModalDialog.current_modal != null) {
157 ModalDialog.current_modal.makeVisible();
158 ModalDialog.current_modal.toFront();
159 }
160 }
161 }
162
163 /** 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.
164 * @param event An <strong>ActionEvent</strong> containing information about the action that has occured.
165 */
166 public void actionPerformed(ActionEvent event) {
167 Object esrc = event.getSource();
168 // *************
169 // File Options.
170 // *************
171 if (esrc == menu_bar.file_associations) {
172 Gatherer.assoc_man.edit();
173 }
174 else if (esrc == menu_bar.file_close) {
175 saveThenCloseCurrentCollection();
176 }
177 else if (esrc == menu_bar.file_delete) {
178 DeleteCollectionPrompt dcp = new DeleteCollectionPrompt();
179 if (dcp.display()) {
180 saveThenCloseCurrentCollection();
181 }
182 dcp.destroy();
183 dcp = null;
184 System.gc();
185 }
186 else if (esrc == menu_bar.file_cdimage) {
187 WriteCDImagePrompt wcdip = new WriteCDImagePrompt();
188 wcdip.display();
189 wcdip.destroy();
190 wcdip = null;
191 }
192 else if (esrc == menu_bar.file_exportas) {
193 ExportAsPrompt eap = new ExportAsPrompt();
194 eap.display();
195 eap.destroy();
196 eap = null;
197 }
198 else if (esrc == menu_bar.file_exit) {
199 exit();
200 }
201 else if (esrc == menu_bar.file_new) {
202 new NewCollectionTask().start();
203 }
204 else if (esrc == menu_bar.file_open) {
205 new OpenCollectionTask().start();
206 }
207 else if (esrc == menu_bar.file_options) {
208 // Just incase the user has edited the GeneralSettings of a collection without losing focus afterwards. Well I'm forever losing foc... ooh shiney.
209 design_pane.loseFocus();
210 // And spawn a new preferences.
211 new Preferences();
212 }
213 else if (esrc == menu_bar.file_save) {
214 Gatherer.c_man.saveCollection();
215 }
216
217 // *************
218 // Edit Options.
219 // *************
220 else if(esrc == menu_bar.edit_copy) {
221 try {
222 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
223 // Get the component with selected text as a JTextComponent
224 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();//getFocusOwner();
225 text.copy();
226 }
227 catch (Exception cce) {
228 // If the component is not a text component ignore the copy command
229 DebugStream.println(cce.toString());
230 }
231 }
232 else if(esrc == menu_bar.edit_cut) {
233 try {
234 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
235 // Get the component with selected text as a JTextComponent
236 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
237 // Cut the text to the clipboard
238 text.cut();
239 }
240 catch (ClassCastException cce) {
241 // If the component is not a text component ignore the cut command
242 DebugStream.println(cce.toString());
243 }
244 }
245 else if(esrc == menu_bar.edit_paste) {
246 try {
247 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
248 // Get the component with selected text as a JTextComponent
249 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
250 // Cut the text to the clipboard
251 text.paste();
252 }
253 catch (ClassCastException cce) {
254 // If the component is not a text component ignore the paste command
255 DebugStream.println(cce.toString());
256 }
257 }
258
259 // *************
260 // Help Options.
261 // *************
262 else if (esrc == menu_bar.help_general) {
263 HelpFrame.setView("introduction");
264 }
265 else if (esrc == menu_bar.help_download) {
266 HelpFrame.setView("downloadingfiles");
267 }
268 else if (esrc == menu_bar.help_gather) {
269 HelpFrame.setView("collectingfiles");
270 }
271 else if (esrc == menu_bar.help_enrich) {
272 HelpFrame.setView("enrichingacollection");
273 }
274 else if (esrc == menu_bar.help_design) {
275 HelpFrame.setView("designingacollection");
276 }
277 else if (esrc == menu_bar.help_create) {
278 HelpFrame.setView("producingthecollection");
279 }
280 else if (esrc == menu_bar.help_format) {
281 HelpFrame.setView("formattingacollection");
282 }
283 else if (esrc == menu_bar.help_about) {
284 new AboutDialog(this);
285 }
286 }
287
288
289 /** 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.
290 */
291 public void afterDisplay() {
292 if (download_pane != null) {
293 download_pane.afterDisplay();
294 }
295 enrich_pane.afterDisplay();
296 }
297
298
299 public void saveThenCloseCurrentCollection()
300 {
301 tab_pane.setSelectedComponent(gather_pane);
302 Gatherer.c_man.saveCollection();
303 Gatherer.c_man.closeCollection();
304 }
305
306
307 /** This is called when we're absolutely finished with the GLI. It is *not* called when the applet is suspended.
308 */
309 public void destroy()
310 {
311 // Destroying create pane ensures the latest log has been closed
312 if (create_pane != null) {
313 create_pane.destroy();
314 }
315
316 // Deal to help
317 if (help != null) {
318 help.destroy();
319 help = null;
320 }
321 }
322
323
324 /** Enabled events on the window to be trapped, creates all the visual components, then builds the tab and other layouts.
325 */
326 public void display() {
327 content_pane = (JPanel) this.getContentPane();
328 // Enable window-type events to be fired.
329 enableEvents(AWTEvent.WINDOW_EVENT_MASK);
330 // Initialise and layout sub-components, plus other window dressing.
331 try {
332 this.setSize(size);
333
334 // Set the title
335 String collection_title = null;
336 String collection_name = null;
337 if (Gatherer.c_man.ready()) {
338 Collection collection = Gatherer.c_man.getCollection();
339 collection_title = collection.getTitle();
340 collection_name = collection.getName();
341 collection = null;
342 }
343 setTitle(collection_title, collection_name);
344 collection_title = null;
345 collection_name = null;
346
347 // Pretty corner icon
348 this.setIconImage(JarTools.getImage("gatherer_small.gif").getImage());
349 // BorderLayout for the main screen. I'll try my best to avoid these in subcomponents as they're space greedy.
350 content_pane.setLayout(new BorderLayout());
351 // Create the menu-bar and stick it up the top.
352 menu_bar = new MenuBar(new MenuListenerImpl());
353
354 //feedback changes
355 //content_pane.add(menu_bar, BorderLayout.NORTH);
356 this.setJMenuBar(menu_bar);
357 // end feedback changes
358
359 // Create the tabbed pane and plop it in the center where it will
360 // expand to consume all available space like any good gas would.
361 tab_pane = new JTabbedPane();
362 tab_pane.addChangeListener(this);
363 tab_pane.setFont(Configuration.getFont("general.font", false));
364
365 if (Configuration.get("workflow.download", true)) {
366 download_pane = new DownloadPane();
367 // "GUI.Download_Tooltip" is used automatically
368 tab_pane.addTab(Dictionary.get("GUI.Download"), JarTools.getImage("download.gif"), download_pane, Dictionary.get("GUI.Download_Tooltip"));
369 tab_pane.setEnabledAt(tab_pane.indexOfComponent(download_pane), Configuration.get("workflow.download", false));
370 }
371
372 gather_pane = new GatherPane();
373 gather_pane.display();
374 if (Configuration.get("workflow.gather", true)) {
375 // "GUI.Gather_Tooltip" is used automatically
376 tab_pane.addTab(Dictionary.get("GUI.Gather"), JarTools.getImage("gather.gif"), gather_pane, Dictionary.get("GUI.Gather_Tooltip"));
377 tab_pane.setEnabledAt(tab_pane.indexOfComponent(gather_pane), Configuration.get("workflow.gather", false));
378 }
379
380 enrich_pane = new EnrichPane();
381 enrich_pane.display();
382 if (Configuration.get("workflow.enrich", true)) {
383 // "GUI.Enrich_Tooltip" is used automatically
384 tab_pane.addTab(Dictionary.get("GUI.Enrich"), JarTools.getImage("enrich.gif"), enrich_pane, Dictionary.get("GUI.Enrich_Tooltip"));
385 tab_pane.setEnabledAt(tab_pane.indexOfComponent(enrich_pane), false);
386 }
387
388 design_pane = new DesignPane();
389 design_pane.display();
390 if (Configuration.get("workflow.design", true)) {
391 // "GUI.Design_Tooltip" is used automatically
392 tab_pane.addTab(Dictionary.get("GUI.Design"), JarTools.getImage("design.gif"), design_pane, Dictionary.get("GUI.Design_Tooltip"));
393 tab_pane.setEnabledAt(tab_pane.indexOfComponent(design_pane), false);
394 }
395
396 create_pane = new CreatePane();
397 create_pane.display();
398 if (Configuration.get("workflow.create", true)) {
399 // "GUI.Create_Tooltip" is used automatically
400 tab_pane.addTab(Dictionary.get("GUI.Create"), JarTools.getImage("create.gif"), create_pane, Dictionary.get("GUI.Create_Tooltip"));
401 tab_pane.setEnabledAt(tab_pane.indexOfComponent(create_pane), false);
402 }
403
404 format_pane = new FormatPane();
405 format_pane.display();
406 if (Configuration.get("workflow.format", true)) {
407 tab_pane.addTab(Dictionary.get("GUI.Format"), JarTools.getImage("format.gif"), format_pane, Dictionary.get("GUI.Format_Tooltip"));
408 tab_pane.setEnabledAt(tab_pane.indexOfComponent(format_pane), false);
409 }
410
411 // The MetaAuditFrame must be created after the gather/enrich panes but before they get focus
412 meta_audit = new MetaAuditFrame();
413
414 // Select the collect pane if it is available
415 if (tab_pane.indexOfComponent(gather_pane) != -1) {
416 tab_pane.setSelectedComponent(gather_pane);
417 }
418 // Otherwise find the first tab that is enabled and select that.
419 else {
420 for (int i = 0; i < tab_pane.getTabCount(); i++) {
421 if (tab_pane.isEnabledAt(i)) {
422 tab_pane.setSelectedIndex(i);
423 break;
424 }
425 }
426 }
427
428 content_pane.add(tab_pane, BorderLayout.CENTER);
429
430 // Add an extra progress bar at the bottom of every screen when using a remote Greenstone server
431 if (Gatherer.isGsdlRemote) {
432 JPanel remote_greenstone_server_progress_panel = new JPanel();
433 JLabel remote_greenstone_server_progress_label = new JLabel(Dictionary.get("RemoteGreenstoneServer.Progress"));
434 remote_greenstone_server_progress_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
435 remote_greenstone_server_progress_panel.setLayout(new BorderLayout());
436 remote_greenstone_server_progress_panel.add(remote_greenstone_server_progress_label, BorderLayout.WEST);
437 remote_greenstone_server_progress_panel.add(RemoteGreenstoneServer.getProgressBar(), BorderLayout.CENTER);
438 content_pane.add(remote_greenstone_server_progress_panel, BorderLayout.SOUTH);
439 }
440
441 // Call refresh to update all controls to reflect current collection status.
442 refresh(-1, Gatherer.c_man.ready());
443 }
444 catch (Exception e) {
445 DebugStream.printStackTrace(e);
446 // The GUI failing to build is an app killer
447 e.printStackTrace();
448 System.exit(1);
449 }
450 }
451
452 public void exit()
453 {
454 exit(0);
455 }
456
457 /** This method ensures that all the things needing saving are saved before Gatherer.exit() is called.
458 */
459 public void exit(int exit_status)
460 {
461 // If we have a collection open remember it for next time, then save it and close it
462 if (Gatherer.c_man.ready()) {
463 Configuration.setString("general.open_collection", true, Gatherer.c_man.getCollectionFilePath());
464 saveThenCloseCurrentCollection();
465 }
466 else {
467 Configuration.setString("general.open_collection", true, null);
468 }
469
470 // Store the current position and size of the GLI for next time
471 Configuration.setBounds("general.bounds", true, getBounds());
472
473 // Save configuration
474 Configuration.save();
475
476 // Hide the main window
477 setVisible(false);
478
479 // If we're running as an applet we don't quit here (we quit when the browser calls GathererApplet.destroy())
480 if (!Gatherer.isApplet) {
481 Gatherer.exit(exit_status);
482 }
483 }
484
485
486 /** 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.
487 */
488 public void lockCollection(boolean import_stage, boolean lock)
489 {
490 locked = lock;
491
492 if (import_stage) {
493 int gather_pos = tab_pane.indexOfComponent(gather_pane);
494 if (gather_pos != -1) {
495 tab_pane.setEnabledAt(gather_pos, !lock);
496 }
497 int enrich_pos = tab_pane.indexOfComponent(enrich_pane);
498 if (enrich_pos != -1) {
499 tab_pane.setEnabledAt(enrich_pos, !lock);
500 }
501 }
502
503 int design_pos = tab_pane.indexOfComponent(design_pane);
504 if (design_pos != -1) {
505 tab_pane.setEnabledAt(design_pos, !lock);
506 }
507 }
508
509
510 public void modeChanged(int mode) {
511 // Set the title
512 String collection_title = null;
513 String collection_name = null;
514 if (Gatherer.c_man.ready()) {
515 Collection collection = Gatherer.c_man.getCollection();
516 collection_title = collection.getTitle();
517 collection_name = collection.getName();
518 collection = null;
519 }
520 setTitle(collection_title, collection_name);
521 collection_title = null;
522 collection_name = null;
523 // Now pass on the message to anyone who cares
524 if (download_pane != null) {
525 download_pane.modeChanged(mode);
526 }
527 if (gather_pane != null) {
528 gather_pane.modeChanged(mode);
529 }
530 if (enrich_pane != null) {
531 enrich_pane.modeChanged(mode);
532 }
533 if (design_pane != null) {
534 design_pane.modeChanged(mode);
535 }
536 if (create_pane != null) {
537 create_pane.modeChanged(mode);
538 }
539 if (format_pane != null) {
540 format_pane.modeChanged(mode);
541 }
542 }
543
544
545 public void refresh(int refresh_reason, boolean collection_loaded)
546 {
547 // Set the collection information in the title bar
548 if (collection_loaded) {
549 Collection collection = Gatherer.c_man.getCollection();
550 setTitle(collection.getTitle(), collection.getName());
551 }
552 else {
553 setTitle(null, null);
554 }
555
556 // Update the menu bar
557 menu_bar.refresh(refresh_reason, collection_loaded);
558
559 // Update the loaded panes
560 if (download_pane != null) {
561 download_pane.refresh(refresh_reason, collection_loaded);
562 }
563 if (gather_pane != null) {
564 gather_pane.refresh(refresh_reason, collection_loaded);
565 }
566 if (enrich_pane != null) {
567 enrich_pane.refresh(refresh_reason, collection_loaded);
568 }
569 if (design_pane != null) {
570 design_pane.refresh(refresh_reason, collection_loaded);
571 }
572 if (create_pane != null) {
573 create_pane.refresh(refresh_reason, collection_loaded);
574 }
575 if (format_pane != null) {
576 format_pane.refresh(refresh_reason, collection_loaded);
577 }
578
579 // Now enable tabs as necessary. Do this on event queue to prevent crazy NPEs
580 if (!locked) {
581 if (tab_updater == null) {
582 tab_updater = new TabUpdater(tab_pane, collection_loaded);
583 }
584 else {
585 tab_updater.setReady(collection_loaded);
586 }
587 SwingUtilities.invokeLater(tab_updater);
588 }
589 }
590
591
592 public void refreshCollectionTree(int refresh_reason)
593 {
594 if (gather_pane != null) {
595 gather_pane.refreshCollectionTree(refresh_reason);
596 }
597 }
598
599
600 public void refreshWorkspaceTree(int refresh_reason)
601 {
602 if (gather_pane != null) {
603 gather_pane.refreshWorkspaceTree(refresh_reason);
604 }
605 }
606
607
608 /** Returns to some "initial" pane (when no collection is loaded) */
609 public void returnToInitialPane()
610 {
611 if (gather_pane != null) {
612 tab_pane.setSelectedComponent(gather_pane);
613 }
614 }
615
616
617 /** Specifies whether a certain tab is enabled or not. */
618 private void setTabEnabled(String rawname, boolean state) {
619 // Retrieve the dictionary based name.
620 String name = Dictionary.get("GUI." + rawname);
621 int index = tab_pane.indexOfTab(name);
622 // Of course we may not have this tab available.
623 if(index != -1) {
624 // Some tabs are also dependant on if a collection is ready
625 Component component = tab_pane.getComponentAt(index);
626 if(component == enrich_pane || component == design_pane || component == create_pane || component == format_pane) {
627 tab_pane.setEnabledAt(index, state && Gatherer.c_man != null && Gatherer.c_man.ready());
628 }
629 else {
630 tab_pane.setEnabledAt(index, state);
631 }
632 // If this was the currently selected tab and it is now disabled, change the view to the first enabled tab.
633 if(tab_pane.getSelectedIndex() == index && !state) {
634 boolean found = false;
635 for(int i = 0; !found && i < tab_pane.getTabCount(); i++) {
636 if(tab_pane.isEnabledAt(i)) {
637 tab_pane.setSelectedIndex(i);
638 found = true;
639 }
640 }
641 // If there are no tabs enabled, which should be impossible, then select the first tab
642 if(!found) {
643 tab_pane.setSelectedIndex(0);
644 }
645 }
646 }
647 }
648
649 /** 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.
650 * @param title
651 * @param name
652 */
653 public void setTitle(String title, String name) {
654 // Finally display the collection name in the title bar.
655 StringBuffer title_buffer = new StringBuffer(Gatherer.PROGRAM_NAME);
656 title_buffer.append(StaticStrings.SPACE_CHARACTER);
657 title_buffer.append(Gatherer.PROGRAM_VERSION);
658 title_buffer.append(StaticStrings.SPACE_CHARACTER);
659 title_buffer.append(StaticStrings.SPACE_CHARACTER);
660 // Describe the current user mode
661 title_buffer.append(StaticStrings.MODE_STR);
662 title_buffer.append(Configuration.getModeAsString());
663 title_buffer.append(StaticStrings.SPACE_CHARACTER);
664 title_buffer.append(StaticStrings.SPACE_CHARACTER);
665 // Now for the current collection
666 title_buffer.append(StaticStrings.COLLECTION_STR);
667 if (title != null && name != null) {
668 title_buffer.append(title);
669 title_buffer.append(StaticStrings.SPACE_CHARACTER);
670 title_buffer.append(StaticStrings.OPEN_PARENTHESIS_CHARACTER);
671 title_buffer.append(name);
672 title_buffer.append(StaticStrings.CLOSE_PARENTHESIS_CHARACTER);
673 }
674 else {
675 title_buffer.append(Dictionary.get("Collection.No_Collection"));
676 }
677 this.setTitle(title_buffer.toString());
678 title_buffer = null;
679 }
680
681
682 private class OpenCollectionTask
683 extends Thread
684 {
685 public void run()
686 {
687 // If using a remote Greenstone check if the collection configurations have been downloaded; do so if not
688 if (Gatherer.isGsdlRemote && !CollectionManager.downloaded_collection_configurations) {
689 if (RemoteGreenstoneServer.downloadCollectionConfigurations().equals("")) {
690 // Something went wrong downloading the collection configurations
691 return;
692 }
693
694 CollectionManager.downloaded_collection_configurations = true;
695 }
696
697 String collection_file_path = showOpenCollectionDialog();
698
699 // User has selected a collection to open
700 if (collection_file_path != null) {
701 // If there is already a collection open, save and close it
702 if (Gatherer.c_man.ready()) {
703 saveThenCloseCurrentCollection();
704 }
705
706 // Open the selected collection
707 Gatherer.c_man.loadCollection(collection_file_path);
708 }
709 }
710 }
711
712
713 /** When the load collection option is chosen this method is called to produce the modal file load prompt.
714 */
715 private String showOpenCollectionDialog()
716 {
717 // We first try the simple open collection dialog
718 SimpleOpenCollectionDialog dialog = new SimpleOpenCollectionDialog();
719 int user_choice = dialog.display();
720
721 // Used simple collection list
722 if (user_choice == SimpleOpenCollectionDialog.OK_OPTION) {
723 return dialog.getFileName();
724 }
725
726 // Chosen to use the advanced 'browse' dialog
727 File collect_directory = null;
728 if (user_choice == SimpleOpenCollectionDialog.BROWSE_OPTION) {
729 if (Gatherer.GS3) {
730 collect_directory = new File(Utility.getSitesDir(Configuration.gsdl3_path));
731 }
732 else {
733 collect_directory = new File(Gatherer.getCollectDirectoryPath());
734 }
735 OpenCollectionDialog chooser = new OpenCollectionDialog(collect_directory);
736 return chooser.getFileName();
737 }
738
739 // User must have cancelled the action
740 return null;
741 }
742
743
744 /** When called this method causes the MetadataAuditTable to display a nice dialog box which contains all the metadata assigned in the collection.
745 */
746 public void showMetaAuditBox() {
747 wait(true);
748 meta_audit.display();
749 wait(false);
750 }
751
752
753 private class NewCollectionTask
754 extends Thread
755 {
756 public void run()
757 {
758 // If using a remote Greenstone check if the collection configurations have been downloaded; do so if not
759 if (Gatherer.isGsdlRemote && !CollectionManager.downloaded_collection_configurations) {
760 if (RemoteGreenstoneServer.downloadCollectionConfigurations().equals("")) {
761 // Something went wrong downloading the collection configurations
762 return;
763 }
764
765 CollectionManager.downloaded_collection_configurations = true;
766 }
767
768 // Create the collection details prompt from new collection prompt
769 NewCollectionDetailsPrompt ncd_prompt = new NewCollectionDetailsPrompt();
770 // dc metadata set is the default
771 ArrayList metadata_sets = new ArrayList();
772 File dc_file = new File(Gatherer.getGLIMetadataDirectoryPath()+"dublin.mds");
773 if (dc_file.exists()) {
774 metadata_sets.add(new MetadataSet(dc_file));
775 }
776 // Create the new collection (if not cancelled) in a new thread.
777 if (!ncd_prompt.isCancelled()) {
778 // If there is already a collection open, save and close it.
779 if (Gatherer.c_man.ready()) {
780 saveThenCloseCurrentCollection();
781 }
782
783 // Create new collection.
784 Gatherer.c_man.createCollection(ncd_prompt.getDescription(), Configuration.getEmail(), ncd_prompt.getName(), ncd_prompt.getTitle(), ncd_prompt.getBase(), metadata_sets);
785 ncd_prompt.dispose();
786 }
787
788 // Done
789 ncd_prompt = null;
790 }
791 }
792
793
794 /** 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.
795 * @param event A ChangeEvent containing information about the event that fired this call.
796 */
797 public void stateChanged(ChangeEvent event)
798 {
799 if (previous_pane != null) {
800 if (previous_pane == gather_pane) {
801 gather_pane.loseFocus();
802 }
803 else if (previous_pane == enrich_pane) {
804 enrich_pane.loseFocus();
805 }
806 else if (previous_pane == design_pane) {
807 design_pane.loseFocus();
808 }
809 else if (previous_pane == create_pane) {
810 create_pane.loseFocus();
811 }
812 else if (previous_pane == format_pane) {
813 format_pane.loseFocus();
814 }
815 }
816
817 menu_bar.tabSelected(tab_pane.getSelectedIndex());
818 int selected_index = tab_pane.getSelectedIndex();
819 if (selected_index == tab_pane.indexOfComponent(download_pane)) {
820 download_pane.gainFocus();
821 }
822 else if (selected_index == tab_pane.indexOfComponent(gather_pane)) {
823 gather_pane.gainFocus();
824 }
825 else if (selected_index == tab_pane.indexOfComponent(enrich_pane)) {
826 enrich_pane.gainFocus();
827 }
828 else if (selected_index == tab_pane.indexOfComponent(design_pane)) {
829 design_pane.gainFocus();
830 }
831 else if (selected_index == tab_pane.indexOfComponent(create_pane)) {
832 create_pane.gainFocus();
833 }
834 else if (selected_index == tab_pane.indexOfComponent(format_pane)) {
835 format_pane.gainFocus();
836 }
837
838 previous_pane = (JPanel) tab_pane.getSelectedComponent();
839
840 }
841
842
843 private MouseListener mouse_blocker_listener = new MouseAdapter() {};
844
845 public void updateUI()
846 {
847 JPanel pane = (JPanel) getContentPane();
848 pane.updateUI();
849 // Also update all of the tabs according to workflow.
850 workflowUpdate("Download", Configuration.get("workflow.download", false));
851 workflowUpdate("Gather", Configuration.get("workflow.gather", false));
852 workflowUpdate("Enrich", Configuration.get("workflow.enrich", false));
853 workflowUpdate("Design", Configuration.get("workflow.design", false));
854 workflowUpdate("Create", Configuration.get("workflow.create", false));
855 workflowUpdate("Format", Configuration.get("workflow.format", false));
856 }
857
858 public void wait(boolean waiting) {
859 Component glass_pane = getGlassPane();
860 if(waiting) {
861 // Show wait cursor.
862 glass_pane.addMouseListener(mouse_blocker_listener);
863 glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
864 glass_pane.setVisible(true);
865 }
866 else {
867 // Hide wait cursor.
868 glass_pane.setVisible(false);
869 glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
870 glass_pane.removeMouseListener(mouse_blocker_listener);
871 }
872 glass_pane = null;
873 }
874
875 public void workflowUpdate(String raw, boolean state) {
876 WorkflowUpdater task = new WorkflowUpdater(raw, state);
877 SwingUtilities.invokeLater(task);
878 task = null;
879 }
880
881
882 /**Overridden from JFrame so we can exit safely when window is closed (or destroyed).
883 * @param event A <strong>WindowEvent</strong> containing information about the event that fired this call.
884 */
885 protected void processWindowEvent(WindowEvent event) {
886 if(event.getID() == WindowEvent.WINDOW_CLOSING) {
887 exit();
888 }
889 }
890
891
892 /** 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.
893 */
894 private class MenuListenerImpl
895 implements MenuListener {
896 /** Called whenever a popup menu is hidden, but we don't care.
897 * @param e Some <strong>MenuEvent</strong> that we could care less about.
898 */
899 public void menuCanceled(MenuEvent e) {
900 }
901 /** Called whenever a menu header (ie button) becomes unselected, but we don't care.
902 * @param e Some <strong>MenuEvent</strong> that we could care less about.
903 */
904 public void menuDeselected(MenuEvent e) {
905 }
906 /** 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.
907 * @param e The <strong>MenuEvent</strong> whose source is checked.
908 */
909 public void menuSelected(MenuEvent e) {
910 if(e.getSource() == menu_bar.help) {
911 if(menu_bar.help.isSelected()) {
912 menu_bar.help.doClick(10);
913 }
914 }
915 }
916 }
917
918 private class TabUpdater
919 implements Runnable {
920 private boolean ready = false;
921 private int download_pos = -1;
922 private int enrich_pos = -1;
923 private int design_pos = -1;
924 private int create_pos = -1;
925 private int format_pos = -1;
926 private int export_pos = -1;
927 private JTabbedPane tab_pane = null;
928
929 public TabUpdater(JTabbedPane tab_pane, boolean ready) {
930 this.ready = ready;
931 this.tab_pane = tab_pane;
932 download_pos = tab_pane.indexOfComponent(download_pane);
933 enrich_pos = tab_pane.indexOfComponent(enrich_pane);
934 design_pos = tab_pane.indexOfComponent(design_pane);
935 create_pos = tab_pane.indexOfComponent(create_pane);
936 format_pos = tab_pane.indexOfComponent(format_pane);
937 }
938
939 public void run()
940 {
941 if (download_pos != -1) {
942 if (ready) {
943 tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", false));
944 }
945 else {
946 tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", true));
947 }
948 }
949 if (enrich_pos != -1) {
950 tab_pane.setEnabledAt(enrich_pos, ready && Configuration.get("workflow.enrich", false));
951 }
952 if (design_pos != -1) {
953 tab_pane.setEnabledAt(design_pos, ready && Configuration.get("workflow.design", false) && Configuration.getMode() > Configuration.ASSISTANT_MODE);
954 }
955 if (create_pos != -1) {
956 tab_pane.setEnabledAt(create_pos, ready && Configuration.get("workflow.create", false));
957 }
958 if (format_pos != -1) {
959 tab_pane.setEnabledAt(format_pos, ready && Configuration.get("workflow.format", false));
960 }
961 }
962
963 public void setReady(boolean ready) {
964 this.ready = ready;
965 }
966 }
967
968 private class WorkflowUpdater
969 implements Runnable {
970 private boolean state;
971 private String raw;
972 public WorkflowUpdater(String raw, boolean state) {
973 this.raw = raw;
974 this.state = state;
975 }
976 public void run() {
977 setTabEnabled(raw, state);
978 }
979 }
980}
Note: See TracBrowser for help on using the repository browser.