source: debug-testing/gli-ctrlC-issue/GUIManager.java@ 31935

Last change on this file since 31935 was 31736, checked in by ak19, 7 years ago

Creating a folder to add files that are in a convenient state for debugging problems we haven't resolved yet. And adding files for debugging the issue of launching GLI from DOS, but Ctrl-C being ineffective until you exit GLI, which is when the Ctrl-C finally registers.

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