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

Last change on this file since 9800 was 9800, checked in by mdewsnip, 19 years ago

Now switches back to the Gather pane before closing the collection, to prevent nasty problems.

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