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

Last change on this file since 23143 was 23143, checked in by ak19, 14 years ago

More changes to making collectdir movable: 1. When not working with a remote GS or server.exe: if the collecthome set in GLI is not the same as the one in gsdlsite.cfg used by the apache web server, then a dialog pops up on exiting GLI allowing the user to set the collecthome value for both GLI (in the user's GLI config.xml) and the server (in gsdlsite.cfg). 2. Collecthome line in gsdlsite.cfg is removed if it is the default GS collect folder. (Just as a recent commit stores an empty string for the open_collection element in the GLI config.xml file if no collection is left open on exiting GLI and the collect folder is the default GS collect directory.) 3. Some bug fixes.

  • Property svn:keywords set to Author Date Id Revision
File size: 41.6 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.metadata.MetadataXMLFileManager;
63import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
64import org.greenstone.gatherer.util.JarTools;
65import org.greenstone.gatherer.util.StaticStrings;
66import org.greenstone.gatherer.util.Utility;
67
68/** 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. */
69public class GUIManager
70 extends JFrame
71 implements ActionListener, ChangeListener, WindowFocusListener{
72 /** The download pane contains controls for downloading internet sites. */
73 public DownloadPane download_pane = null;
74 /** The gather pane is more like a file manager where you drag files from one tree to another. */
75 public GatherPane gather_pane = null;
76 /** The enrich pane is used to assign, edit and remove metadata from files within the collection. */
77 public EnrichPane enrich_pane = null;
78 /** The design pane allows you to edit the design of the library in terms of the collection configuration file. - the stuff that requires rebuilding */
79 public DesignPane design_pane = null;
80 /** The create pane contains scripting options for importing and building collections into libraries. */
81 public CreatePane create_pane = null;
82 /** 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 */
83 public FormatPane format_pane = null;
84
85 public FileOpenActionListener foa_listener = new FileOpenActionListener();
86
87
88 /** A reference to the currently instantiated help window, if any. */
89 private HelpFrame help = null;
90 /** The menu bar. */
91 public MenuBar menu_bar = null;
92 public MetaAuditFrame meta_audit;
93 /** Are certain panes currently locked? */
94 private boolean locked = false;
95 /** The size of the Gatherer window. */
96 private Dimension size = null;
97 /** The panel within the window that other components are placed on. */
98 private JPanel content_pane = null;
99 /** The last view pane selected. */
100 private JPanel previous_pane;
101 /** The main tab pane containing the different views, available here to trap view change events. */
102 private JTabbedPane tab_pane = null;
103 /** A threaded tab changer to try and avoid NPE on exit. */
104 private TabUpdater tab_updater = null;
105
106 final static String newline = "\n";
107 final static String space = " ";
108
109
110 /**Constructor. Enable window events and arranges all other components.
111 * @param size The intial <strong>Dimension</strong> of the screen.
112 */
113 public GUIManager(Dimension size) {
114 super();
115 this.setComponentOrientation(Dictionary.getOrientation());
116 // Initialization
117 this.help = new HelpFrame();
118 this.size = size;
119
120 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
121
122 // 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.
123 this.addFocusListener(new GLIGUIFocusListener());
124
125 this.addWindowFocusListener(this);
126
127 // Make the Tool tip hang around for a rediculous amount of time.
128 ToolTipManager.sharedInstance().setDismissDelay(10000);
129
130 // Set up some other UI stuff. (fonts handled in Gatherer.main())
131 UIManager.put("FileChooser.lookInLabelText", Dictionary.get("SaveCollectionBox.Look_In"));
132 UIManager.put("FileChooser.filesOfTypeLabelText", Dictionary.get("SaveCollectionBox.Files_Of_Type"));
133 UIManager.put("FileChooser.fileNameLabelText", Dictionary.get("SaveCollectionBox.File_Name"));
134 }
135
136
137 public void windowGainedFocus(WindowEvent e)
138 {
139 }
140
141
142 public void windowLostFocus(WindowEvent e)
143 {
144 // Save the loaded collection
145 if (Gatherer.c_man != null && Gatherer.c_man.ready() && Gatherer.c_man.getCollection().cdm != null) {
146 Gatherer.c_man.saveCollection();
147 }
148 }
149
150
151 private class GLIGUIFocusListener
152 extends FocusAdapter {
153 public void focusGained(FocusEvent e) {
154 if (ModalDialog.current_modal != null) {
155 ModalDialog.current_modal.makeVisible();
156 ModalDialog.current_modal.toFront();
157 }
158 }
159 }
160
161 /** 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.
162 * @param event An <strong>ActionEvent</strong> containing information about the action that has occured.
163 */
164 public void actionPerformed(ActionEvent event) {
165 Object esrc = event.getSource();
166 // *************
167 // File Options.
168 // *************
169 if (esrc == menu_bar.file_associations) {
170 Gatherer.assoc_man.edit();
171 }
172 else if (esrc == menu_bar.file_close) {
173 saveThenCloseCurrentCollection();
174 }
175 else if (esrc == menu_bar.file_delete) {
176 new DeleteCollectionTask().start();
177 }
178 else if (esrc == menu_bar.file_cdimage) {
179 WriteCDImagePrompt wcdip = new WriteCDImagePrompt();
180 wcdip.display();
181 wcdip.destroy();
182 wcdip = null;
183 }
184 else if (esrc == menu_bar.file_exportas) {
185 ExportAsPrompt eap = new ExportAsPrompt();
186 eap.display();
187 eap.destroy();
188 eap = null;
189 }
190 else if (esrc == menu_bar.file_exit) {
191 exit();
192 }
193 else if (esrc == menu_bar.file_new) {
194 new NewCollectionTask().start();
195 }
196 else if (esrc == menu_bar.file_open) {
197 new OpenCollectionTask().start();
198 }
199 else if (esrc == menu_bar.file_options) {
200 new Preferences();
201 }
202 else if (esrc == menu_bar.file_save) {
203 // Very important: make sure metadata values are saved too
204 enrich_pane.stopEditingAndRebuild();
205 // Make sure all the metadata has been saved to file
206 MetadataXMLFileManager.saveMetadataXMLFiles();
207
208 Gatherer.c_man.saveCollection();
209 }
210
211 // *************
212 // Edit Options.
213 // *************
214 else if(esrc == menu_bar.edit_copy) {
215 try {
216 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
217 // Get the component with selected text as a JTextComponent
218 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();//getFocusOwner();
219 text.copy();
220 }
221 catch (Exception cce) {
222 // If the component is not a text component ignore the copy command
223 DebugStream.println(cce.toString());
224 }
225 }
226 else if(esrc == menu_bar.edit_cut) {
227 try {
228 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
229 // Get the component with selected text as a JTextComponent
230 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
231 // Cut the text to the clipboard
232 text.cut();
233 }
234 catch (ClassCastException cce) {
235 // If the component is not a text component ignore the cut command
236 DebugStream.println(cce.toString());
237 }
238 }
239 else if(esrc == menu_bar.edit_paste) {
240 try {
241 KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
242 // Get the component with selected text as a JTextComponent
243 JTextComponent text = (JTextComponent) kfm.getPermanentFocusOwner();
244 // Cut the text to the clipboard
245 text.paste();
246 }
247 catch (ClassCastException cce) {
248 // If the component is not a text component ignore the paste command
249 DebugStream.println(cce.toString());
250 }
251 }
252
253 // *************
254 // Help Options.
255 // *************
256 else if (esrc == menu_bar.help_general) {
257 HelpFrame.setView("introduction");
258 }
259 else if (esrc == menu_bar.help_download) {
260 HelpFrame.setView("themirrorview");
261 }
262 else if (esrc == menu_bar.help_gather) {
263 HelpFrame.setView("collectingfiles");
264 }
265 else if (esrc == menu_bar.help_enrich) {
266 HelpFrame.setView("enrichingacollection");
267 }
268 else if (esrc == menu_bar.help_design) {
269 HelpFrame.setView("designingacollection");
270 }
271 else if (esrc == menu_bar.help_create) {
272 HelpFrame.setView("producingthecollection");
273 }
274 else if (esrc == menu_bar.help_format) {
275 HelpFrame.setView("formattingacollection");
276 }
277 else if (esrc == menu_bar.help_about) {
278 new AboutDialog(this);
279 }
280 }
281
282
283 /** 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.
284 */
285 public void afterDisplay() {
286 if (download_pane != null) {
287 download_pane.afterDisplay();
288 }
289 enrich_pane.afterDisplay();
290 }
291
292
293 public void closeCurrentCollection()
294 {
295 tab_pane.setSelectedComponent(gather_pane);
296 Gatherer.c_man.closeCollection();
297 }
298
299
300 public void saveThenCloseCurrentCollection()
301 {
302 Gatherer.c_man.saveCollection();
303 closeCurrentCollection();
304 }
305
306
307 /** This is called when we're absolutely finished with the GLI. It is *not* called when the applet is suspended.
308 */
309 public void destroy()
310 {
311 // Destroying create pane ensures the latest log has been closed
312 if (create_pane != null) {
313 create_pane.destroy();
314 }
315
316 // Deal to help
317 if (help != null) {
318 help.destroy();
319 help = null;
320 }
321 }
322
323
324 /** Enabled events on the window to be trapped, creates all the visual components, then builds the tab and other layouts.
325 */
326 public void display() {
327 content_pane = (JPanel) this.getContentPane();
328 content_pane.setComponentOrientation(Dictionary.getOrientation());
329
330 // Enable window-type events to be fired.
331 enableEvents(AWTEvent.WINDOW_EVENT_MASK);
332 // Initialise and layout sub-components, plus other window dressing.
333 try {
334 this.setSize(size);
335
336 // Set the title
337 String collection_title = null;
338 String collection_name = null;
339 if (Gatherer.c_man.ready()) {
340 Collection collection = Gatherer.c_man.getCollection();
341 collection_title = collection.getTitle();
342 collection_name = collection.getGroupQualifiedName(true);
343 collection = null;
344 }
345 setTitle(collection_title, collection_name);
346 collection_title = null;
347 collection_name = null;
348
349 // Pretty corner icon
350 String gsmall_image = "gatherer.png";
351 if (Configuration.fedora_info.isActive()) {
352 gsmall_image = "fli-" + gsmall_image;
353 }
354 if(Gatherer.isGsdlRemote) {
355 gsmall_image = "client-" + gsmall_image;
356 }
357 this.setIconImage(JarTools.getImage(gsmall_image).getImage());
358 // BorderLayout for the main screen. I'll try my best to avoid these in subcomponents as they're space greedy.
359 content_pane.setLayout(new BorderLayout());
360 // Create the menu-bar and stick it up the top.
361 menu_bar = new MenuBar(new MenuListenerImpl());
362 menu_bar.setComponentOrientation(Dictionary.getOrientation());
363
364 //feedback changes
365 //content_pane.add(menu_bar, BorderLayout.NORTH);
366 this.setJMenuBar(menu_bar);
367 // end feedback changes
368
369 // Create the tabbed pane and plop it in the center where it will
370 // expand to consume all available space like any good gas would.
371 tab_pane = new JTabbedPane();
372 tab_pane.setComponentOrientation(Dictionary.getOrientation());
373 tab_pane.addChangeListener(this);
374 tab_pane.setFont(Configuration.getFont("general.font", false));
375
376 if (Configuration.get("workflow.download", true) && Gatherer.isDownloadEnabled) {
377 download_pane = new DownloadPane();
378 // "GUI.Download_Tooltip" is used automatically
379 tab_pane.addTab(Dictionary.get("GUI.Download"), JarTools.getImage("download.gif"), download_pane, Dictionary.get("GUI.Download_Tooltip"));
380 tab_pane.setEnabledAt(tab_pane.indexOfComponent(download_pane), Configuration.get("workflow.download", false));
381 }
382
383 gather_pane = new GatherPane();
384 gather_pane.display();
385 if (Configuration.get("workflow.gather", true)) {
386 // "GUI.Gather_Tooltip" is used automatically
387 tab_pane.addTab(Dictionary.get("GUI.Gather"), JarTools.getImage("gather.gif"), gather_pane, Dictionary.get("GUI.Gather_Tooltip"));
388 tab_pane.setEnabledAt(tab_pane.indexOfComponent(gather_pane), Configuration.get("workflow.gather", false));
389 }
390
391 enrich_pane = new EnrichPane();
392 enrich_pane.display();
393 if (Configuration.get("workflow.enrich", true)) {
394 // "GUI.Enrich_Tooltip" is used automatically
395 tab_pane.addTab(Dictionary.get("GUI.Enrich"), JarTools.getImage("enrich.gif"), enrich_pane, Dictionary.get("GUI.Enrich_Tooltip"));
396 tab_pane.setEnabledAt(tab_pane.indexOfComponent(enrich_pane), false);
397 }
398
399 design_pane = new DesignPane();
400 design_pane.display();
401 if (Configuration.get("workflow.design", true)) {
402 // "GUI.Design_Tooltip" is used automatically
403 if (Configuration.fedora_info.isActive()) {
404 tab_pane.addTab("Plugins", JarTools.getImage("design.gif"), design_pane, Dictionary.get("GUI.Design_Tooltip"));
405 }
406 else {
407 tab_pane.addTab(Dictionary.get("GUI.Design"), JarTools.getImage("design.gif"), design_pane, Dictionary.get("GUI.Design_Tooltip"));
408 }
409
410 tab_pane.setEnabledAt(tab_pane.indexOfComponent(design_pane), false);
411 }
412
413 create_pane = new CreatePane();
414 create_pane.setComponentOrientation(Dictionary.getOrientation());
415 create_pane.display();
416 if (Configuration.get("workflow.create", true)) {
417 // "GUI.Create_Tooltip" is used automatically
418 tab_pane.addTab(Dictionary.get("GUI.Create"), JarTools.getImage("create.gif"), create_pane, Dictionary.get("GUI.Create_Tooltip"));
419 tab_pane.setEnabledAt(tab_pane.indexOfComponent(create_pane), false);
420 }
421
422 format_pane = new FormatPane();
423 format_pane.setComponentOrientation(Dictionary.getOrientation());
424 format_pane.display();
425 if (Configuration.get("workflow.format", true)) {
426 tab_pane.addTab(Dictionary.get("GUI.Format"), JarTools.getImage("format.gif"), format_pane, Dictionary.get("GUI.Format_Tooltip"));
427 tab_pane.setEnabledAt(tab_pane.indexOfComponent(format_pane), false);
428 }
429
430 // The MetaAuditFrame must be created after the gather/enrich panes but before they get focus
431 meta_audit = new MetaAuditFrame();
432 meta_audit.setComponentOrientation(Dictionary.getOrientation());
433 // Select the collect pane if it is available
434 if (tab_pane.indexOfComponent(gather_pane) != -1) {
435 tab_pane.setSelectedComponent(gather_pane);
436 }
437 // Otherwise find the first tab that is enabled and select that.
438 else {
439 for (int i = 0; i < tab_pane.getTabCount(); i++) {
440 if (tab_pane.isEnabledAt(i)) {
441 tab_pane.setSelectedIndex(i);
442 break;
443 }
444 }
445 }
446
447 content_pane.add(tab_pane, BorderLayout.CENTER);
448
449 // Add an extra progress bar at the bottom of every screen when using a remote Greenstone server
450 if (Gatherer.isGsdlRemote) {
451 JPanel remote_greenstone_server_progress_panel = new JPanel();
452 //remote_greenstone_server_progress_panel.setComponentOrientation(Dictionary.getOrientation());
453 JLabel remote_greenstone_server_progress_label = new JLabel(Dictionary.get("RemoteGreenstoneServer.Progress"));
454 //remote_greenstone_server_progress_label.setComponentOrientation(Dictionary.getOrientation());
455 remote_greenstone_server_progress_panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
456 remote_greenstone_server_progress_panel.setLayout(new BorderLayout());
457 remote_greenstone_server_progress_panel.add(remote_greenstone_server_progress_label, BorderLayout.LINE_START);
458 remote_greenstone_server_progress_panel.add(Gatherer.remoteGreenstoneServer.getProgressBar(), BorderLayout.CENTER);
459 content_pane.add(remote_greenstone_server_progress_panel, BorderLayout.SOUTH);
460 }
461
462 // Call refresh to update all controls to reflect current collection status.
463 refresh(-1, Gatherer.c_man.ready());
464 }
465 catch (Exception e) {
466 DebugStream.printStackTrace(e);
467 // The GUI failing to build is an app killer
468 e.printStackTrace();
469 System.exit(1);
470 }
471 }
472
473 public void exit()
474 {
475 exit(0);
476 }
477
478 // some cases we have already saved the collection, but don't want to
479 // override the general.open_collection value here
480 public void exitNoCollectionSave(int exit_status) {
481 // Store the current position and size of the GLI for next time
482 Configuration.setBounds("general.bounds", true, getBounds());
483
484 // Save configuration
485 Configuration.save();
486
487 // Hide the main window
488 setVisible(false);
489
490 // If we're running as an applet we don't quit here (we quit when the browser calls GathererApplet.destroy())
491 if (!Gatherer.isApplet) {
492 Gatherer.exit(exit_status);
493 }
494
495 }
496 /** This method ensures that all the things needing saving are saved before Gatherer.exit() is called.
497 */
498 public void exit(int exit_status)
499 {
500 boolean collection_open = false;
501 // If we have a collection open remember it for next time, then save it and close it
502 if (Gatherer.c_man.ready()) {
503 // but we no longer remember open collections for remote GLI, as this causes problems
504 // in applets when other users on a machine want to use an applet and GLI wants to load
505 // a collection left open from a previous session and *requires* the old user to authenticate
506 if(Gatherer.isGsdlRemote) {
507 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
508 true, "");
509 } else {
510 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
511 true, CollectionManager.getLoadedCollectionColFilePath());
512 }
513 saveThenCloseCurrentCollection();
514 collection_open = true;
515 }
516 else {
517 // if there was no open collection, then write out the collect dir path for next time
518 // IF this is not the default collect directory and not a remote GLI/applet
519 if(Gatherer.isGsdlRemote || Gatherer.getCollectDirectoryPath().equals(
520 Gatherer.getDefaultGSCollectDirectoryPath(true))) {
521 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
522 true, "");
523 } else {
524 Configuration.setString("general.open_collection"+Configuration.gliPropertyNameSuffix(),
525 true, Gatherer.getCollectDirectoryPath());
526 }
527 }
528
529
530 // Basically, if GLI coldir != gsdlsite_colhome, we ask them if they want to save GLI coldir as gsdlsite_colhome
531 // If gsdlsite_colhome = "" (meaning default GS coldir) and GLI is also set to defaultGScoldir, no saving necessary.
532 // We ONLY do this for the local included apache web server, since the issue revolves around gsdlsite.cfg containing
533 // the global collecthome when using the apache web server. This is not an issue for remote GS or server.exe (the latter
534 // has separate config files specifying collecthome for when GLI is running whereas when just the server.exe is running).
535 if(!Gatherer.isGsdlRemote && !Gatherer.isPersistentServer()) {
536
537 String defaultColDir = Gatherer.getDefaultGSCollectDirectoryPath(false); // no filesep at end
538 String gliColDir = Gatherer.getCollectDirectoryPath();
539 String serverColDir = Gatherer.gsdlsite_collecthome;
540
541 boolean showSettingsDlg = true;
542 // if collectdir was changed during GLI session (to something different from what's in gsdlsite), need to ask what to store
543 if(gliColDir.equals(Gatherer.gsdlsite_collecthome+File.separator)) {
544 showSettingsDlg = false;
545 } else if(Gatherer.gsdlsite_collecthome.equals("") // both set to default coldir
546 && gliColDir.equals(defaultColDir+File.separator)) {
547 showSettingsDlg = false;
548 }
549 if(showSettingsDlg) {
550
551 // else we will be showing the Collect Directory Settings Dialog
552 if(gliColDir.endsWith(File.separator)) {
553 gliColDir = gliColDir.substring(0, gliColDir.length()-1);
554 }
555
556 if(serverColDir.equals("")) {
557 serverColDir = defaultColDir;
558 }
559 collectDirSettingsDialog(defaultColDir, serverColDir, gliColDir, collection_open);
560 }
561 }
562
563 // Store the current position and size of the GLI for next time
564 Configuration.setBounds("general.bounds", true, getBounds());
565
566 // Save configuration
567 Configuration.save();
568
569 // Hide the main window
570 setVisible(false);
571
572 // If we're running as an applet we don't quit here (we quit when the browser calls GathererApplet.destroy())
573 if (!Gatherer.isApplet) {
574 Gatherer.exit(exit_status);
575 }
576 }
577
578 public void collectDirSettingsDialog(final String defaultColDir,
579 final String from, final String to, final boolean collection_open)
580 {
581 final JDialog colHomeDialog
582 = new JDialog(this, Dictionary.get("GUI.CollectHome.title"), true); // this = Gatherer.g_man
583 colHomeDialog.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
584
585
586 JRadioButton gliYes = new JRadioButton(Dictionary.get("General.Yes"), true);
587 // the default selection for GLI, collecthome=to
588 JRadioButton serverYes = new JRadioButton(Dictionary.get("General.Yes")); // not selected for the server
589 JRadioButton gliNo = null;
590 JRadioButton gliThirdOption = null;
591 JRadioButton serverNo = null;
592 JRadioButton serverThirdOption = null;
593
594 if(from.equals(defaultColDir)) {
595 gliNo = new JRadioButton(Dictionary.get("GUI.CollectHome.resetToDefault"));
596 serverNo = new JRadioButton(Dictionary.get("GUI.CollectHome.leaveAtDefault"), true);
597 // default selection for server, collecthome=from
598 } else {
599 gliNo = new JRadioButton(Dictionary.get("General.No"));
600 serverNo = new JRadioButton(Dictionary.get("General.No"), true); // default selection for server
601 if(!to.equals(defaultColDir)) { // neither from nor to is the default GS collect dir, so give them that as the third option
602 gliThirdOption = new JRadioButton(Dictionary.get("GUI.CollectHome.reset"));
603 serverThirdOption = new JRadioButton(Dictionary.get("GUI.CollectHome.reset"));
604 }
605 }
606
607 JPanel gliPanel = new JPanel(); // flowlayout by default
608 ButtonGroup gliGroup = new ButtonGroup();
609 JPanel serverPanel = new JPanel(); // flowlayout by default
610 ButtonGroup serverGroup = new ButtonGroup();
611
612 gliGroup.add(gliYes);
613 gliPanel.add(gliYes);
614 serverGroup.add(serverYes);
615 serverPanel.add(serverYes);
616
617 gliGroup.add(gliNo);
618 gliPanel.add(gliNo);
619 serverGroup.add(serverNo);
620 serverPanel.add(serverNo);
621
622 if(gliThirdOption != null) {
623 gliThirdOption = new JRadioButton("Reset to default");
624 serverThirdOption = new JRadioButton("Reset to default");
625
626 gliGroup.add(gliThirdOption);
627 gliPanel.add(gliThirdOption);
628 serverGroup.add(serverThirdOption);
629 serverPanel.add(serverThirdOption);
630 }
631
632 // vars need to be final to use them in the actionlistener below
633 final JRadioButton gli_yes = gliYes;
634 final JRadioButton gli_no = gliNo;
635 final JRadioButton gli_optional = gliThirdOption;
636 final JRadioButton server_yes = serverYes;
637 final JRadioButton server_no = serverNo;
638 final JRadioButton server_optional = serverThirdOption;
639
640 JButton okButton = new JButton(Dictionary.get("General.OK"));
641 okButton.addActionListener(new ActionListener() {
642 public void actionPerformed(ActionEvent e) {
643 // store the option chosen for GLI
644 String gliColDir = to;
645 if(gli_optional != null && gli_optional.isSelected()) {
646 // defaultColDir
647 gliColDir = "";
648 } else if(gli_yes.isSelected()) {
649 gliColDir = to;
650 } else if (gli_no.isSelected()) {
651 gliColDir = from;
652 }
653 if(defaultColDir.equals(gliColDir)) {
654 gliColDir = "";
655 }
656 if(!(collection_open && gli_yes.isSelected())) { // don't overwrite open collections
657 Configuration.setString(
658 "general.open_collection"+Configuration.gliPropertyNameSuffix(),
659 true, gliColDir);
660 }
661
662 // store the option chosen for the server's settings
663 String serverColDir = from;
664 if(server_optional != null && server_optional.isSelected()) {
665 // defaultColDir
666 serverColDir = null;
667 } else if(server_yes.isSelected()) {
668 serverColDir = to;
669 } else if (server_no.isSelected()) {
670 serverColDir = from;
671 }
672 if(serverColDir != null && defaultColDir.equals(serverColDir)) {
673 serverColDir = null;
674 }
675
676 Gatherer.gsdlsite_collecthome = Utility.updatePropertyConfigFile(
677 Gatherer.getGsdlSiteConfigFile(), "collecthome", serverColDir);
678
679 colHomeDialog.dispose();
680 }
681 });
682
683 //String[] dirs = {from, to};
684 //JLabel message = new JLabel(Dictionary.get("GUI.CollectHome.message", dirs));
685 JLabel message = new JLabel(Dictionary.get("GUI.CollectHome.message"));
686 JLabel fromDirLine = new JLabel(Dictionary.get("GUI.CollectHome.dir", from));
687 fromDirLine.setBorder(BorderFactory.createEmptyBorder(0,25,0,0)); // padding
688 JLabel toLine = new JLabel(Dictionary.get("GUI.CollectHome.to"));
689 JLabel toDirLine = new JLabel(Dictionary.get("GUI.CollectHome.dir", to));
690 toDirLine.setBorder(BorderFactory.createEmptyBorder(0,25,0,0)); // padding
691 JLabel gliOption = new JLabel(Dictionary.get("GUI.CollectHome.gli"));
692 JLabel serverOption = new JLabel(Dictionary.get("GUI.CollectHome.server"));
693
694 JPanel mainPanel = new JPanel();
695 mainPanel.setLayout(new GridLayout(9, 1));
696 mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); // padding
697 mainPanel.add(message);
698 mainPanel.add(fromDirLine);
699 mainPanel.add(toLine);
700 mainPanel.add(toDirLine);
701 mainPanel.add(gliOption);
702 mainPanel.add(gliPanel);
703 mainPanel.add(serverOption);
704 mainPanel.add(serverPanel);
705 mainPanel.add(okButton);
706 Container c = colHomeDialog.getContentPane();
707 c.setLayout(new BorderLayout());
708 c.add(mainPanel, BorderLayout.CENTER);
709 colHomeDialog.getRootPane().setDefaultButton(okButton);
710
711 colHomeDialog.pack();
712 colHomeDialog.setVisible(true);
713 }
714
715
716 /** 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.
717 */
718 public void lockCollection(boolean import_stage, boolean lock)
719 {
720 locked = lock;
721
722 if (import_stage) {
723 int gather_pos = tab_pane.indexOfComponent(gather_pane);
724 if (gather_pos != -1) {
725 tab_pane.setEnabledAt(gather_pos, !lock);
726 }
727 int enrich_pos = tab_pane.indexOfComponent(enrich_pane);
728 if (enrich_pos != -1) {
729 tab_pane.setEnabledAt(enrich_pos, !lock);
730 }
731 }
732
733 int design_pos = tab_pane.indexOfComponent(design_pane);
734 if (design_pos != -1) {
735 tab_pane.setEnabledAt(design_pos, !lock);
736 }
737 }
738
739
740 public void modeChanged(int mode) {
741 // Set the title
742 String collection_title = null;
743 String collection_name = null;
744 if (Gatherer.c_man.ready()) {
745 Collection collection = Gatherer.c_man.getCollection();
746 collection_title = collection.getTitle();
747 collection_name = collection.getGroupQualifiedName(true);
748 collection = null;
749 }
750 setTitle(collection_title, collection_name);
751 collection_title = null;
752 collection_name = null;
753 // Now pass on the message to anyone who cares
754 if (download_pane != null) {
755 download_pane.modeChanged(mode);
756 }
757 if (gather_pane != null) {
758 gather_pane.modeChanged(mode);
759 }
760 if (enrich_pane != null) {
761 enrich_pane.modeChanged(mode);
762 }
763 if (design_pane != null) {
764 design_pane.modeChanged(mode);
765 }
766 if (create_pane != null) {
767 create_pane.modeChanged(mode);
768 }
769 if (format_pane != null) {
770 format_pane.modeChanged(mode);
771 }
772 }
773
774
775 public void refresh(int refresh_reason, boolean collection_loaded)
776 {
777 // Set the collection information in the title bar
778 if (collection_loaded) {
779 Collection collection = Gatherer.c_man.getCollection();
780 setTitle(collection.getTitle(), collection.getGroupQualifiedName(true));
781 }
782 else {
783 setTitle(null, null);
784 }
785
786 // Update the menu bar
787 menu_bar.refresh(refresh_reason, collection_loaded);
788
789 // Update the loaded panes
790 if (download_pane != null) {
791 download_pane.refresh(refresh_reason, collection_loaded);
792 }
793 if (gather_pane != null) {
794 gather_pane.refresh(refresh_reason, collection_loaded);
795 }
796 if (enrich_pane != null) {
797 enrich_pane.refresh(refresh_reason, collection_loaded);
798 }
799 if (design_pane != null) {
800 design_pane.refresh(refresh_reason, collection_loaded);
801 }
802 if (create_pane != null) {
803 create_pane.refresh(refresh_reason, collection_loaded);
804 }
805 if (format_pane != null) {
806 format_pane.refresh(refresh_reason, collection_loaded);
807 }
808
809 // Now enable tabs as necessary. Do this on event queue to prevent crazy NPEs
810 if (!locked) {
811 if (tab_updater == null) {
812 tab_updater = new TabUpdater(tab_pane, collection_loaded);
813 }
814 else {
815 tab_updater.setReady(collection_loaded);
816 }
817 SwingUtilities.invokeLater(tab_updater);
818 }
819 }
820
821
822 public void refreshCollectionTree(int refresh_reason)
823 {
824 if (gather_pane != null) {
825 gather_pane.refreshCollectionTree(refresh_reason);
826 }
827 }
828
829
830 public void refreshWorkspaceTree(int refresh_reason)
831 {
832 if (gather_pane != null) {
833 gather_pane.refreshWorkspaceTree(refresh_reason);
834 }
835 }
836
837 public void refreshWorkspaceTreeGreenstoneCollections()
838 {
839 refreshWorkspaceTree(WorkspaceTree.LIBRARY_CONTENTS_CHANGED);
840 }
841
842 /** Specifies whether a certain tab is enabled or not. */
843 private void setTabEnabled(String rawname, boolean state) {
844 // Retrieve the dictionary based name.
845 String name = Dictionary.get("GUI." + rawname);
846 int index = tab_pane.indexOfTab(name);
847 // Of course we may not have this tab available.
848 if(index != -1) {
849 // Some tabs are also dependant on if a collection is ready
850 Component component = tab_pane.getComponentAt(index);
851 if(component == enrich_pane || component == design_pane || component == create_pane || component == format_pane) {
852 tab_pane.setEnabledAt(index, state && Gatherer.c_man != null && Gatherer.c_man.ready());
853 }
854 else {
855 tab_pane.setEnabledAt(index, state);
856 }
857 // If this was the currently selected tab and it is now disabled, change the view to the first enabled tab.
858 if(tab_pane.getSelectedIndex() == index && !state) {
859 boolean found = false;
860 for(int i = 0; !found && i < tab_pane.getTabCount(); i++) {
861 if(tab_pane.isEnabledAt(i)) {
862 tab_pane.setSelectedIndex(i);
863 found = true;
864 }
865 }
866 // If there are no tabs enabled, which should be impossible, then select the first tab
867 if(!found) {
868 tab_pane.setSelectedIndex(0);
869 }
870 }
871 }
872 }
873
874 /** 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.
875 * @param title
876 * @param name
877 */
878 public void setTitle(String title, String name) {
879
880 // Finally display the collection name in the title bar.
881 StringBuffer title_buffer = new StringBuffer(Configuration.getApplicationTitle());
882 title_buffer.append(StaticStrings.SPACE_CHARACTER);
883 title_buffer.append(Gatherer.PROGRAM_VERSION);
884 title_buffer.append(StaticStrings.SPACE_CHARACTER);
885 title_buffer.append(StaticStrings.SPACE_CHARACTER);
886 // Server version information
887 title_buffer.append(Gatherer.getServerVersionAsString());
888 title_buffer.append(StaticStrings.SPACE_CHARACTER);
889 title_buffer.append(StaticStrings.SPACE_CHARACTER);
890 // Describe the current user mode
891 title_buffer.append(StaticStrings.MODE_STR);
892 title_buffer.append(Configuration.getModeAsString());
893 title_buffer.append(StaticStrings.SPACE_CHARACTER);
894 title_buffer.append(StaticStrings.SPACE_CHARACTER);
895 // Now for the current collection
896 title_buffer.append(StaticStrings.COLLECTION_STR);
897 if (title != null && name != null) {
898 title_buffer.append(title);
899 title_buffer.append(StaticStrings.SPACE_CHARACTER);
900 title_buffer.append(StaticStrings.OPEN_PARENTHESIS_CHARACTER);
901 title_buffer.append(name);
902 title_buffer.append(StaticStrings.CLOSE_PARENTHESIS_CHARACTER);
903 }
904 else {
905 title_buffer.append(Dictionary.get("Collection.No_Collection"));
906 }
907 this.setTitle(title_buffer.toString());
908 title_buffer = null;
909 }
910
911
912 private class OpenCollectionTask
913 extends Thread
914 {
915 public void run()
916 {
917 String collection_file_path = showOpenCollectionDialog();
918
919 // User has selected a collection to open
920 if (collection_file_path != null) {
921 // If there is already a collection open, save and close it
922 if (Gatherer.c_man.ready()) {
923 saveThenCloseCurrentCollection();
924 }
925
926 // Open the selected collection
927 Gatherer.c_man.loadCollection(collection_file_path);
928 }
929 }
930 }
931
932
933 /** When the load collection option is chosen this method is called to produce the modal file load prompt.
934 */
935 private String showOpenCollectionDialog()
936 {
937 OpenCollectionDialog dialog = new OpenCollectionDialog();
938 dialog.setComponentOrientation(Dictionary.getOrientation());
939 if (dialog.display() == OpenCollectionDialog.OK_OPTION) {
940 return dialog.getFileName();
941 }
942
943 // User must have cancelled the action
944 return null;
945 }
946
947
948 /** When called this method causes the MetadataAuditTable to display a nice dialog box which contains all the metadata assigned in the collection.
949 */
950 public void showMetaAuditBox() {
951 wait(true);
952 meta_audit.display();
953 wait(false);
954 }
955
956
957 private class NewCollectionTask
958 extends Thread
959 {
960 public void run()
961 {
962 // Create the collection details prompt from new collection prompt
963 NewCollectionDetailsPrompt ncd_prompt = new NewCollectionDetailsPrompt();
964
965 // Create the new collection (if not cancelled) in a new thread.
966 if (!ncd_prompt.isCancelled()) {
967 // If there is already a collection open, save and close it.
968 if (Gatherer.c_man.ready()) {
969 saveThenCloseCurrentCollection();
970 }
971
972 // Create new collection.
973 Gatherer.c_man.createCollection(ncd_prompt.getDescription(), Configuration.getEmail(), ncd_prompt.getName(), ncd_prompt.getTitle(), ncd_prompt.getBase(), new ArrayList());
974 ncd_prompt.dispose();
975 }
976
977 // Done
978 ncd_prompt = null;
979 }
980 }
981
982
983 private class DeleteCollectionTask
984 extends Thread
985 {
986 public void run()
987 {
988 // The rest is handled by the DeleteCollectionPrompt
989 DeleteCollectionPrompt dc_prompt = new DeleteCollectionPrompt();
990 if (dc_prompt.display()) {
991 //closeCurrentCollection();
992 }
993 dc_prompt.destroy();
994 dc_prompt = null;
995 }
996 }
997
998
999 /** 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.
1000 * @param event A ChangeEvent containing information about the event that fired this call.
1001 */
1002 public void stateChanged(ChangeEvent event)
1003 {
1004 if (previous_pane != null) {
1005 if (previous_pane == gather_pane) {
1006 gather_pane.loseFocus();
1007 }
1008 else if (previous_pane == enrich_pane) {
1009 enrich_pane.loseFocus();
1010 }
1011 else if (previous_pane == design_pane) {
1012 design_pane.loseFocus();
1013 }
1014 else if (previous_pane == create_pane) {
1015 create_pane.loseFocus();
1016 }
1017 else if (previous_pane == format_pane) {
1018 format_pane.loseFocus();
1019 }
1020 }
1021
1022 menu_bar.tabSelected(tab_pane.getSelectedIndex());
1023 int selected_index = tab_pane.getSelectedIndex();
1024 if (selected_index == tab_pane.indexOfComponent(download_pane)) {
1025 download_pane.gainFocus();
1026 }
1027 else if (selected_index == tab_pane.indexOfComponent(gather_pane)) {
1028 gather_pane.gainFocus();
1029 }
1030 else if (selected_index == tab_pane.indexOfComponent(enrich_pane)) {
1031 enrich_pane.gainFocus();
1032 }
1033 else if (selected_index == tab_pane.indexOfComponent(design_pane)) {
1034 design_pane.gainFocus();
1035 }
1036 else if (selected_index == tab_pane.indexOfComponent(create_pane)) {
1037 create_pane.gainFocus();
1038 }
1039 else if (selected_index == tab_pane.indexOfComponent(format_pane)) {
1040 format_pane.gainFocus();
1041 }
1042
1043 previous_pane = (JPanel) tab_pane.getSelectedComponent();
1044
1045 }
1046
1047
1048 private MouseListener mouse_blocker_listener = new MouseAdapter() {};
1049
1050 public void updateUI()
1051 {
1052 JPanel pane = (JPanel) getContentPane();
1053 pane.updateUI();
1054 // Also update all of the tabs according to workflow.
1055 workflowUpdate("Download", Configuration.get("workflow.download", false));
1056 workflowUpdate("Gather", Configuration.get("workflow.gather", false));
1057 workflowUpdate("Enrich", Configuration.get("workflow.enrich", false));
1058 workflowUpdate("Design", Configuration.get("workflow.design", false));
1059 workflowUpdate("Create", Configuration.get("workflow.create", false));
1060 workflowUpdate("Format", Configuration.get("workflow.format", false));
1061 }
1062
1063 public void wait(boolean waiting) {
1064 Component glass_pane = getGlassPane();
1065 if(waiting) {
1066 // Show wait cursor.
1067 glass_pane.addMouseListener(mouse_blocker_listener);
1068 glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1069 glass_pane.setVisible(true);
1070 }
1071 else {
1072 // Hide wait cursor.
1073 glass_pane.setVisible(false);
1074 glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1075 glass_pane.removeMouseListener(mouse_blocker_listener);
1076 }
1077 glass_pane = null;
1078 }
1079
1080 public void workflowUpdate(String raw, boolean state) {
1081 WorkflowUpdater task = new WorkflowUpdater(raw, state);
1082 SwingUtilities.invokeLater(task);
1083 task = null;
1084 }
1085
1086
1087 /**Overridden from JFrame so we can exit safely when window is closed (or destroyed).
1088 * @param event A <strong>WindowEvent</strong> containing information about the event that fired this call.
1089 */
1090 protected void processWindowEvent(WindowEvent event) {
1091 if(event.getID() == WindowEvent.WINDOW_CLOSING) {
1092 exit();
1093 }
1094 }
1095
1096
1097 /** 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.
1098 */
1099 private class MenuListenerImpl
1100 implements MenuListener {
1101 /** Called whenever a popup menu is hidden, but we don't care.
1102 * @param e Some <strong>MenuEvent</strong> that we could care less about.
1103 */
1104 public void menuCanceled(MenuEvent e) {
1105 }
1106 /** Called whenever a menu header (ie button) becomes unselected, but we don't care.
1107 * @param e Some <strong>MenuEvent</strong> that we could care less about.
1108 */
1109 public void menuDeselected(MenuEvent e) {
1110 }
1111 /** 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.
1112 * @param e The <strong>MenuEvent</strong> whose source is checked.
1113 */
1114 public void menuSelected(MenuEvent e) {
1115 if(e.getSource() == menu_bar.help) {
1116 if(menu_bar.help.isSelected()) {
1117 menu_bar.help.doClick(10);
1118 }
1119 }
1120 }
1121 }
1122
1123 private class TabUpdater
1124 implements Runnable {
1125 private boolean ready = false;
1126 private int download_pos = -1;
1127 private int enrich_pos = -1;
1128 private int design_pos = -1;
1129 private int create_pos = -1;
1130 private int format_pos = -1;
1131 private int export_pos = -1;
1132 private JTabbedPane tab_pane = null;
1133
1134 public TabUpdater(JTabbedPane tab_pane, boolean ready) {
1135 this.ready = ready;
1136 this.tab_pane = tab_pane;
1137 download_pos = tab_pane.indexOfComponent(download_pane);
1138 enrich_pos = tab_pane.indexOfComponent(enrich_pane);
1139 design_pos = tab_pane.indexOfComponent(design_pane);
1140 create_pos = tab_pane.indexOfComponent(create_pane);
1141 format_pos = tab_pane.indexOfComponent(format_pane);
1142 }
1143
1144 public void run()
1145 {
1146 if (download_pos != -1) {
1147 if (ready) {
1148 tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", false));
1149 }
1150 else {
1151 tab_pane.setEnabledAt(download_pos, Configuration.get("workflow.download", true));
1152 }
1153 }
1154 if (enrich_pos != -1) {
1155 tab_pane.setEnabledAt(enrich_pos, ready && Configuration.get("workflow.enrich", false));
1156 }
1157 if (design_pos != -1) {
1158 tab_pane.setEnabledAt(design_pos, ready && Configuration.get("workflow.design", false) && Configuration.getMode() > Configuration.ASSISTANT_MODE);
1159 }
1160 if (create_pos != -1) {
1161 tab_pane.setEnabledAt(create_pos, ready && Configuration.get("workflow.create", false));
1162 }
1163 if (format_pos != -1) {
1164 tab_pane.setEnabledAt(format_pos, ready && Configuration.get("workflow.format", false) && Configuration.getMode() > Configuration.ASSISTANT_MODE);
1165 }
1166 }
1167
1168 public void setReady(boolean ready) {
1169 this.ready = ready;
1170 }
1171 }
1172
1173 private class WorkflowUpdater
1174 implements Runnable {
1175 private boolean state;
1176 private String raw;
1177 public WorkflowUpdater(String raw, boolean state) {
1178 this.raw = raw;
1179 this.state = state;
1180 }
1181 public void run() {
1182 setTabEnabled(raw, state);
1183 }
1184 }
1185}
Note: See TracBrowser for help on using the repository browser.