source: gli/branches/rtl-gli/src/org/greenstone/gatherer/gui/GUIManager.java@ 18297

Last change on this file since 18297 was 18297, checked in by kjdon, 15 years ago

interface updated to display right to left for rtl languages. This code is thanks to Amin Hejazi. It seems to be only partially complete. Amin was working with Greenstone 3 so might have missed some panels

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