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

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

Made major rearrangements to the way path variables are calculated. This is to facilitate being able to specify a "-collectdir" argument to the GLI so one GLI installation can be used in a networked, multi-user situation. Hope I haven't broken anything!

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