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

Last change on this file since 30701 was 30701, checked in by ak19, 8 years ago

All the changes to get the new collectionConfig.xml Editor (ConfigFileEditor.java) to work.

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