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

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

Changes to reinstate SwingUtilities.invokeLater() calls added for GUI testing so that it will still work with the remote GS server. Note however that new Gatherer() calls Gatherer.init() does a lot of GUI stuff too depending on circumstances (such as requestGLIServerURL(), missingGSDL(), missingExec(), popupFedoraInfo(), initCollectDirectoryPath() which calls nonStandardCollectHomeMessage()). But Gatherer.init() is not yet wrapped in an invokeLater(), so this will conflict with GLI GUI testing.

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