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

Last change on this file since 24905 was 24905, checked in by ak19, 12 years ago

Now that quotes are necessary around collecthome in gsdlsite.cfg if there are spaces in the collecthome path, this needs to propagate into GLI: a dialog pops up on GLI exit if collecthome has changed. But collecthome has not changed if all that's been added is quotes around the collecthome variable as read from gsdlsite.cfg.

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