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

Last change on this file since 17916 was 17916, checked in by davidb, 15 years ago

FLI based version now uses blue fli-*.gif images rather than the default green ones

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