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

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

(MAJOR CHANGE) This is the remote Greenstone building functionality implemented for the West Yorkshire Fire and Rescue Service. It allows collections to be built without having a local version of Greenstone, using either a stand-alone version of the GLI or the applet.

The collections are stored on the server (allowing people to collaborate on collections -- but not at the same time), and only what is necessary to let the user edit the collection is downloaded. Any changes to the collection are uploaded to the server.

An access restriction mechanism is implemented which uses the standard Greenstone user database to control who has access to collections.

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