source: other-projects/FileTransfer-WebSocketPair/testGXTWithGreenstone/src/org/greenstone/gatherer/gui/GUIManager.java@ 33053

Last change on this file since 33053 was 33053, checked in by ak19, 5 years ago

I still had some stuff of Nathan Kelly's (FileTransfer-WebSocketPair) sitting on my USB. Had already commited the Themes folder at the time, 2 years back. Not sure if he wanted this additional folder commited. But I didn't want to delete it and decided it will be better off on SVN. When we use his project, if we find we didn't need this test folder, we can remove it from svn then.

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