1   /*
2    *  Copyright (c) 1998-2004, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  Valentin Tablan 22/01/2001
10   *
11   *  $Id: MainFrame.java,v 1.201 2004/12/02 19:41:08 valyt Exp $
12   *
13   */
14  
15  package gate.gui;
16  
17  import java.awt.*;
18  import java.awt.event.*;
19  import java.beans.PropertyChangeEvent;
20  import java.beans.PropertyChangeListener;
21  import java.io.File;
22  import java.io.IOException;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.text.NumberFormat;
26  import java.util.*;
27  import java.util.List;
28  
29  import javax.swing.*;
30  import javax.swing.event.*;
31  import javax.swing.tree.*;
32  
33  import junit.framework.Assert;
34  
35  import com.ontotext.gate.vr.Gaze;
36  import com.ontotext.gate.vr.OntologyEditorImpl;
37  
38  import gate.*;
39  import gate.creole.*;
40  import gate.event.*;
41  import gate.persist.PersistenceException;
42  import gate.security.*;
43  import gate.swing.*;
44  import gate.util.*;
45  
46  /**
47   * The main Gate GUI frame.
48   */
49  public class MainFrame extends JFrame
50                      implements ProgressListener, StatusListener, CreoleListener{
51  
52    protected JMenuBar menuBar;
53    protected JSplitPane mainSplit;
54    protected JSplitPane leftSplit;
55    protected JLabel statusBar;
56    protected JProgressBar progressBar;
57    protected XJTabbedPane mainTabbedPane;
58    protected JScrollPane projectTreeScroll;
59    protected JScrollPane lowerScroll;
60  
61    /**
62     * Popup used for right click actions on the Applications node.
63     */
64    protected JPopupMenu appsPopup;
65    /**
66     * Popup used for right click actions on the Datastores node.
67     */
68    protected JPopupMenu dssPopup;
69    
70    /**
71     * Popup used for right click actions on the LRs node.
72     */
73    protected JPopupMenu lrsPopup;
74    
75    /**
76     * Popup used for right click actions on the PRs node.
77     */
78    protected JPopupMenu prsPopup;
79  
80    protected JCheckBoxMenuItem verboseModeItem;
81    
82    protected JTree resourcesTree;
83    protected JScrollPane resourcesTreeScroll;
84    protected DefaultTreeModel resourcesTreeModel;
85    protected DefaultMutableTreeNode resourcesTreeRoot;
86    protected DefaultMutableTreeNode applicationsRoot;
87    protected DefaultMutableTreeNode languageResourcesRoot;
88    protected DefaultMutableTreeNode processingResourcesRoot;
89    protected DefaultMutableTreeNode datastoresRoot;
90  
91  
92  
93  
94    protected Splash splash;
95    protected PluginManagerUI pluginManager;
96    protected LogArea logArea;
97    protected JScrollPane logScroll;
98    protected JToolBar toolbar;
99    static JFileChooser fileChooser;
100 
101   protected AppearanceDialog appearanceDialog;
102   protected OptionsDialog optionsDialog;
103   protected CartoonMinder animator;
104   protected TabHighlighter logHighlighter;
105   protected NewResourceDialog newResourceDialog;
106   protected WaitDialog waitDialog;
107 
108 
109   /**
110    * Holds all the icons used in the Gate GUI indexed by filename.
111    * This is needed so we do not need to decode the icon everytime
112    * we need it as that would use unecessary CPU time and memory.
113    * Access to this data is avaialable through the {@link #getIcon(String)}
114    * method.
115    */
116   protected static Map iconByName = new HashMap();
117 
118   /**
119    * A Map which holds listeners that are singletons (e.g. the status listener
120    * that updates the status bar on the main frame or the progress listener that
121    * updates the progress bar on the main frame).
122    * The keys used are the class names of the listener interface and the values
123    * are the actual listeners (e.g "gate.event.StatusListener" -> this).
124    */
125   private static java.util.Map listeners = new HashMap();
126   protected static java.util.Collection guiRoots = new ArrayList();
127 
128   private static JDialog guiLock = null;
129 
130   static public Icon getIcon(String filename){
131     Icon result = (Icon)iconByName.get(filename);
132     if(result == null){
133       result = new ImageIcon(MainFrame.class.
134               getResource(Files.getResourcePath() + "/img/" + filename));
135       iconByName.put(filename, result);
136     }
137     return result;
138   }
139 
140 
141 /*
142   static public MainFrame getInstance(){
143     if(instance == null) instance = new MainFrame();
144     return instance;
145   }
146 */
147 
148   static public JFileChooser getFileChooser(){
149     return fileChooser;
150   }
151 
152 
153   /**
154    * Selects a resource if loaded in the system and not invisible.
155    * @param res the resource to be selected.
156    */
157   public void select(Resource res){
158     //first find the handle for the resource
159     Handle handle = null;
160     //go through all the nodes
161     Enumeration nodesEnum = resourcesTreeRoot.breadthFirstEnumeration();
162     while(nodesEnum.hasMoreElements() && handle == null){
163       Object node = nodesEnum.nextElement();
164       if(node instanceof DefaultMutableTreeNode){
165         DefaultMutableTreeNode dmtNode = (DefaultMutableTreeNode)node;
166         if(dmtNode.getUserObject() instanceof Handle){
167           if(((Handle)dmtNode.getUserObject()).getTarget() == res){
168             handle = (Handle)dmtNode.getUserObject();
169           }
170         }
171       }
172     }
173 
174     //now select the handle if found
175     if(handle != null) select(handle);
176   }
177 
178   protected void select(Handle handle){
179     if(mainTabbedPane.indexOfComponent(handle.getLargeView()) != -1) {
180       //select
181       JComponent largeView = handle.getLargeView();
182       if(largeView != null) {
183         mainTabbedPane.setSelectedComponent(largeView);
184       }
185       JComponent smallView = handle.getSmallView();
186       if(smallView != null) {
187         lowerScroll.getViewport().setView(smallView);
188       } else {
189         lowerScroll.getViewport().setView(null);
190       }
191     } else {
192       //show
193       JComponent largeView = handle.getLargeView();
194       if(largeView != null) {
195         mainTabbedPane.addTab(handle.getTitle(), handle.getIcon(),
196                               largeView, handle.getTooltipText());
197         mainTabbedPane.setSelectedComponent(handle.getLargeView());
198       }
199       JComponent smallView = handle.getSmallView();
200       if(smallView != null) {
201         lowerScroll.getViewport().setView(smallView);
202       } else {
203         lowerScroll.getViewport().setView(null);
204       }
205     }
206   }//protected void select(ResourceHandle handle)
207 
208   public MainFrame() {
209     this(false);
210   } // MainFrame
211 
212   /**Construct the frame*/
213   public MainFrame(boolean isShellSlacGIU) {
214     guiRoots.add(this);
215     if(fileChooser == null){
216       fileChooser = new JFileChooser();
217       fileChooser.setMultiSelectionEnabled(false);
218       guiRoots.add(fileChooser);
219 
220       //the JFileChooser seems to size itself better once it's been added to a
221       //top level container such as a dialog.
222       JDialog dialog = new JDialog(this, "", true);
223       java.awt.Container contentPane = dialog.getContentPane();
224       contentPane.setLayout(new BorderLayout());
225       contentPane.add(fileChooser, BorderLayout.CENTER);
226       dialog.pack();
227       dialog.getContentPane().removeAll();
228       dialog.dispose();
229       dialog = null;
230     }
231     enableEvents(AWTEvent.WINDOW_EVENT_MASK);
232     initLocalData(isShellSlacGIU);
233     initGuiComponents(isShellSlacGIU);
234     initListeners(isShellSlacGIU);
235   } // MainFrame(boolean simple)
236 
237   protected void initLocalData(boolean isShellSlacGIU){
238     resourcesTreeRoot = new DefaultMutableTreeNode("GATE", true);
239     applicationsRoot = new DefaultMutableTreeNode("Applications", true);
240     if(isShellSlacGIU) {
241       languageResourcesRoot = new DefaultMutableTreeNode("Documents",
242                                                        true);
243     } else {
244       languageResourcesRoot = new DefaultMutableTreeNode("Language Resources",
245                                                        true);
246     } // if
247     processingResourcesRoot = new DefaultMutableTreeNode("Processing Resources",
248                                                          true);
249     datastoresRoot = new DefaultMutableTreeNode("Data stores", true);
250     resourcesTreeRoot.add(applicationsRoot);
251     resourcesTreeRoot.add(languageResourcesRoot);
252     resourcesTreeRoot.add(processingResourcesRoot);
253     resourcesTreeRoot.add(datastoresRoot);
254 
255     resourcesTreeModel = new ResourcesTreeModel(resourcesTreeRoot, true);
256   }
257 
258   protected void initGuiComponents(boolean isShellSlacGUI){
259     this.getContentPane().setLayout(new BorderLayout());
260 
261     Integer width =Gate.getUserConfig().getInt(GateConstants.MAIN_FRAME_WIDTH);
262     Integer height =Gate.getUserConfig().getInt(GateConstants.MAIN_FRAME_HEIGHT);
263     this.setSize(new Dimension(width == null ? 800 : width.intValue(),
264                                height == null ? 600 : height.intValue()));
265 
266     this.setIconImage(Toolkit.getDefaultToolkit().getImage(
267           MainFrame.class.getResource(Files.getResourcePath() + 
268                   "/img/gateIcon.gif")));
269     resourcesTree = new JTree(resourcesTreeModel){
270       public void updateUI(){
271         super.updateUI();
272         setRowHeight(0);
273       }
274     };
275 
276     resourcesTree.setEditable(true);
277     ResourcesTreeCellRenderer treeCellRenderer =
278                               new ResourcesTreeCellRenderer();
279     resourcesTree.setCellRenderer(treeCellRenderer);
280     resourcesTree.setCellEditor(new ResourcesTreeCellEditor(resourcesTree,
281                                                           treeCellRenderer));
282 
283     resourcesTree.setRowHeight(0);
284     //expand all nodes
285     resourcesTree.expandRow(0);
286     resourcesTree.expandRow(1);
287     resourcesTree.expandRow(2);
288     resourcesTree.expandRow(3);
289     resourcesTree.expandRow(4);
290     resourcesTree.getSelectionModel().
291                   setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION
292                                    );
293     resourcesTree.setEnabled(true);
294     ToolTipManager.sharedInstance().registerComponent(resourcesTree);
295     resourcesTreeScroll = new JScrollPane(resourcesTree);
296 
297     lowerScroll = new JScrollPane();
298     JPanel lowerPane = new JPanel();
299     lowerPane.setLayout(new OverlayLayout(lowerPane));
300 
301     JPanel animationPane = new JPanel();
302     animationPane.setOpaque(false);
303     animationPane.setLayout(new BoxLayout(animationPane, BoxLayout.X_AXIS));
304 
305     JPanel vBox = new JPanel();
306     vBox.setLayout(new BoxLayout(vBox, BoxLayout.Y_AXIS));
307     vBox.setOpaque(false);
308 
309     JPanel hBox = new JPanel();
310     hBox.setLayout(new BoxLayout(hBox, BoxLayout.X_AXIS));
311     hBox.setOpaque(false);
312 
313     vBox.add(Box.createVerticalGlue());
314     vBox.add(animationPane);
315 
316     hBox.add(vBox);
317     hBox.add(Box.createHorizontalGlue());
318 
319     lowerPane.add(hBox);
320     lowerPane.add(lowerScroll);
321 
322     animator = new CartoonMinder(animationPane);
323     Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
324                                animator,
325                                "MainFrame1");
326     thread.setPriority(Thread.MIN_PRIORITY);
327     thread.start();
328 
329     leftSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
330                                resourcesTreeScroll, lowerPane);
331 
332     leftSplit.setResizeWeight((double)0.7);
333 
334     // Create a new logArea and redirect the Out and Err output to it.
335     logArea = new LogArea();
336     logScroll = new JScrollPane(logArea);
337     // Out has been redirected to the logArea
338     
339     Out.prln("GATE " + Main.version + " build " + Main.build + " started at: " + 
340             new Date().toString());
341     mainTabbedPane = new XJTabbedPane(JTabbedPane.TOP);
342     mainTabbedPane.insertTab("Messages",null, logScroll, "GATE log", 0);
343 
344     logHighlighter = new TabHighlighter(mainTabbedPane, logScroll, Color.red);
345 
346 
347     mainSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
348                                leftSplit, mainTabbedPane);
349 
350     mainSplit.setDividerLocation(leftSplit.getPreferredSize().width + 10);
351     this.getContentPane().add(mainSplit, BorderLayout.CENTER);
352 
353     //status and progress bars
354     statusBar = new JLabel(" ");
355     statusBar.setPreferredSize(new Dimension(200,
356                                              statusBar.getPreferredSize().
357                                              height));
358 
359     UIManager.put("ProgressBar.cellSpacing", new Integer(0));
360     progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
361 //    progressBar.setBorder(BorderFactory.createEmptyBorder());
362     progressBar.setForeground(new Color(150, 75, 150));
363 //    progressBar.setBorderPainted(false);
364     progressBar.setStringPainted(false);
365     progressBar.setOrientation(JProgressBar.HORIZONTAL);
366 
367     JPanel southBox = new JPanel();
368     southBox.setLayout(new GridLayout(1,2));
369     southBox.setBorder(null);
370 
371     Box tempHBox = Box.createHorizontalBox();
372     tempHBox.add(Box.createHorizontalStrut(5));
373     tempHBox.add(statusBar);
374     southBox.add(tempHBox);
375     tempHBox = Box.createHorizontalBox();
376     tempHBox.add(progressBar);
377     tempHBox.add(Box.createHorizontalStrut(5));
378     southBox.add(tempHBox);
379 
380     this.getContentPane().add(southBox, BorderLayout.SOUTH);
381     progressBar.setVisible(false);
382 
383 
384     //extra stuff
385     newResourceDialog = new NewResourceDialog(
386       this, "Resource parameters", true
387     );
388     waitDialog = new WaitDialog(this, "");
389     //build the Help->About dialog
390     JPanel splashBox = new JPanel();
391     splashBox.setLayout(new BoxLayout(splashBox, BoxLayout.Y_AXIS));
392     splashBox.setBackground(Color.white);
393 
394     JLabel gifLbl = new JLabel(getIcon("gateSplash.gif"));
395     Box box = new Box(BoxLayout.X_AXIS);
396     box.add(Box.createHorizontalGlue());
397     box.add(gifLbl);
398     box.add(Box.createHorizontalGlue());
399     splashBox.add(box);
400 
401     gifLbl = new JLabel(getIcon("gateHeader.gif"));
402     box = new Box(BoxLayout.X_AXIS);
403     box.add(gifLbl);
404     box.add(Box.createHorizontalGlue());
405     splashBox.add(box);
406     splashBox.add(Box.createVerticalStrut(10));
407 
408     JLabel verLbl = new JLabel(
409       "<HTML><FONT color=\"blue\">Version <B>"
410       + Main.version + "</B></FONT>" +
411       ", <FONT color=\"red\">build <B>" + Main.build + "</B></FONT></HTML>"
412     );
413     box = new Box(BoxLayout.X_AXIS);
414     box.add(Box.createHorizontalGlue());
415     box.add(verLbl);
416 
417     splashBox.add(box);
418     splashBox.add(Box.createVerticalStrut(10));
419 
420     verLbl = new JLabel(
421 "<HTML>" +
422 "<B>Hamish Cunningham, Valentin Tablan, Kalina Bontcheva, Diana Maynard,</B>" +
423 "<BR>Niraj Aswani, Mike Dowman, Marin Dimitrov, Bobby Popov, Yaoyong Li, Akshay Java," +
424 "<BR>Wim Peters, Mark Greenwood, Angus Roberts, Andrey Shafirin, Horacio Saggion," +
425 //"<BR>XXX," +
426 //"<BR>XXX," +
427 "<BR>Cristian Ursu, Atanas Kiryakov, Angel Kirilov, Damyan Ognyanoff, Dimitar Manov," +
428 "<BR>Milena Yankova, Oana Hamza, Robert Gaizauskas, Mark Hepple, Mark Leisher," +
429 "<BR>Fang Huang, Kevin Humphreys, Yorick Wilks." +
430 "<P><B>JVM version</B>: " + System.getProperty("java.version") +
431 " from " + System.getProperty("java.vendor")
432     );
433     box = new Box(BoxLayout.X_AXIS);
434     box.add(verLbl);
435     box.add(Box.createHorizontalGlue());
436 
437     splashBox.add(box);
438 
439     JButton okBtn = new JButton("OK");
440     okBtn.addActionListener(new ActionListener() {
441       public void actionPerformed(ActionEvent e) {
442         splash.setVisible(false);
443       }
444     });
445     okBtn.setBackground(Color.white);
446     box = new Box(BoxLayout.X_AXIS);
447     box.add(Box.createHorizontalGlue());
448     box.add(okBtn);
449     box.add(Box.createHorizontalGlue());
450 
451     splashBox.add(Box.createVerticalStrut(10));
452     splashBox.add(box);
453     splashBox.add(Box.createVerticalStrut(10));
454     splash = new Splash(this, splashBox);
455 
456 
457     //MENUS
458     menuBar = new JMenuBar();
459 
460 
461     JMenu fileMenu = new XJMenu("File");
462 
463     LiveMenu newAPPMenu = new LiveMenu(LiveMenu.APP);
464     newAPPMenu.setText("New application");
465     newAPPMenu.setIcon(getIcon("applications.gif"));
466     fileMenu.add(newAPPMenu);
467     
468     LiveMenu newLRMenu = new LiveMenu(LiveMenu.LR);
469     newLRMenu.setText("New language resource");
470     newLRMenu.setIcon(getIcon("lrs.gif"));
471     fileMenu.add(newLRMenu);
472     
473     LiveMenu newPRMenu = new LiveMenu(LiveMenu.PR);
474     newPRMenu.setText("New processing resource");
475     newPRMenu.setIcon(getIcon("prs.gif"));
476     fileMenu.add(newPRMenu);
477 
478     JMenu dsMenu = new JMenu("Datastores");
479     dsMenu.setIcon(getIcon("dss.gif"));
480     dsMenu.add(new XJMenuItem(new NewDSAction(), this));
481     dsMenu.add(new XJMenuItem(new OpenDSAction(), this));
482     fileMenu.add(dsMenu);
483     
484     fileMenu.addSeparator();
485     fileMenu.add(new XJMenuItem(new LoadResourceFromFileAction(), this));
486     
487     fileMenu.addSeparator();
488     JMenu loadANNIEMenu = new JMenu("Load ANNIE system");
489     loadANNIEMenu.setIcon(getIcon("application.gif"));
490     loadANNIEMenu.add(new XJMenuItem(new LoadANNIEWithDefaultsAction(), this));
491     loadANNIEMenu.add(new XJMenuItem(new LoadANNIEWithoutDefaultsAction(), this));
492     fileMenu.add(loadANNIEMenu);
493     
494 //    fileMenu.add(new XJMenuItem(new LoadCreoleRepositoryAction(), this));
495     
496     fileMenu.add(new XJMenuItem(new ManagePluginsAction(), this));
497     fileMenu.addSeparator();
498 
499     fileMenu.add(new XJMenuItem(new ExitGateAction(), this));
500     menuBar.add(fileMenu);
501 
502 
503 
504     JMenu optionsMenu = new JMenu("Options");
505 
506     optionsDialog = new OptionsDialog(MainFrame.this);
507     optionsMenu.add(new XJMenuItem(new AbstractAction("Configuration"){
508       {
509         putValue(SHORT_DESCRIPTION, "Edit gate options");
510       }
511       public void actionPerformed(ActionEvent evt){
512         optionsDialog.show();
513       }
514     }, this));
515 
516 
517     JMenu imMenu = null;
518     List installedLocales = new ArrayList();
519     try{
520       //if this fails guk is not present
521       Class.forName("guk.im.GateIMDescriptor");
522       //add the Gate input methods
523       installedLocales.addAll(Arrays.asList(new guk.im.GateIMDescriptor().
524                                             getAvailableLocales()));
525     }catch(Exception e){
526       //something happened; most probably guk not present.
527       //just drop it, is not vital.
528     }
529     try{
530       //add the MPI IMs
531       //if this fails mpi IM is not present
532       Class.forName("mpi.alt.java.awt.im.spi.lookup.LookupDescriptor");
533 
534       installedLocales.addAll(Arrays.asList(
535             new mpi.alt.java.awt.im.spi.lookup.LookupDescriptor().
536             getAvailableLocales()));
537     }catch(Exception e){
538       //something happened; most probably MPI not present.
539       //just drop it, is not vital.
540     }
541 
542     Collections.sort(installedLocales, new Comparator(){
543       public int compare(Object o1, Object o2){
544         return ((Locale)o1).getDisplayName().compareTo(((Locale)o2).getDisplayName());
545       }
546     });
547     JMenuItem item;
548     if(!installedLocales.isEmpty()){
549       imMenu = new XJMenu("Input methods");
550       ButtonGroup bg = new ButtonGroup();
551       item = new LocaleSelectorMenuItem();
552       imMenu.add(item);
553       item.setSelected(true);
554       imMenu.addSeparator();
555       bg.add(item);
556       for(int i = 0; i < installedLocales.size(); i++){
557         Locale locale = (Locale)installedLocales.get(i);
558         item = new LocaleSelectorMenuItem(locale);
559         imMenu.add(item);
560         bg.add(item);
561       }
562     }
563     if(imMenu != null) optionsMenu.add(imMenu);
564 
565     menuBar.add(optionsMenu);
566 
567     JMenu toolsMenu = new XJMenu("Tools");
568     toolsMenu.add(new NewAnnotDiffAction());
569 //    toolsMenu.add(newCorpusAnnotDiffAction);
570     toolsMenu.add(new NewBootStrapAction());
571     //temporarily disabled till the evaluation tools are made to run within
572     //the GUI
573     JMenu corpusEvalMenu = new JMenu("Corpus Benchmark Tools");
574     corpusEvalMenu.setIcon(getIcon("annDiff.gif"));
575     toolsMenu.add(corpusEvalMenu);
576     corpusEvalMenu.add(new NewCorpusEvalAction());
577     corpusEvalMenu.addSeparator();
578     corpusEvalMenu.add(new GenerateStoredCorpusEvalAction());
579     corpusEvalMenu.addSeparator();
580     corpusEvalMenu.add(new StoredMarkedCorpusEvalAction());
581     corpusEvalMenu.add(new CleanMarkedCorpusEvalAction());
582     corpusEvalMenu.addSeparator();
583     verboseModeItem =
584       new JCheckBoxMenuItem(new VerboseModeCorpusEvalToolAction());
585     corpusEvalMenu.add(verboseModeItem);
586 //    JCheckBoxMenuItem datastoreModeItem =
587 //      new JCheckBoxMenuItem(datastoreModeCorpusEvalToolAction);
588 //    corpusEvalMenu.add(datastoreModeItem);
589     toolsMenu.add(
590       new AbstractAction("Unicode editor", getIcon("unicode.gif")){
591       public void actionPerformed(ActionEvent evt){
592         new guk.Editor();
593       }
594     });
595 
596     /*add the ontology editor to the tools menu
597     ontotext.bp */
598     toolsMenu.add(new NewOntologyEditorAction());
599 
600     if(Gate.isEnableJapeDebug()) {
601       // by Shafirin Andrey start
602       toolsMenu.add(
603           new AbstractAction("JAPE Debugger", getIcon("application.gif")) {
604         public void actionPerformed(ActionEvent evt) {
605           System.out.println("Creating Jape Debugger");
606           new debugger.JapeDebugger();
607         }
608       });
609       // by Shafirin Andrey end
610     }
611 
612     menuBar.add(toolsMenu);
613 
614     JMenu helpMenu = new JMenu("Help");
615 //    helpMenu.add(new HelpUserGuideAction());
616     helpMenu.add(new HelpAboutAction());
617     menuBar.add(helpMenu);
618 
619     this.setJMenuBar(menuBar);
620 
621     //popups
622     appsPopup = new XJPopupMenu();
623     LiveMenu appsMenu = new LiveMenu(LiveMenu.APP);
624     appsMenu.setText("New");
625     appsPopup.add(appsMenu);
626     appsPopup.addSeparator();
627     appsPopup.add(new XJMenuItem(new LoadResourceFromFileAction(), this));
628     guiRoots.add(appsMenu);
629     guiRoots.add(appsPopup);
630 
631     lrsPopup = new XJPopupMenu();
632     LiveMenu lrsMenu = new LiveMenu(LiveMenu.LR);
633     lrsMenu.setText("New");
634     lrsPopup.add(lrsMenu);
635     guiRoots.add(lrsPopup);
636     guiRoots.add(lrsMenu);
637 
638     prsPopup = new XJPopupMenu();
639     LiveMenu prsMenu = new LiveMenu(LiveMenu.PR);
640     prsMenu.setText("New");
641     prsPopup.add(prsMenu);
642     guiRoots.add(prsMenu);
643     guiRoots.add(prsPopup);
644 
645     dssPopup = new XJPopupMenu();
646     dssPopup.add(new NewDSAction());
647     dssPopup.add(new OpenDSAction());
648     guiRoots.add(dssPopup);
649     
650     //TOOLBAR
651     toolbar = new JToolBar(JToolBar.HORIZONTAL);
652     toolbar.setFloatable(false);
653     toolbar.add(new LoadResourceFromFileAction());
654     JMenuBar smallMenuBar = new JMenuBar();
655     smallMenuBar.setBorderPainted(false);
656     smallMenuBar.setAlignmentY(JComponent.CENTER_ALIGNMENT);
657     JMenu annieMenu = new JMenu();
658     annieMenu.setIcon(getIcon("application.gif"));
659     annieMenu.setToolTipText("Load ANNIE System");
660     annieMenu.add(new LoadANNIEWithDefaultsAction());
661     annieMenu.add(new LoadANNIEWithoutDefaultsAction());
662     smallMenuBar.add(annieMenu);
663     toolbar.add(smallMenuBar);
664     toolbar.addSeparator();
665     smallMenuBar = new JMenuBar();
666     smallMenuBar.setBorderPainted(false);
667     smallMenuBar.setAlignmentY(JComponent.CENTER_ALIGNMENT);
668     LiveMenu tbNewLRMenu = new LiveMenu(LiveMenu.LR);
669     tbNewLRMenu.setToolTipText("New Language Resource");
670     tbNewLRMenu.setIcon(getIcon("lrs.gif"));
671     smallMenuBar.add(tbNewLRMenu);
672     toolbar.add(smallMenuBar);
673     
674     smallMenuBar = new JMenuBar();
675     smallMenuBar.setBorderPainted(false);
676     smallMenuBar.setAlignmentY(JComponent.CENTER_ALIGNMENT);
677     LiveMenu tbNewPRMenu = new LiveMenu(LiveMenu.PR);
678     tbNewPRMenu.setToolTipText("New Processing Resource");
679     tbNewPRMenu.setIcon(getIcon("prs.gif"));
680     smallMenuBar.add(tbNewPRMenu);
681     toolbar.add(smallMenuBar);
682     
683     smallMenuBar = new JMenuBar();
684     smallMenuBar.setBorderPainted(false);
685     smallMenuBar.setAlignmentY(JComponent.CENTER_ALIGNMENT);
686     LiveMenu tbNewAppMenu = new LiveMenu(LiveMenu.APP);
687     tbNewAppMenu.setToolTipText("New Application");
688     tbNewAppMenu.setIcon(getIcon("applications.gif"));
689     smallMenuBar.add(tbNewAppMenu);
690     toolbar.add(smallMenuBar);
691     
692     smallMenuBar = new JMenuBar();
693     smallMenuBar.setBorderPainted(false);
694     smallMenuBar.setAlignmentY(JComponent.CENTER_ALIGNMENT);
695     JMenu tbDsMenu = new JMenu();
696     tbDsMenu.setToolTipText("Datastores");
697     tbDsMenu.setIcon(getIcon("dss.gif"));
698     tbDsMenu.add(new NewDSAction());
699     tbDsMenu.add(new OpenDSAction());
700     smallMenuBar.add(tbDsMenu);
701     toolbar.add(smallMenuBar);
702     
703     toolbar.addSeparator();
704     toolbar.add(new ManagePluginsAction());
705     toolbar.addSeparator();
706     toolbar.add(new NewAnnotDiffAction());
707     
708     toolbar.add(Box.createGlue());
709     this.getContentPane().add(toolbar, BorderLayout.NORTH);    
710   }
711 
712   protected void initListeners(boolean isShellSlacGIU){
713     Gate.getCreoleRegister().addCreoleListener(this);
714 
715     resourcesTree.addMouseListener(new MouseAdapter() {
716       public void mouseClicked(MouseEvent e) {
717         //where inside the tree?
718         int x = e.getX();
719         int y = e.getY();
720         TreePath path = resourcesTree.getPathForLocation(x, y);
721         JPopupMenu popup = null;
722         Handle handle = null;
723         if(path != null){
724           Object value = path.getLastPathComponent();
725           if(value == resourcesTreeRoot){
726           } else if(value == applicationsRoot){
727             popup = appsPopup;
728           } else if(value == languageResourcesRoot){
729             popup = lrsPopup;
730           } else if(value == processingResourcesRoot){
731             popup = prsPopup;
732           } else if(value == datastoresRoot){
733             popup = dssPopup;
734           }else{
735             value = ((DefaultMutableTreeNode)value).getUserObject();
736             if(value instanceof Handle){
737               handle = (Handle)value;
738               popup = handle.getPopup();
739             }
740           }
741         }
742         if (SwingUtilities.isRightMouseButton(e)) {
743           if(resourcesTree.getSelectionCount() > 1){
744             //multiple selection in tree-> show a popup for delete all
745             popup = new XJPopupMenu();
746             popup.add(new XJMenuItem(new CloseSelectedResourcesAction(),
747                       MainFrame.this));
748             popup.show(resourcesTree, e.getX(), e.getY());
749           }else if(popup != null){
750             if(handle != null){
751               // Create a CloseViewAction and a menu item based on it
752               CloseViewAction cva = new CloseViewAction(handle);
753               XJMenuItem menuItem = new XJMenuItem(cva, MainFrame.this);
754               // Add an accelerator ATL+F4 for this action
755               menuItem.setAccelerator(
756                     KeyStroke.getKeyStroke(KeyEvent.VK_H,
757                                            ActionEvent.CTRL_MASK));
758               popup.insert(menuItem, 1);
759               popup.insert(new JPopupMenu.Separator(), 2);
760 
761               popup.insert(new XJMenuItem(new RenameResourceAction(path),
762                                           MainFrame.this), 3);
763 
764               // Put the action command in the component's action map
765               if (handle.getLargeView() != null){
766                 handle.getLargeView().getActionMap().
767                                       put("Hide current view",cva);
768               }
769             }
770 
771 
772             popup.show(resourcesTree, e.getX(), e.getY());
773           }
774         } else if(SwingUtilities.isLeftMouseButton(e)) {
775           if(e.getClickCount() == 2 && handle != null) {
776             //double click - show the resource
777             select(handle);
778           }
779         }
780       }
781 
782       public void mousePressed(MouseEvent e) {
783       }
784 
785       public void mouseReleased(MouseEvent e) {
786       }
787 
788       public void mouseEntered(MouseEvent e) {
789       }
790 
791       public void mouseExited(MouseEvent e) {
792       }
793     });
794 
795     // Add the keyboard listeners for CTRL+F4 and ALT+F4
796     this.addKeyListener(new KeyAdapter() {
797       public void keyTyped(KeyEvent e) {
798       }
799 
800       public void keyPressed(KeyEvent e) {
801         // If Ctrl+F4 was pressed then close the active resource
802         if (e.isControlDown() && e.getKeyCode()==KeyEvent.VK_F4){
803           JComponent resource = (JComponent)
804                                         mainTabbedPane.getSelectedComponent();
805           if (resource != null){
806             Action act = resource.getActionMap().get("Close resource");
807             if (act != null)
808               act.actionPerformed(null);
809           }// End if
810         }// End if
811         // If CTRL+H was pressed then hide the active view.
812         if (e.isControlDown() && e.getKeyCode()==KeyEvent.VK_H){
813           JComponent resource = (JComponent)
814                                         mainTabbedPane.getSelectedComponent();
815           if (resource != null){
816             Action act = resource.getActionMap().get("Hide current view");
817             if (act != null)
818               act.actionPerformed(null);
819           }// End if
820         }// End if
821         // If CTRL+X was pressed then save as XML
822         if (e.isControlDown() && e.getKeyCode()==KeyEvent.VK_X){
823           JComponent resource = (JComponent)
824                                         mainTabbedPane.getSelectedComponent();
825           if (resource != null){
826             Action act = resource.getActionMap().get("Save As XML");
827             if (act != null)
828               act.actionPerformed(null);
829           }// End if
830         }// End if
831       }// End keyPressed();
832 
833       public void keyReleased(KeyEvent e) {
834       }
835     });
836 
837     mainTabbedPane.getModel().addChangeListener(new ChangeListener() {
838       public void stateChanged(ChangeEvent e) {
839         JComponent largeView = (JComponent)mainTabbedPane.getSelectedComponent();
840         Enumeration nodesEnum = resourcesTreeRoot.preorderEnumeration();
841         boolean done = false;
842         DefaultMutableTreeNode node = resourcesTreeRoot;
843         while(!done && nodesEnum.hasMoreElements()){
844           node = (DefaultMutableTreeNode)nodesEnum.nextElement();
845           done = node.getUserObject() instanceof Handle &&
846                  ((Handle)node.getUserObject()).getLargeView()
847                   == largeView;
848         }
849         if(done){
850           select((Handle)node.getUserObject());
851         }else{
852           //the selected item is not a resource (maybe the log area?)
853           lowerScroll.getViewport().setView(null);
854         }
855       }
856     });
857 
858     mainTabbedPane.addMouseListener(new MouseAdapter() {
859       public void mouseClicked(MouseEvent e) {
860         if(SwingUtilities.isRightMouseButton(e)){
861           int index = mainTabbedPane.getIndexAt(e.getPoint());
862           if(index != -1){
863             JComponent view = (JComponent)mainTabbedPane.getComponentAt(index);
864             Enumeration nodesEnum = resourcesTreeRoot.preorderEnumeration();
865             boolean done = false;
866             DefaultMutableTreeNode node = resourcesTreeRoot;
867             while(!done && nodesEnum.hasMoreElements()){
868               node = (DefaultMutableTreeNode)nodesEnum.nextElement();
869               done = node.getUserObject() instanceof Handle &&
870                      ((Handle)node.getUserObject()).getLargeView()
871                       == view;
872             }
873             if(done){
874               Handle handle = (Handle)node.getUserObject();
875               JPopupMenu popup = handle.getPopup();
876               popup.show(mainTabbedPane, e.getX(), e.getY());
877             }
878           }
879         }
880       }
881 
882       public void mousePressed(MouseEvent e) {
883       }
884 
885       public void mouseReleased(MouseEvent e) {
886       }
887 
888       public void mouseEntered(MouseEvent e) {
889       }
890 
891       public void mouseExited(MouseEvent e) {
892       }
893     });
894 
895     addComponentListener(new ComponentAdapter() {
896       public void componentHidden(ComponentEvent e) {
897 
898       }
899 
900       public void componentMoved(ComponentEvent e) {
901       }
902 
903       public void componentResized(ComponentEvent e) {
904       }
905 
906       public void componentShown(ComponentEvent e) {
907         leftSplit.setDividerLocation((double)0.7);
908       }
909     });
910 
911     if(isShellSlacGIU) {
912       mainSplit.setDividerSize(0);
913       mainSplit.getTopComponent().setVisible(false);
914       mainSplit.getTopComponent().addComponentListener(new ComponentAdapter() {
915         public void componentHidden(ComponentEvent e) {
916         }
917         public void componentMoved(ComponentEvent e) {
918           mainSplit.setDividerLocation(0);
919         }
920         public void componentResized(ComponentEvent e) {
921           mainSplit.setDividerLocation(0);
922         }
923         public void componentShown(ComponentEvent e) {
924           mainSplit.setDividerLocation(0);
925         }
926       });
927     } // if
928 
929     //blink the messages tab when new information is displayed
930     logArea.getDocument().addDocumentListener(new javax.swing.event.DocumentListener(){
931       public void insertUpdate(javax.swing.event.DocumentEvent e){
932         changeOccured();
933       }
934       public void removeUpdate(javax.swing.event.DocumentEvent e){
935         changeOccured();
936       }
937       public void changedUpdate(javax.swing.event.DocumentEvent e){
938         changeOccured();
939       }
940       protected void changeOccured(){
941         logHighlighter.highlight();
942       }
943     });
944 
945     logArea.addPropertyChangeListener("document", new PropertyChangeListener(){
946       public void propertyChange(PropertyChangeEvent evt){
947         //add the document listener
948         logArea.getDocument().addDocumentListener(new javax.swing.event.DocumentListener(){
949           public void insertUpdate(javax.swing.event.DocumentEvent e){
950             changeOccured();
951           }
952           public void removeUpdate(javax.swing.event.DocumentEvent e){
953             changeOccured();
954           }
955           public void changedUpdate(javax.swing.event.DocumentEvent e){
956             changeOccured();
957           }
958           protected void changeOccured(){
959             logHighlighter.highlight();
960           }
961         });
962       }
963     });
964 
965 
966    listeners.put("gate.event.StatusListener", MainFrame.this);
967    listeners.put("gate.event.ProgressListener", MainFrame.this);
968   }//protected void initListeners()
969 
970   public void progressChanged(int i) {
971     //progressBar.setStringPainted(true);
972     int oldValue = progressBar.getValue();
973 //    if((!stopAction.isEnabled()) &&
974 //       (Gate.getExecutable() != null)){
975 //      stopAction.setEnabled(true);
976 //      SwingUtilities.invokeLater(new Runnable(){
977 //        public void run(){
978 //          southBox.add(stopBtn, 0);
979 //        }
980 //      });
981 //    }
982     if(!animator.isActive()) animator.activate();
983     if(oldValue != i){
984       SwingUtilities.invokeLater(new ProgressBarUpdater(i));
985     }
986   }
987 
988   /**
989    * Called when the process is finished.
990    *
991    */
992   public void processFinished() {
993     //progressBar.setStringPainted(false);
994 //    if(stopAction.isEnabled()){
995 //      stopAction.setEnabled(false);
996 //      SwingUtilities.invokeLater(new Runnable(){
997 //        public void run(){
998 //          southBox.remove(stopBtn);
999 //        }
1000//      });
1001//    }
1002    SwingUtilities.invokeLater(new ProgressBarUpdater(0));
1003    animator.deactivate();
1004  }
1005
1006  public void statusChanged(String text) {
1007    SwingUtilities.invokeLater(new StatusBarUpdater(text));
1008  }
1009
1010  public void resourceLoaded(CreoleEvent e) {
1011    Resource res = e.getResource();
1012    if(Gate.getHiddenAttribute(res.getFeatures()) || 
1013            res instanceof VisualResource) return;
1014    NameBearerHandle handle = new NameBearerHandle(res, MainFrame.this);
1015    DefaultMutableTreeNode node = new DefaultMutableTreeNode(handle, false);
1016    if(res instanceof ProcessingResource){
1017      resourcesTreeModel.insertNodeInto(node, processingResourcesRoot, 0);
1018    }else if(res instanceof LanguageResource){
1019      resourcesTreeModel.insertNodeInto(node, languageResourcesRoot, 0);
1020    }else if(res instanceof Controller){
1021      resourcesTreeModel.insertNodeInto(node, applicationsRoot, 0);
1022    }
1023
1024    handle.addProgressListener(MainFrame.this);
1025    handle.addStatusListener(MainFrame.this);
1026
1027//    JPopupMenu popup = handle.getPopup();
1028//
1029//    // Create a CloseViewAction and a menu item based on it
1030//    CloseViewAction cva = new CloseViewAction(handle);
1031//    XJMenuItem menuItem = new XJMenuItem(cva, this);
1032//    // Add an accelerator ATL+F4 for this action
1033//    menuItem.setAccelerator(KeyStroke.getKeyStroke(
1034//                                      KeyEvent.VK_H, ActionEvent.CTRL_MASK));
1035//    popup.insert(menuItem, 1);
1036//    popup.insert(new JPopupMenu.Separator(), 2);
1037//
1038//    popup.insert(new XJMenuItem(
1039//                  new RenameResourceAction(
1040//                      new TreePath(resourcesTreeModel.getPathToRoot(node))),
1041//                  MainFrame.this) , 3);
1042//
1043//    // Put the action command in the component's action map
1044//    if (handle.getLargeView() != null)
1045//      handle.getLargeView().getActionMap().put("Hide current view",cva);
1046//
1047  }// resourceLoaded();
1048
1049
1050  public void resourceUnloaded(CreoleEvent e) {
1051    Resource res = e.getResource();
1052    if(Gate.getHiddenAttribute(res.getFeatures())) return;
1053    DefaultMutableTreeNode node;
1054    DefaultMutableTreeNode parent = null;
1055    if(res instanceof ProcessingResource){
1056      parent = processingResourcesRoot;
1057    }else if(res instanceof LanguageResource){
1058      parent = languageResourcesRoot;
1059    }else if(res instanceof Controller){
1060      parent = applicationsRoot;
1061    }
1062    if(parent != null){
1063      Enumeration children = parent.children();
1064      while(children.hasMoreElements()){
1065        node = (DefaultMutableTreeNode)children.nextElement();
1066        if(((NameBearerHandle)node.getUserObject()).getTarget() == res){
1067          resourcesTreeModel.removeNodeFromParent(node);
1068          Handle handle = (Handle)node.getUserObject();
1069          if(mainTabbedPane.indexOfComponent(handle.getLargeView()) != -1){
1070            mainTabbedPane.remove(handle.getLargeView());
1071          }
1072          if(lowerScroll.getViewport().getView() == handle.getSmallView()){
1073            lowerScroll.getViewport().setView(null);
1074          }
1075          return;
1076        }
1077      }
1078    }
1079  }
1080
1081  /**Called when a {@link gate.DataStore} has been opened*/
1082  public void datastoreOpened(CreoleEvent e){
1083    DataStore ds = e.getDatastore();
1084
1085    ds.setName(ds.getStorageUrl());
1086
1087    NameBearerHandle handle = new NameBearerHandle(ds, MainFrame.this);
1088    DefaultMutableTreeNode node = new DefaultMutableTreeNode(handle, false);
1089    resourcesTreeModel.insertNodeInto(node, datastoresRoot, 0);
1090    handle.addProgressListener(MainFrame.this);
1091    handle.addStatusListener(MainFrame.this);
1092
1093//    JPopupMenu popup = handle.getPopup();
1094//    popup.addSeparator();
1095//    // Create a CloseViewAction and a menu item based on it
1096//    CloseViewAction cva = new CloseViewAction(handle);
1097//    XJMenuItem menuItem = new XJMenuItem(cva, this);
1098//    // Add an accelerator ATL+F4 for this action
1099//    menuItem.setAccelerator(KeyStroke.getKeyStroke(
1100//                                      KeyEvent.VK_H, ActionEvent.CTRL_MASK));
1101//    popup.add(menuItem);
1102//    // Put the action command in the component's action map
1103//    if (handle.getLargeView() != null)
1104//      handle.getLargeView().getActionMap().put("Hide current view",cva);
1105  }// datastoreOpened();
1106
1107  /**Called when a {@link gate.DataStore} has been created*/
1108  public void datastoreCreated(CreoleEvent e){
1109    datastoreOpened(e);
1110  }
1111
1112  /**Called when a {@link gate.DataStore} has been closed*/
1113  public void datastoreClosed(CreoleEvent e){
1114    DataStore ds = e.getDatastore();
1115    DefaultMutableTreeNode node;
1116    DefaultMutableTreeNode parent = datastoresRoot;
1117    if(parent != null){
1118      Enumeration children = parent.children();
1119      while(children.hasMoreElements()){
1120        node = (DefaultMutableTreeNode)children.nextElement();
1121        if(((NameBearerHandle)node.getUserObject()).
1122            getTarget() == ds){
1123          resourcesTreeModel.removeNodeFromParent(node);
1124          NameBearerHandle handle = (NameBearerHandle)
1125                                          node.getUserObject();
1126          if(mainTabbedPane.indexOfComponent(handle.getLargeView()) != -1){
1127            mainTabbedPane.remove(handle.getLargeView());
1128          }
1129          if(lowerScroll.getViewport().getView() == handle.getSmallView()){
1130            lowerScroll.getViewport().setView(null);
1131          }
1132          return;
1133        }
1134      }
1135    }
1136  }
1137
1138  public void resourceRenamed(Resource resource, String oldName,
1139                              String newName){
1140    for(int i = 0; i < mainTabbedPane.getTabCount(); i++){
1141      if(mainTabbedPane.getTitleAt(i).equals(oldName)){
1142        mainTabbedPane.setTitleAt(i, newName);
1143
1144        return;
1145      }
1146    }
1147  }
1148
1149  /**
1150   * Overridden so we can exit when window is closed
1151   */
1152  protected void processWindowEvent(WindowEvent e) {
1153    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
1154      new ExitGateAction().actionPerformed(null);
1155    }
1156    super.processWindowEvent(e);
1157  }// processWindowEvent(WindowEvent e)
1158
1159  /**
1160   * Returns the listeners map, a map that holds all the listeners that are
1161   * singletons (e.g. the status listener that updates the status bar on the
1162   * main frame or the progress listener that updates the progress bar on the
1163   * main frame).
1164   * The keys used are the class names of the listener interface and the values
1165   * are the actual listeners (e.g "gate.event.StatusListener" -> this).
1166   * The returned map is the actual data member used to store the listeners so
1167   * any changes in this map will be visible to everyone.
1168   */
1169  public static java.util.Map getListeners() {
1170    return listeners;
1171  }
1172
1173  public static java.util.Collection getGuiRoots() {
1174    return guiRoots;
1175  }
1176
1177  /**
1178   * This method will lock all input to the gui by means of a modal dialog.
1179   * If Gate is not currently running in GUI mode this call will be ignored.
1180   * A call to this method while the GUI is locked will cause the GUI to be
1181   * unlocked and then locked again with the new message.
1182   * If a message is provided it will show in the dialog.
1183   * @param message the message to be displayed while the GUI is locked
1184   */
1185  public synchronized static void lockGUI(final String message){
1186    //check whether GUI is up
1187    if(getGuiRoots() == null || getGuiRoots().isEmpty()) return;
1188    //if the GUI is locked unlock it so we can show the new message
1189    unlockGUI();
1190
1191    //build the dialog contents
1192    Object[] options = new Object[]{new JButton(new StopAction())};
1193    JOptionPane pane = new JOptionPane(message, JOptionPane.WARNING_MESSAGE,
1194                                       JOptionPane.DEFAULT_OPTION,
1195                                       null, options, null);
1196
1197    //build the dialog
1198    Component parentComp = (Component)((ArrayList)getGuiRoots()).get(0);
1199    JDialog dialog;
1200    Window parentWindow;
1201    if(parentComp instanceof Window) parentWindow = (Window)parentComp;
1202    else parentWindow = SwingUtilities.getWindowAncestor(parentComp);
1203    if(parentWindow instanceof Frame){
1204      dialog = new JDialog((Frame)parentWindow, "Please wait", true){
1205        protected void processWindowEvent(WindowEvent e) {
1206          if (e.getID() == WindowEvent.WINDOW_CLOSING) {
1207            getToolkit().beep();
1208          }
1209        }
1210      };
1211    }else if(parentWindow instanceof Dialog){
1212      dialog = new JDialog((Dialog)parentWindow, "Please wait", true){
1213        protected void processWindowEvent(WindowEvent e) {
1214          if (e.getID() == WindowEvent.WINDOW_CLOSING) {
1215            getToolkit().beep();
1216          }
1217        }
1218      };
1219    }else{
1220      dialog = new JDialog(JOptionPane.getRootFrame(), "Please wait", true){
1221        protected void processWindowEvent(WindowEvent e) {
1222          if (e.getID() == WindowEvent.WINDOW_CLOSING) {
1223            getToolkit().beep();
1224          }
1225        }
1226      };
1227    }
1228    dialog.getContentPane().setLayout(new BorderLayout());
1229    dialog.getContentPane().add(pane, BorderLayout.CENTER);
1230    dialog.pack();
1231    dialog.setLocationRelativeTo(parentComp);
1232    dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
1233    guiLock = dialog;
1234
1235    //this call needs to return so we'll show the dialog from a different thread
1236    //the Swing thread sounds good for that
1237    SwingUtilities.invokeLater(new Runnable(){
1238      public void run(){
1239        guiLock.setVisible(true);
1240      }
1241    });
1242
1243    //this call should not return until the dialog is up to ensure proper
1244    //sequentiality for lock - unlock calls
1245    while(!guiLock.isShowing()){
1246      try{
1247        Thread.sleep(100);
1248      }catch(InterruptedException ie){}
1249    }
1250  }
1251
1252  public synchronized static void unlockGUI(){
1253    //check whether GUI is up
1254    if(getGuiRoots() == null || getGuiRoots().isEmpty()) return;
1255
1256    if(guiLock != null) guiLock.setVisible(false);
1257    guiLock = null;
1258  }
1259
1260  /** Flag to protect Frame title to be changed */
1261  private boolean titleChangable = false;
1262
1263  public void setTitleChangable(boolean isChangable) {
1264    titleChangable = isChangable;
1265  } // setTitleChangable(boolean isChangable)
1266
1267  /** Override to avoid Protege to change Frame title */
1268  public synchronized void setTitle(String title) {
1269    if(titleChangable) {
1270      super.setTitle(title);
1271    } // if
1272  } // setTitle(String title)
1273
1274
1275
1276  /** Method is used in NewDSAction */
1277  protected DataStore createSerialDataStore() {
1278    DataStore ds = null;
1279
1280    //get the URL (a file in this case)
1281    fileChooser.setDialogTitle("Please create a new empty directory");
1282    fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1283    if(fileChooser.showOpenDialog(MainFrame.this) ==
1284                                          JFileChooser.APPROVE_OPTION){
1285      try {
1286        URL dsURL = fileChooser.getSelectedFile().toURL();
1287        ds = Factory.createDataStore("gate.persist.SerialDataStore",
1288                                               dsURL.toExternalForm());
1289      } catch(MalformedURLException mue) {
1290        JOptionPane.showMessageDialog(
1291            MainFrame.this, "Invalid location for the datastore\n " +
1292                              mue.toString(),
1293                              "GATE", JOptionPane.ERROR_MESSAGE);
1294      } catch(PersistenceException pe) {
1295        JOptionPane.showMessageDialog(
1296            MainFrame.this, "Datastore creation error!\n " +
1297                              pe.toString(),
1298                              "GATE", JOptionPane.ERROR_MESSAGE);
1299      } // catch
1300    } // if
1301
1302    return ds;
1303  } // createSerialDataStore()
1304
1305  /** Method is used in OpenDSAction */
1306  protected DataStore openSerialDataStore() {
1307    DataStore ds = null;
1308
1309    //get the URL (a file in this case)
1310    fileChooser.setDialogTitle("Select the datastore directory");
1311    fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1312    if (fileChooser.showOpenDialog(MainFrame.this) ==
1313                                          JFileChooser.APPROVE_OPTION){
1314      try {
1315        URL dsURL = fileChooser.getSelectedFile().toURL();
1316        ds = Factory.openDataStore("gate.persist.SerialDataStore",
1317                                             dsURL.toExternalForm());
1318      } catch(MalformedURLException mue) {
1319        JOptionPane.showMessageDialog(
1320            MainFrame.this, "Invalid location for the datastore\n " +
1321                              mue.toString(),
1322                              "GATE", JOptionPane.ERROR_MESSAGE);
1323      } catch(PersistenceException pe) {
1324        JOptionPane.showMessageDialog(
1325            MainFrame.this, "Datastore opening error!\n " +
1326                              pe.toString(),
1327                              "GATE", JOptionPane.ERROR_MESSAGE);
1328      } // catch
1329    } // if
1330
1331    return ds;
1332  } // openSerialDataStore()
1333
1334
1335/*
1336  synchronized void showWaitDialog() {
1337    Point location = getLocationOnScreen();
1338    location.translate(10,
1339              getHeight() - waitDialog.getHeight() - southBox.getHeight() - 10);
1340    waitDialog.setLocation(location);
1341    waitDialog.showDialog(new Component[]{});
1342  }
1343
1344  synchronized void  hideWaitDialog() {
1345    waitDialog.goAway();
1346  }
1347*/
1348
1349/*
1350  class NewProjectAction extends AbstractAction {
1351    public NewProjectAction(){
1352      super("New Project", new ImageIcon(MainFrame.class.getResource(
1353                                        "/gate/resources/img/newProject.gif")));
1354      putValue(SHORT_DESCRIPTION,"Create a new project");
1355    }
1356    public void actionPerformed(ActionEvent e){
1357      fileChooser.setDialogTitle("Select new project file");
1358      fileChooser.setFileSelectionMode(fileChooser.FILES_ONLY);
1359      if(fileChooser.showOpenDialog(parentFrame) == fileChooser.APPROVE_OPTION){
1360        ProjectData pData = new ProjectData(fileChooser.getSelectedFile(),
1361                                                                  parentFrame);
1362        addProject(pData);
1363      }
1364    }
1365  }
1366*/
1367
1368  /** This class represent an action which brings up the Annot Diff tool*/
1369  class NewAnnotDiffAction extends AbstractAction {
1370    public NewAnnotDiffAction() {
1371      super("Annotation Diff", getIcon("annDiff.gif"));
1372      putValue(SHORT_DESCRIPTION,"Open a new Annotation Diff window");
1373    }// NewAnnotDiffAction
1374    public void actionPerformed(ActionEvent e) {
1375//      AnnotDiffDialog annotDiffDialog = new AnnotDiffDialog(MainFrame.this);
1376//      annotDiffDialog.setTitle("Annotation Diff Tool");
1377//      annotDiffDialog.setVisible(true);
1378      AnnotationDiffGUI frame = new AnnotationDiffGUI("Annotation Diff Tool");
1379      frame.pack();
1380      frame.setIconImage(((ImageIcon)getIcon("annDiff.gif")).getImage());
1381      frame.setLocationRelativeTo(MainFrame.this);
1382      frame.setVisible(true);
1383    }// actionPerformed();
1384  }//class NewAnnotDiffAction
1385
1386  /** This class represent an action which brings up the Corpus Annot Diff tool*/
1387  class NewCorpusAnnotDiffAction extends AbstractAction {
1388    public NewCorpusAnnotDiffAction() {
1389      super("Corpus Annotation Diff", getIcon("annDiff.gif"));
1390      putValue(SHORT_DESCRIPTION,"Create a new Corpus Annotation Diff Tool");
1391    }// NewCorpusAnnotDiffAction
1392    public void actionPerformed(ActionEvent e) {
1393      CorpusAnnotDiffDialog annotDiffDialog =
1394        new CorpusAnnotDiffDialog(MainFrame.this);
1395      annotDiffDialog.setTitle("Corpus Annotation Diff Tool");
1396      annotDiffDialog.setVisible(true);
1397    }// actionPerformed();
1398  }//class NewCorpusAnnotDiffAction
1399
1400  /** This class represent an action which brings up the corpus evaluation tool*/
1401  class NewCorpusEvalAction extends AbstractAction {
1402    public NewCorpusEvalAction() {
1403      super("Default mode");
1404      putValue(SHORT_DESCRIPTION,"Run the Benchmark Tool in its default mode");
1405    }// newCorpusEvalAction
1406
1407    public void actionPerformed(ActionEvent e) {
1408      Runnable runnable = new Runnable(){
1409        public void run(){
1410          JFileChooser chooser = MainFrame.getFileChooser();
1411          chooser.setDialogTitle("Please select a directory which contains " +
1412                                 "the documents to be evaluated");
1413          chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1414          chooser.setMultiSelectionEnabled(false);
1415          int state = chooser.showOpenDialog(MainFrame.this);
1416          File startDir = chooser.getSelectedFile();
1417          if (state == JFileChooser.CANCEL_OPTION || startDir == null)
1418            return;
1419
1420          chooser.setDialogTitle("Please select the application that you want to run");
1421          chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1422          state = chooser.showOpenDialog(MainFrame.this);
1423          File testApp = chooser.getSelectedFile();
1424          if (state == JFileChooser.CANCEL_OPTION || startDir == null)
1425            return;
1426
1427          //first create the tool and set its parameters
1428          CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
1429          theTool.setStartDirectory(startDir);
1430          theTool.setApplicationFile(testApp);
1431          theTool.setVerboseMode(verboseModeItem.isSelected());
1432
1433          Out.prln("Please wait while GATE tools are initialised.");
1434          //initialise the tool
1435          theTool.init();
1436          //and execute it
1437          theTool.execute();
1438          theTool.printStatistics();
1439
1440          Out.prln("Overall average precision: " + theTool.getPrecisionAverage());
1441          Out.prln("Overall average recall: " + theTool.getRecallAverage());
1442          Out.prln("Finished!");
1443          theTool.unloadPRs();
1444        }
1445      };
1446      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1447                                 runnable, "Eval thread");
1448      thread.setPriority(Thread.MIN_PRIORITY);
1449      thread.start();
1450    }// actionPerformed();
1451  }//class NewCorpusEvalAction
1452
1453  /** This class represent an action which brings up the corpus evaluation tool*/
1454  class StoredMarkedCorpusEvalAction extends AbstractAction {
1455    public StoredMarkedCorpusEvalAction() {
1456      super("Human marked against stored processing results");
1457      putValue(SHORT_DESCRIPTION,"Run the Benchmark Tool -stored_clean");
1458    }// newCorpusEvalAction
1459
1460    public void actionPerformed(ActionEvent e) {
1461      Runnable runnable = new Runnable(){
1462        public void run(){
1463          JFileChooser chooser = MainFrame.getFileChooser();
1464          chooser.setDialogTitle("Please select a directory which contains " +
1465                                 "the documents to be evaluated");
1466          chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1467          chooser.setMultiSelectionEnabled(false);
1468          int state = chooser.showOpenDialog(MainFrame.this);
1469          File startDir = chooser.getSelectedFile();
1470          if (state == JFileChooser.CANCEL_OPTION || startDir == null)
1471            return;
1472
1473          //first create the tool and set its parameters
1474          CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
1475          theTool.setStartDirectory(startDir);
1476          theTool.setMarkedStored(true);
1477          theTool.setVerboseMode(verboseModeItem.isSelected());
1478//          theTool.setMarkedDS(
1479//            MainFrame.this.datastoreModeCorpusEvalToolAction.isDatastoreMode());
1480
1481
1482          Out.prln("Evaluating human-marked documents against pre-stored results.");
1483          //initialise the tool
1484          theTool.init();
1485          //and execute it
1486          theTool.execute();
1487          theTool.printStatistics();
1488
1489          Out.prln("Overall average precision: " + theTool.getPrecisionAverage());
1490          Out.prln("Overall average recall: " + theTool.getRecallAverage());
1491          Out.prln("Finished!");
1492          theTool.unloadPRs();
1493        }
1494      };
1495      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1496                                 runnable, "Eval thread");
1497      thread.setPriority(Thread.MIN_PRIORITY);
1498      thread.start();
1499    }// actionPerformed();
1500  }//class StoredMarkedCorpusEvalActionpusEvalAction
1501
1502  /** This class represent an action which brings up the corpus evaluation tool*/
1503  class CleanMarkedCorpusEvalAction extends AbstractAction {
1504    public CleanMarkedCorpusEvalAction() {
1505      super("Human marked against current processing results");
1506      putValue(SHORT_DESCRIPTION,"Run the Benchmark Tool -marked_clean");
1507    }// newCorpusEvalAction
1508
1509    public void actionPerformed(ActionEvent e) {
1510      Runnable runnable = new Runnable(){
1511        public void run(){
1512          JFileChooser chooser = MainFrame.getFileChooser();
1513          chooser.setDialogTitle("Please select a directory which contains " +
1514                                 "the documents to be evaluated");
1515          chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1516          chooser.setMultiSelectionEnabled(false);
1517          int state = chooser.showOpenDialog(MainFrame.this);
1518          File startDir = chooser.getSelectedFile();
1519          if (state == JFileChooser.CANCEL_OPTION || startDir == null)
1520            return;
1521
1522          chooser.setDialogTitle("Please select the application that you want to run");
1523          chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1524          state = chooser.showOpenDialog(MainFrame.this);
1525          File testApp = chooser.getSelectedFile();
1526          if (state == JFileChooser.CANCEL_OPTION || startDir == null)
1527            return;
1528
1529          //first create the tool and set its parameters
1530          CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
1531          theTool.setStartDirectory(startDir);
1532          theTool.setApplicationFile(testApp);
1533          theTool.setMarkedClean(true);
1534          theTool.setVerboseMode(verboseModeItem.isSelected());
1535
1536          Out.prln("Evaluating human-marked documents against current processing results.");
1537          //initialise the tool
1538          theTool.init();
1539          //and execute it
1540          theTool.execute();
1541          theTool.printStatistics();
1542
1543          Out.prln("Overall average precision: " + theTool.getPrecisionAverage());
1544          Out.prln("Overall average recall: " + theTool.getRecallAverage());
1545          Out.prln("Finished!");
1546          theTool.unloadPRs();
1547        }
1548      };
1549      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1550                                 runnable, "Eval thread");
1551      thread.setPriority(Thread.MIN_PRIORITY);
1552      thread.start();
1553    }// actionPerformed();
1554  }//class CleanMarkedCorpusEvalActionpusEvalAction
1555
1556
1557  /** This class represent an action which brings up the corpus evaluation tool*/
1558  class GenerateStoredCorpusEvalAction extends AbstractAction {
1559    public GenerateStoredCorpusEvalAction() {
1560      super("Store corpus for future evaluation");
1561      putValue(SHORT_DESCRIPTION,"Run the Benchmark Tool -generate");
1562    }// newCorpusEvalAction
1563
1564    public void actionPerformed(ActionEvent e) {
1565      Runnable runnable = new Runnable(){
1566        public void run(){
1567          JFileChooser chooser = MainFrame.getFileChooser();
1568          chooser.setDialogTitle("Please select a directory which contains " +
1569                                 "the documents to be evaluated");
1570          chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1571          chooser.setMultiSelectionEnabled(false);
1572          int state = chooser.showOpenDialog(MainFrame.this);
1573          File startDir = chooser.getSelectedFile();
1574          if (state == JFileChooser.CANCEL_OPTION || startDir == null)
1575            return;
1576
1577          chooser.setDialogTitle("Please select the application that you want to run");
1578          chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
1579          state = chooser.showOpenDialog(MainFrame.this);
1580          File testApp = chooser.getSelectedFile();
1581          if (state == JFileChooser.CANCEL_OPTION || startDir == null)
1582            return;
1583
1584          //first create the tool and set its parameters
1585          CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
1586          theTool.setStartDirectory(startDir);
1587          theTool.setApplicationFile(testApp);
1588          theTool.setGenerateMode(true);
1589
1590          Out.prln("Processing and storing documents for future evaluation.");
1591          //initialise the tool
1592          theTool.init();
1593          //and execute it
1594          theTool.execute();
1595          theTool.unloadPRs();
1596          Out.prln("Finished!");
1597        }
1598      };
1599      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1600                                 runnable, "Eval thread");
1601      thread.setPriority(Thread.MIN_PRIORITY);
1602      thread.start();
1603    }// actionPerformed();
1604  }//class GenerateStoredCorpusEvalAction
1605
1606  /** This class represent an action which brings up the corpus evaluation tool*/
1607  class VerboseModeCorpusEvalToolAction extends AbstractAction  {
1608    public VerboseModeCorpusEvalToolAction() {
1609      super("Verbose mode");
1610      putValue(SHORT_DESCRIPTION,"Run the Benchmark Tool in verbose mode");
1611    }// VerboseModeCorpusEvalToolAction
1612
1613    public boolean isVerboseMode() {return verboseMode;}
1614
1615    public void actionPerformed(ActionEvent e) {
1616      if (! (e.getSource() instanceof JCheckBoxMenuItem))
1617        return;
1618      verboseMode = ((JCheckBoxMenuItem)e.getSource()).getState();
1619    }// actionPerformed();
1620    protected boolean verboseMode = false;
1621  }//class f
1622
1623  /** This class represent an action which brings up the corpus evaluation tool*/
1624/*
1625  class DatastoreModeCorpusEvalToolAction extends AbstractAction  {
1626    public DatastoreModeCorpusEvalToolAction() {
1627      super("Use a datastore for human annotated texts");
1628      putValue(SHORT_DESCRIPTION,"Use a datastore for the human annotated texts");
1629    }// DatastoreModeCorpusEvalToolAction
1630
1631    public boolean isDatastoreMode() {return datastoreMode;}
1632
1633    public void actionPerformed(ActionEvent e) {
1634      if (! (e.getSource() instanceof JCheckBoxMenuItem))
1635        return;
1636      datastoreMode = ((JCheckBoxMenuItem)e.getSource()).getState();
1637    }// actionPerformed();
1638    protected boolean datastoreMode = false;
1639  }//class DatastoreModeCorpusEvalToolListener
1640*/
1641
1642  /** This class represent an action which loads ANNIE with default params*/
1643  class LoadANNIEWithDefaultsAction extends AbstractAction
1644                                    implements ANNIEConstants{
1645    public LoadANNIEWithDefaultsAction() {
1646      super("With defaults");
1647      putValue(SHORT_DESCRIPTION, "Load ANNIE system using defaults");
1648      putValue(SMALL_ICON, getIcon("application.gif"));
1649    }// NewAnnotDiffAction
1650    public void actionPerformed(ActionEvent e) {
1651      // Loads ANNIE with defaults
1652      Runnable runnable = new Runnable(){
1653        public void run(){
1654          long startTime = System.currentTimeMillis();
1655          FeatureMap params = Factory.newFeatureMap();
1656          try{
1657            //lock the gui
1658            lockGUI("ANNIE is being loaded...");
1659            // Create a serial analyser
1660            SerialAnalyserController sac = (SerialAnalyserController)
1661                Factory.createResource("gate.creole.SerialAnalyserController",
1662                                       Factory.newFeatureMap(),
1663                                       Factory.newFeatureMap(),
1664                                       "ANNIE_" + Gate.genSym());
1665            // Load each PR as defined in gate.creole.ANNIEConstants.PR_NAMES
1666            for(int i = 0; i < PR_NAMES.length; i++){
1667            ProcessingResource pr = (ProcessingResource)
1668                Factory.createResource(PR_NAMES[i], params);
1669              // Add the PR to the sac
1670              sac.add(pr);
1671            }// End for
1672
1673            long endTime = System.currentTimeMillis();
1674            statusChanged("ANNIE loaded in " +
1675                NumberFormat.getInstance().format(
1676                (double)(endTime - startTime) / 1000) + " seconds");
1677          }catch(gate.creole.ResourceInstantiationException ex){
1678            ex.printStackTrace(Err.getPrintWriter());
1679          }finally{
1680            unlockGUI();
1681          }
1682        }// run()
1683      };// End Runnable
1684      Thread thread = new Thread(runnable, "");
1685      thread.setPriority(Thread.MIN_PRIORITY);
1686      thread.start();
1687    }// actionPerformed();
1688  }//class LoadANNIEWithDefaultsAction
1689
1690  /** This class represent an action which loads ANNIE with default params*/
1691  class LoadANNIEWithoutDefaultsAction extends AbstractAction
1692                                    implements ANNIEConstants{
1693    public LoadANNIEWithoutDefaultsAction() {
1694      super("Without defaults");
1695      putValue(SHORT_DESCRIPTION, "Load ANNIE system without defaults");
1696      putValue(SMALL_ICON, getIcon("application.gif"));
1697    }// NewAnnotDiffAction
1698    public void actionPerformed(ActionEvent e) {
1699      // Loads ANNIE with defaults
1700      Runnable runnable = new Runnable(){
1701        public void run(){
1702          FeatureMap params = Factory.newFeatureMap();
1703          try{
1704            // Create a serial analyser
1705            SerialAnalyserController sac = (SerialAnalyserController)
1706                Factory.createResource("gate.creole.SerialAnalyserController",
1707                                       Factory.newFeatureMap(),
1708                                       Factory.newFeatureMap(),
1709                                       "ANNIE_" + Gate.genSym());
1710//            NewResourceDialog resourceDialog = new NewResourceDialog(
1711//                                  MainFrame.this, "Resource parameters", true );
1712            // Load each PR as defined in gate.creole.ANNIEConstants.PR_NAMES
1713            for(int i = 0; i < PR_NAMES.length; i++){
1714              //get the params for the Current PR
1715              ResourceData resData = (ResourceData)Gate.getCreoleRegister().
1716                                      get(PR_NAMES[i]);
1717              if(newResourceDialog.show(resData,
1718                                     "Parameters for the new " +
1719                                     resData.getName())){
1720                sac.add((ProcessingResource)Factory.createResource(
1721                          PR_NAMES[i],
1722                          newResourceDialog.getSelectedParameters()));
1723              }else{
1724                //the user got bored and aborted the operation
1725                statusChanged("Loading cancelled! Removing traces...");
1726                Iterator loadedPRsIter = new ArrayList(sac.getPRs()).iterator();
1727                while(loadedPRsIter.hasNext()){
1728                  Factory.deleteResource((ProcessingResource)
1729                                         loadedPRsIter.next());
1730                }
1731                Factory.deleteResource(sac);
1732                statusChanged("Loading cancelled!");
1733                return;
1734              }
1735            }// End for
1736            statusChanged("ANNIE loaded!");
1737          }catch(gate.creole.ResourceInstantiationException ex){
1738            ex.printStackTrace(Err.getPrintWriter());
1739          }// End try
1740        }// run()
1741      };// End Runnable
1742      SwingUtilities.invokeLater(runnable);
1743//      Thread thread = new Thread(runnable, "");
1744//      thread.setPriority(Thread.MIN_PRIORITY);
1745//      thread.start();
1746    }// actionPerformed();
1747  }//class LoadANNIEWithoutDefaultsAction
1748
1749  /** This class represent an action which loads ANNIE without default param*/
1750  class LoadANNIEWithoutDefaultsAction1 extends AbstractAction
1751                                       implements ANNIEConstants {
1752    public LoadANNIEWithoutDefaultsAction1() {
1753      super("Without defaults");
1754    }// NewAnnotDiffAction
1755    public void actionPerformed(ActionEvent e) {
1756      //Load ANNIE without defaults
1757      CreoleRegister reg = Gate.getCreoleRegister();
1758      // Load each PR as defined in gate.creole.ANNIEConstants.PR_NAMES
1759      for(int i = 0; i < PR_NAMES.length; i++){
1760        ResourceData resData = (ResourceData)reg.get(PR_NAMES[i]);
1761        if (resData != null){
1762          NewResourceDialog resourceDialog = new NewResourceDialog(
1763              MainFrame.this, "Resource parameters", true );
1764          resourceDialog.setTitle(
1765                            "Parameters for the new " + resData.getName());
1766          resourceDialog.show(resData);
1767        }else{
1768          Err.prln(PR_NAMES[i] + " not found in Creole register");
1769        }// End if
1770      }// End for
1771      try{
1772        // Create an application at the end.
1773        Factory.createResource("gate.creole.SerialAnalyserController",
1774                               Factory.newFeatureMap(), Factory.newFeatureMap(),
1775                               "ANNIE_" + Gate.genSym());
1776      }catch(gate.creole.ResourceInstantiationException ex){
1777        ex.printStackTrace(Err.getPrintWriter());
1778      }// End try
1779    }// actionPerformed();
1780  }//class LoadANNIEWithoutDefaultsAction
1781
1782  class NewBootStrapAction extends AbstractAction {
1783    public NewBootStrapAction() {
1784      super("BootStrap Wizard", getIcon("application.gif"));
1785    }// NewBootStrapAction
1786    public void actionPerformed(ActionEvent e) {
1787      BootStrapDialog bootStrapDialog = new BootStrapDialog(MainFrame.this);
1788      bootStrapDialog.setVisible(true);
1789    }// actionPerformed();
1790  }//class NewBootStrapAction
1791
1792  
1793  class ManagePluginsAction extends AbstractAction {
1794    public ManagePluginsAction(){
1795      super("Manage CREOLE plugins");
1796      putValue(SHORT_DESCRIPTION,"Manage CREOLE plugins");
1797      putValue(SMALL_ICON, getIcon("param.gif"));
1798    }
1799
1800    public void actionPerformed(ActionEvent e) {
1801      if(pluginManager == null){
1802        pluginManager = new PluginManagerUI(MainFrame.this);
1803//        pluginManager.setLocationRelativeTo(MainFrame.this);
1804        pluginManager.setModal(true);
1805        getGuiRoots().add(pluginManager);
1806        pluginManager.pack();
1807        //size the window so that it doesn't go off-screen
1808        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
1809        Dimension dialogSize = pluginManager.getPreferredSize();
1810        int width = dialogSize.width > screenSize.width ?
1811                screenSize.width * 3 /4 :
1812                dialogSize.width;
1813        int height = dialogSize.height > screenSize.height ?
1814                screenSize.height * 3 /4 :
1815                dialogSize.height;
1816        pluginManager.setSize(width, height);
1817        pluginManager.validate();        
1818        //center the window on screen
1819        int x = (screenSize.width - width)/2;
1820        int y = (screenSize.height - height)/2;
1821        pluginManager.setLocation(x, y);
1822      }
1823      pluginManager.setVisible(true);
1824    }
1825  }
1826  
1827
1828  class LoadCreoleRepositoryAction extends AbstractAction {
1829    public LoadCreoleRepositoryAction(){
1830      super("Load a CREOLE repository");
1831      putValue(SHORT_DESCRIPTION,"Load a CREOLE repository");
1832    }
1833
1834    public void actionPerformed(ActionEvent e) {
1835      Box messageBox = Box.createHorizontalBox();
1836      Box leftBox = Box.createVerticalBox();
1837      JTextField urlTextField = new JTextField(20);
1838      leftBox.add(new JLabel("Type an URL"));
1839      leftBox.add(urlTextField);
1840      messageBox.add(leftBox);
1841
1842      messageBox.add(Box.createHorizontalStrut(10));
1843      messageBox.add(new JLabel("or"));
1844      messageBox.add(Box.createHorizontalStrut(10));
1845
1846      class URLfromFileAction extends AbstractAction{
1847        URLfromFileAction(JTextField textField){
1848          super(null, getIcon("loadFile.gif"));
1849          putValue(SHORT_DESCRIPTION,"Click to select a directory");
1850          this.textField = textField;
1851        }
1852
1853        public void actionPerformed(ActionEvent e){
1854          fileChooser.setMultiSelectionEnabled(false);
1855          fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
1856          fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
1857          int result = fileChooser.showOpenDialog(MainFrame.this);
1858          if(result == JFileChooser.APPROVE_OPTION){
1859            try{
1860              textField.setText(fileChooser.getSelectedFile().
1861                                            toURL().toExternalForm());
1862            }catch(MalformedURLException mue){
1863              throw new GateRuntimeException(mue.toString());
1864            }
1865          }
1866        }
1867        JTextField textField;
1868      };//class URLfromFileAction extends AbstractAction
1869
1870      Box rightBox = Box.createVerticalBox();
1871      rightBox.add(new JLabel("Select a directory"));
1872      JButton fileBtn = new JButton(new URLfromFileAction(urlTextField));
1873      rightBox.add(fileBtn);
1874      messageBox.add(rightBox);
1875
1876
1877//JOptionPane.showInputDialog(
1878//                            MainFrame.this,
1879//                            "Select type of Datastore",
1880//                            "Gate", JOptionPane.QUESTION_MESSAGE,
1881//                            null, names,
1882//                            names[0]);
1883
1884      int res = JOptionPane.showConfirmDialog(
1885                            MainFrame.this, messageBox,
1886                            "Enter an URL to the directory containig the " +
1887                            "\"creole.xml\" file", JOptionPane.OK_CANCEL_OPTION,
1888                            JOptionPane.QUESTION_MESSAGE, null);
1889      if(res == JOptionPane.OK_OPTION){
1890        try{
1891          URL creoleURL = new URL(urlTextField.getText());
1892          Gate.getCreoleRegister().registerDirectories(creoleURL);
1893        }catch(Exception ex){
1894          JOptionPane.showMessageDialog(
1895              MainFrame.this,
1896              "There was a problem with your selection:\n" +
1897              ex.toString() ,
1898              "GATE", JOptionPane.ERROR_MESSAGE);
1899          ex.printStackTrace(Err.getPrintWriter());
1900        }
1901      }
1902    }
1903  }//class LoadCreoleRepositoryAction extends AbstractAction
1904
1905
1906  class NewResourceAction extends AbstractAction {
1907    /** Used for creation of resource menu item and creation dialog */
1908    ResourceData rData;
1909
1910    public NewResourceAction(ResourceData rData) {
1911      super(rData.getName());
1912      putValue(SHORT_DESCRIPTION, rData.getComment());
1913      this.rData = rData;
1914    } // NewResourceAction(ResourceData rData)
1915
1916    public void actionPerformed(ActionEvent evt) {
1917      Runnable runnable = new Runnable(){
1918        public void run(){
1919          newResourceDialog.setTitle(
1920                              "Parameters for the new " + rData.getName());
1921          newResourceDialog.show(rData);
1922        }
1923      };
1924      SwingUtilities.invokeLater(runnable);
1925    } // actionPerformed
1926  } // class NewResourceAction extends AbstractAction
1927
1928
1929  static class StopAction extends AbstractAction {
1930    public StopAction(){
1931      super(" Stop! ");
1932      putValue(SHORT_DESCRIPTION,"Stops the current action");
1933    }
1934
1935    public boolean isEnabled(){
1936      return Gate.getExecutable() != null;
1937    }
1938
1939    public void actionPerformed(ActionEvent e) {
1940      Executable ex = Gate.getExecutable();
1941      if(ex != null) ex.interrupt();
1942    }
1943  }
1944
1945
1946  class NewDSAction extends AbstractAction {
1947    public NewDSAction(){
1948      super("Create datastore");
1949      putValue(SHORT_DESCRIPTION,"Create a new Datastore");
1950      putValue(SMALL_ICON, getIcon("ds.gif"));
1951    }
1952
1953    public void actionPerformed(ActionEvent e) {
1954      DataStoreRegister reg = Gate.getDataStoreRegister();
1955      Map dsTypes = DataStoreRegister.getDataStoreClassNames();
1956      HashMap dsTypeByName = new HashMap();
1957      Iterator dsTypesIter = dsTypes.entrySet().iterator();
1958      while(dsTypesIter.hasNext()){
1959        Map.Entry entry = (Map.Entry)dsTypesIter.next();
1960        dsTypeByName.put(entry.getValue(), entry.getKey());
1961      }
1962
1963      if(!dsTypeByName.isEmpty()) {
1964        Object[] names = dsTypeByName.keySet().toArray();
1965        Object answer = JOptionPane.showInputDialog(
1966                            MainFrame.this,
1967                            "Select type of Datastore",
1968                            "GATE", JOptionPane.QUESTION_MESSAGE,
1969                            null, names,
1970                            names[0]);
1971        if(answer != null) {
1972          String className = (String)dsTypeByName.get(answer);
1973          if(className.equals("gate.persist.SerialDataStore")){
1974            createSerialDataStore();
1975          } else if(className.equals("gate.persist.OracleDataStore")) {
1976              JOptionPane.showMessageDialog(
1977                    MainFrame.this, "Oracle datastores can only be created " +
1978                                    "by your Oracle administrator!",
1979                                    "GATE", JOptionPane.ERROR_MESSAGE);
1980          }  else {
1981
1982            throw new UnsupportedOperationException("Unimplemented option!\n"+
1983                                                    "Use a serial datastore");
1984          }
1985        }
1986      } else {
1987        //no ds types
1988        JOptionPane.showMessageDialog(MainFrame.this,
1989                                      "Could not find any registered types " +
1990                                      "of datastores...\n" +
1991                                      "Check your GATE installation!",
1992                                      "GATE", JOptionPane.ERROR_MESSAGE);
1993
1994      }
1995    }
1996  }//class NewDSAction extends AbstractAction
1997
1998  class LoadResourceFromFileAction extends AbstractAction {
1999    public LoadResourceFromFileAction(){
2000      super("Restore application from file");
2001      putValue(SHORT_DESCRIPTION,"Restores a previously saved application");
2002      putValue(SMALL_ICON, getIcon("controller.gif"));
2003    }
2004
2005    public void actionPerformed(ActionEvent e) {
2006      Runnable runnable = new Runnable(){
2007        public void run(){
2008          fileChooser.setDialogTitle("Select a file for this resource");
2009          fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
2010          if (fileChooser.showOpenDialog(MainFrame.this) ==
2011                                                JFileChooser.APPROVE_OPTION){
2012            File file = fileChooser.getSelectedFile();
2013            try{
2014              gate.util.persistence.PersistenceManager.loadObjectFromFile(file);
2015            }catch(ResourceInstantiationException rie){
2016              processFinished();
2017              JOptionPane.showMessageDialog(MainFrame.this,
2018                              "Error!\n"+
2019                               rie.toString(),
2020                               "GATE", JOptionPane.ERROR_MESSAGE);
2021              rie.printStackTrace(Err.getPrintWriter());
2022            }catch(Exception ex){
2023              processFinished();
2024              JOptionPane.showMessageDialog(MainFrame.this,
2025                              "Error!\n"+
2026                               ex.toString(),
2027                               "GATE", JOptionPane.ERROR_MESSAGE);
2028              ex.printStackTrace(Err.getPrintWriter());
2029            }
2030          }
2031        }
2032      };
2033      Thread thread = new Thread(runnable);
2034      thread.setPriority(Thread.MIN_PRIORITY);
2035      thread.start();
2036    }
2037  }
2038
2039  /**
2040   * Closes the view associated to a resource.
2041   * Does not remove the resource from the system, only its view.
2042   */
2043  class CloseViewAction extends AbstractAction {
2044    public CloseViewAction(Handle handle) {
2045      super("Hide this view");
2046      putValue(SHORT_DESCRIPTION, "Hides this view");
2047      this.handle = handle;
2048    }
2049
2050    public void actionPerformed(ActionEvent e) {
2051      mainTabbedPane.remove(handle.getLargeView());
2052      mainTabbedPane.setSelectedIndex(mainTabbedPane.getTabCount() - 1);
2053    }//public void actionPerformed(ActionEvent e)
2054    Handle handle;
2055  }//class CloseViewAction
2056
2057  class RenameResourceAction extends AbstractAction{
2058    RenameResourceAction(TreePath path){
2059      super("Rename");
2060      putValue(SHORT_DESCRIPTION, "Renames the resource");
2061      this.path = path;
2062    }
2063    public void actionPerformed(ActionEvent e) {
2064      resourcesTree.startEditingAtPath(path);
2065    }
2066
2067    TreePath path;
2068  }
2069
2070  class CloseSelectedResourcesAction extends AbstractAction {
2071    public CloseSelectedResourcesAction() {
2072      super("Close all");
2073      putValue(SHORT_DESCRIPTION, "Closes the selected resources");
2074    }
2075
2076    public void actionPerformed(ActionEvent e) {
2077      TreePath[] paths = resourcesTree.getSelectionPaths();
2078      for(int i = 0; i < paths.length; i++){
2079        Object userObject = ((DefaultMutableTreeNode)paths[i].
2080                            getLastPathComponent()).getUserObject();
2081        if(userObject instanceof NameBearerHandle){
2082          ((NameBearerHandle)userObject).getCloseAction().actionPerformed(null);
2083        }
2084      }
2085    }
2086  }
2087
2088
2089  /**
2090   * Closes the view associated to a resource.
2091   * Does not remove the resource from the system, only its view.
2092   */
2093  class ExitGateAction extends AbstractAction {
2094    public ExitGateAction() {
2095      super("Exit GATE");
2096      putValue(SHORT_DESCRIPTION, "Closes the application");
2097      putValue(SMALL_ICON, getIcon("exit.gif"));
2098    }
2099
2100    public void actionPerformed(ActionEvent e) {
2101      Runnable runnable = new Runnable(){
2102        public void run(){
2103          //save the options
2104          OptionsMap userConfig = Gate.getUserConfig();
2105          if(userConfig.getBoolean(GateConstants.SAVE_OPTIONS_ON_EXIT).
2106             booleanValue()){
2107            //save the window size
2108            Integer width = new Integer(MainFrame.this.getWidth());
2109            Integer height = new Integer(MainFrame.this.getHeight());
2110            userConfig.put(GateConstants.MAIN_FRAME_WIDTH, width);
2111            userConfig.put(GateConstants.MAIN_FRAME_HEIGHT, height);
2112            try{
2113              Gate.writeUserConfig();
2114            }catch(GateException ge){
2115              logArea.getOriginalErr().println("Failed to save config data:");
2116              ge.printStackTrace(logArea.getOriginalErr());
2117            }
2118          }else{
2119            //don't save options on close
2120            //save the option not to save the options
2121            OptionsMap originalUserConfig = Gate.getOriginalUserConfig();
2122            originalUserConfig.put(GateConstants.SAVE_OPTIONS_ON_EXIT,
2123                                   new Boolean(false));
2124            userConfig.clear();
2125            userConfig.putAll(originalUserConfig);
2126            try{
2127              Gate.writeUserConfig();
2128            }catch(GateException ge){
2129              logArea.getOriginalErr().println("Failed to save config data:");
2130              ge.printStackTrace(logArea.getOriginalErr());
2131            }
2132          }
2133
2134          //save the session;
2135          File sessionFile = new File(Gate.getUserSessionFileName());
2136          if(userConfig.getBoolean(GateConstants.SAVE_SESSION_ON_EXIT).
2137             booleanValue()){
2138            //save all the open applications
2139            try{
2140              ArrayList appList = new ArrayList(Gate.getCreoleRegister().
2141                                  getAllInstances("gate.Controller"));
2142              //remove all hidden instances
2143              Iterator appIter = appList.iterator();
2144              while(appIter.hasNext())
2145                if(Gate.getHiddenAttribute(((Controller)appIter.next()).
2146                   getFeatures())) appIter.remove();
2147
2148
2149              gate.util.persistence.PersistenceManager.
2150                                    saveObjectToFile(appList, sessionFile);
2151            }catch(Exception ex){
2152              logArea.getOriginalErr().println("Failed to save session data:");
2153              ex.printStackTrace(logArea.getOriginalErr());
2154            }
2155          }else{
2156            //we don't want to save the session
2157            if(sessionFile.exists()) sessionFile.delete();
2158          }
2159          setVisible(false);
2160          dispose();
2161          System.exit(0);
2162        }//run
2163      };//Runnable
2164      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
2165                                 runnable, "Session loader");
2166      thread.setPriority(Thread.MIN_PRIORITY);
2167      thread.start();
2168    }
2169  }
2170
2171
2172  class OpenDSAction extends AbstractAction {
2173    public OpenDSAction() {
2174      super("Open datastore");
2175      putValue(SHORT_DESCRIPTION,"Open a datastore");
2176      putValue(SMALL_ICON, getIcon("ds.gif"));
2177    }
2178
2179    public void actionPerformed(ActionEvent e) {
2180      DataStoreRegister reg = Gate.getDataStoreRegister();
2181      Map dsTypes = DataStoreRegister.getDataStoreClassNames();
2182      HashMap dsTypeByName = new HashMap();
2183      Iterator dsTypesIter = dsTypes.entrySet().iterator();
2184      while(dsTypesIter.hasNext()){
2185        Map.Entry entry = (Map.Entry)dsTypesIter.next();
2186        dsTypeByName.put(entry.getValue(), entry.getKey());
2187      }
2188
2189      if(!dsTypeByName.isEmpty()) {
2190        Object[] names = dsTypeByName.keySet().toArray();
2191        Object answer = JOptionPane.showInputDialog(
2192                            MainFrame.this,
2193                            "Select type of Datastore",
2194                            "GATE", JOptionPane.QUESTION_MESSAGE,
2195                            null, names,
2196                            names[0]);
2197        if(answer != null) {
2198          String className = (String)dsTypeByName.get(answer);
2199          if(className.indexOf("SerialDataStore") != -1){
2200            openSerialDataStore();
2201          } else if(className.equals("gate.persist.OracleDataStore") ||
2202                    className.equals("gate.persist.PostgresDataStore")
2203                   ) {
2204              List dbPaths = new ArrayList();
2205              Iterator keyIter = DataStoreRegister.getConfigData().keySet().iterator();
2206              while (keyIter.hasNext()) {
2207                String keyName = (String) keyIter.next();
2208                if (keyName.startsWith("url"))
2209                  dbPaths.add(DataStoreRegister.getConfigData().get(keyName));
2210              }
2211              if (dbPaths.isEmpty())
2212                throw new
2213                  GateRuntimeException("JDBC URL not configured in gate.xml");
2214              //by default make it the first
2215              String storageURL = (String)dbPaths.get(0);
2216              if (dbPaths.size() > 1) {
2217                Object[] paths = dbPaths.toArray();
2218                answer = JOptionPane.showInputDialog(
2219                                    MainFrame.this,
2220                                    "Select a database",
2221                                    "GATE", JOptionPane.QUESTION_MESSAGE,
2222                                    null, paths,
2223                                    paths[0]);
2224                if (answer != null)
2225                  storageURL = (String) answer;
2226                else
2227                  return;
2228              }
2229              DataStore ds = null;
2230              AccessController ac = null;
2231              try {
2232                //1. login the user
2233//                ac = new AccessControllerImpl(storageURL);
2234                ac = Factory.createAccessController(storageURL);
2235                Assert.assertNotNull(ac);
2236                ac.open();
2237
2238                Session mySession = null;
2239                User usr = null;
2240                Group grp = null;
2241                try {
2242                  String userName = "";
2243                  String userPass = "";
2244                  String group = "";
2245
2246                  JPanel listPanel = new JPanel();
2247                  listPanel.setLayout(new BoxLayout(listPanel,BoxLayout.X_AXIS));
2248
2249                  JPanel panel1 = new JPanel();
2250                  panel1.setLayout(new BoxLayout(panel1,BoxLayout.Y_AXIS));
2251                  panel1.add(new JLabel("User name: "));
2252                  panel1.add(new JLabel("Password: "));
2253                  panel1.add(new JLabel("Group: "));
2254
2255                  JPanel panel2 = new JPanel();
2256                  panel2.setLayout(new BoxLayout(panel2,BoxLayout.Y_AXIS));
2257                  JTextField usrField = new JTextField(30);
2258                  panel2.add(usrField);
2259                  JPasswordField pwdField = new JPasswordField(30);
2260                  panel2.add(pwdField);
2261                  JComboBox grpField = new JComboBox(ac.listGroups().toArray());
2262                  grpField.setSelectedIndex(0);
2263                  panel2.add(grpField);
2264
2265                  listPanel.add(panel1);
2266                  listPanel.add(Box.createHorizontalStrut(20));
2267                  listPanel.add(panel2);
2268
2269                  if(OkCancelDialog.showDialog(MainFrame.this.getContentPane(),
2270                                                listPanel,
2271                                                "Please enter login details")){
2272
2273                    userName = usrField.getText();
2274                    userPass = new String(pwdField.getPassword());
2275                    group = (String) grpField.getSelectedItem();
2276
2277                    if(userName.equals("") || userPass.equals("") || group.equals("")) {
2278                      JOptionPane.showMessageDialog(
2279                        MainFrame.this,
2280                        "You must provide non-empty user name, password and group!",
2281                        "Login error",
2282                        JOptionPane.ERROR_MESSAGE
2283                        );
2284                      return;
2285                    }
2286                  }
2287                  else if(OkCancelDialog.userHasPressedCancel) {
2288                      return;
2289                  }
2290
2291                  grp = ac.findGroup(group);
2292                  usr = ac.findUser(userName);
2293                  mySession = ac.login(userName, userPass, grp.getID());
2294
2295                  //save here the user name, pass and group in local gate.xml
2296
2297                } catch (gate.security.SecurityException ex) {
2298                    JOptionPane.showMessageDialog(
2299                      MainFrame.this,
2300                      ex.getMessage(),
2301                      "Login error",
2302                      JOptionPane.ERROR_MESSAGE
2303                      );
2304                  ac.close();
2305                  return;
2306                }
2307
2308                if (! ac.isValidSession(mySession)){
2309                  JOptionPane.showMessageDialog(
2310                    MainFrame.this,
2311                    "Incorrect session obtained. "
2312                      + "Probably there is a problem with the database!",
2313                    "Login error",
2314                    JOptionPane.ERROR_MESSAGE
2315                    );
2316                  ac.close();
2317                  return;
2318                }
2319
2320                //2. open the oracle datastore
2321                ds = Factory.openDataStore(className, storageURL);
2322                //set the session, so all get/adopt/etc work
2323                ds.setSession(mySession);
2324
2325                //3. add the security data for this datastore
2326                //this saves the user and group information, so it can
2327                //be used later when resources are created with certain rights
2328                FeatureMap securityData = Factory.newFeatureMap();
2329                securityData.put("user", usr);
2330                securityData.put("group", grp);
2331                DataStoreRegister.addSecurityData(ds, securityData);
2332              } catch(PersistenceException pe) {
2333                JOptionPane.showMessageDialog(
2334                    MainFrame.this, "Datastore open error!\n " +
2335                                      pe.toString(),
2336                                      "GATE", JOptionPane.ERROR_MESSAGE);
2337              } catch(gate.security.SecurityException se) {
2338                JOptionPane.showMessageDialog(
2339                    MainFrame.this, "User identification error!\n " +
2340                                      se.toString(),
2341                                      "GATE", JOptionPane.ERROR_MESSAGE);
2342                try {
2343                  if (ac != null)
2344                    ac.close();
2345                  if (ds != null)
2346                    ds.close();
2347                } catch (gate.persist.PersistenceException ex) {
2348                  JOptionPane.showMessageDialog(
2349                      MainFrame.this, "Persistence error!\n " +
2350                                        ex.toString(),
2351                                        "GATE", JOptionPane.ERROR_MESSAGE);
2352                }
2353              }
2354
2355          }else{
2356            JOptionPane.showMessageDialog(
2357                MainFrame.this,
2358                "Support for this type of datastores is not implemenented!\n",
2359                "GATE", JOptionPane.ERROR_MESSAGE);
2360          }
2361        }
2362      } else {
2363        //no ds types
2364        JOptionPane.showMessageDialog(MainFrame.this,
2365                                      "Could not find any registered types " +
2366                                      "of datastores...\n" +
2367                                      "Check your GATE installation!",
2368                                      "GATE", JOptionPane.ERROR_MESSAGE);
2369
2370      }
2371    }
2372  }//class OpenDSAction extends AbstractAction
2373
2374  /**
2375   * A menu that self populates based on CREOLE register data before being 
2376   * shown. Used for creating new resources of all possible types.
2377   */
2378  class LiveMenu extends XJMenu{
2379    public LiveMenu(int type){
2380      super();
2381      this.type = type;
2382      init();
2383    }
2384    
2385
2386    protected void init(){
2387      addMenuListener(new MenuListener(){
2388        public void menuCanceled(MenuEvent e) {
2389        }
2390        public void menuDeselected(MenuEvent e) {
2391        }
2392        public void menuSelected(MenuEvent e) {
2393          removeAll();
2394          //find out the available types of LRs and repopulate the menu
2395          CreoleRegister reg = Gate.getCreoleRegister();
2396          List resTypes;
2397          switch (type){
2398            case LR: 
2399              resTypes = reg.getPublicLrTypes();
2400              break;
2401            case PR:
2402              resTypes = reg.getPublicPrTypes();
2403              break;
2404            case APP:
2405              resTypes = reg.getPublicControllerTypes();
2406              break;
2407            default:
2408              throw new GateRuntimeException("Unknown LiveMenu type: " + type);
2409          }
2410          
2411          if(resTypes != null && !resTypes.isEmpty()){
2412            HashMap resourcesByName = new HashMap();
2413            Iterator resIter = resTypes.iterator();
2414            while(resIter.hasNext()){
2415              ResourceData rData = (ResourceData)reg.get(resIter.next());
2416              resourcesByName.put(rData.getName(), rData);
2417            }
2418            List resNames = new ArrayList(resourcesByName.keySet());
2419            Collections.sort(resNames);
2420            resIter = resNames.iterator();
2421            while(resIter.hasNext()){
2422              ResourceData rData = (ResourceData)resourcesByName.
2423                                   get(resIter.next());
2424              add(new XJMenuItem(new NewResourceAction(rData),
2425                                           MainFrame.this));
2426            }
2427          }
2428        }
2429      });
2430    }
2431    
2432    protected int type;
2433    /**
2434     * Switch for using LR data.
2435     */
2436    public static final int LR = 1;
2437
2438    /**
2439     * Switch for using PR data.
2440     */
2441    public static final int PR = 2;
2442    
2443    /**
2444     * Switch for using Controller data.
2445     */
2446    public static final int APP = 3;
2447  }
2448  
2449  
2450  class HelpAboutAction extends AbstractAction {
2451    public HelpAboutAction(){
2452      super("About");
2453    }
2454
2455    public void actionPerformed(ActionEvent e) {
2456      splash.showSplash();
2457    }
2458  }
2459
2460  class HelpUserGuideAction extends AbstractAction {
2461    public HelpUserGuideAction(){
2462      super("User Guide");
2463      putValue(SHORT_DESCRIPTION, "This option needs an internet connection");
2464    }
2465
2466    public void actionPerformed(ActionEvent e) {
2467
2468      Runnable runnable = new Runnable(){
2469        public void run(){
2470          try{
2471            HelpFrame helpFrame = new HelpFrame();
2472            helpFrame.setPage(new URL("http://www.gate.ac.uk/sale/tao/index.html"));
2473            helpFrame.setSize(800, 600);
2474            //center on screen
2475            Dimension frameSize = helpFrame.getSize();
2476            Dimension ownerSize = Toolkit.getDefaultToolkit().getScreenSize();
2477            Point ownerLocation = new Point(0, 0);
2478            helpFrame.setLocation(
2479                      ownerLocation.x + (ownerSize.width - frameSize.width) / 2,
2480                      ownerLocation.y + (ownerSize.height - frameSize.height) / 2);
2481
2482            helpFrame.setVisible(true);
2483          }catch(IOException ioe){
2484            ioe.printStackTrace(Err.getPrintWriter());
2485          }
2486        }
2487      };
2488      Thread thread = new Thread(runnable);
2489      thread.start();
2490    }
2491  }
2492
2493  protected class ResourcesTreeCellRenderer extends DefaultTreeCellRenderer {
2494    public ResourcesTreeCellRenderer() {
2495      setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
2496    }
2497    public Component getTreeCellRendererComponent(JTree tree,
2498                                              Object value,
2499                                              boolean sel,
2500                                              boolean expanded,
2501                                              boolean leaf,
2502                                              int row,
2503                                              boolean hasFocus){
2504      super.getTreeCellRendererComponent(tree, value, sel, expanded,
2505                                         leaf, row, hasFocus);
2506      if(value == resourcesTreeRoot) {
2507        setIcon(MainFrame.getIcon("project.gif"));
2508        setToolTipText("GATE");
2509      } else if(value == applicationsRoot) {
2510        setIcon(MainFrame.getIcon("applications.gif"));
2511        setToolTipText("GATE applications");
2512      } else if(value == languageResourcesRoot) {
2513        setIcon(MainFrame.getIcon("lrs.gif"));
2514        setToolTipText("Language Resources");
2515      } else if(value == processingResourcesRoot) {
2516        setIcon(MainFrame.getIcon("prs.gif"));
2517        setToolTipText("Processing Resources");
2518      } else if(value == datastoresRoot) {
2519        setIcon(MainFrame.getIcon("dss.gif"));
2520        setToolTipText("GATE Datastores");
2521      }else{
2522        //not one of the default root nodes
2523        value = ((DefaultMutableTreeNode)value).getUserObject();
2524        if(value instanceof Handle) {
2525          setIcon(((Handle)value).getIcon());
2526          setText(((Handle)value).getTitle());
2527          setToolTipText(((Handle)value).getTooltipText());
2528        }
2529      }
2530      return this;
2531    }
2532
2533    public Component getTreeCellRendererComponent1(JTree tree,
2534                                              Object value,
2535                                              boolean sel,
2536                                              boolean expanded,
2537                                              boolean leaf,
2538                                              int row,
2539                                              boolean hasFocus) {
2540      super.getTreeCellRendererComponent(tree, value, selected, expanded,
2541                                         leaf, row, hasFocus);
2542      Object handle = ((DefaultMutableTreeNode)value).getUserObject();
2543      if(handle != null && handle instanceof Handle){
2544        setIcon(((Handle)handle).getIcon());
2545        setText(((Handle)handle).getTitle());
2546        setToolTipText(((Handle)handle).getTooltipText());
2547      }
2548      return this;
2549    }
2550  }
2551
2552  protected class ResourcesTreeCellEditor extends DefaultTreeCellEditor {
2553    ResourcesTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer){
2554      super(tree, renderer);
2555    }
2556
2557    /**
2558     * This is the original implementation from the super class with some
2559     * changes (i.e. shorter timer: 500 ms instead of 1200)
2560     */
2561    protected void startEditingTimer() {
2562      if(timer == null) {
2563        timer = new javax.swing.Timer(500, this);
2564        timer.setRepeats(false);
2565      }
2566      timer.start();
2567    }
2568
2569    /**
2570     * This is the original implementation from the super class with some
2571     * changes (i.e. correct discovery of icon)
2572     */
2573    public Component getTreeCellEditorComponent(JTree tree, Object value,
2574                                                boolean isSelected,
2575                                                boolean expanded,
2576                                                boolean leaf, int row) {
2577      Component retValue = super.getTreeCellEditorComponent(tree, value,
2578                                                            isSelected,
2579                                                            expanded,
2580                                                            leaf, row);
2581      //lets find the actual icon
2582      if(renderer != null) {
2583        renderer.getTreeCellRendererComponent(tree, value, isSelected, expanded,
2584                                              leaf, row, false);
2585        editingIcon = renderer.getIcon();
2586      }
2587      return retValue;
2588    }
2589  }//protected class ResourcesTreeCellEditor extends DefaultTreeCellEditor {
2590
2591  protected class ResourcesTreeModel extends DefaultTreeModel {
2592    ResourcesTreeModel(TreeNode root, boolean asksAllowChildren){
2593      super(root, asksAllowChildren);
2594    }
2595
2596    public void valueForPathChanged(TreePath path, Object newValue){
2597      DefaultMutableTreeNode   aNode = (DefaultMutableTreeNode)
2598                                       path.getLastPathComponent();
2599      Object userObject = aNode.getUserObject();
2600      if(userObject instanceof Handle){
2601        Object target = ((Handle)userObject).getTarget();
2602        if(target instanceof Resource){
2603          Gate.getCreoleRegister().setResourceName((Resource)target,
2604                                                   (String)newValue);
2605        }
2606      }
2607      nodeChanged(aNode);
2608    }
2609  }
2610
2611
2612
2613  class ProgressBarUpdater implements Runnable{
2614    ProgressBarUpdater(int newValue){
2615      value = newValue;
2616    }
2617
2618    public void run(){
2619      if(value == 0) progressBar.setVisible(false);
2620      else progressBar.setVisible(true);
2621      progressBar.setValue(value);
2622    }
2623
2624    int value;
2625  }
2626
2627  class StatusBarUpdater implements Runnable {
2628    StatusBarUpdater(String text){
2629      this.text = text;
2630    }
2631    public void run(){
2632      statusBar.setText(text);
2633    }
2634    String text;
2635  }
2636
2637  /**
2638   * During longer operations it is nice to keep the user entertained so
2639   * (s)he doesn't fall asleep looking at a progress bar that seems have
2640   * stopped. Also there are some operations that do not support progress
2641   * reporting so the progress bar would not work at all so we need a way
2642   * to let the user know that things are happening. We chose for purpose
2643   * to show the user a small cartoon in the form of an animated gif.
2644   * This class handles the diplaying and updating of those cartoons.
2645   */
2646  class CartoonMinder implements Runnable{
2647
2648    CartoonMinder(JPanel targetPanel){
2649      active = false;
2650      dying = false;
2651      this.targetPanel = targetPanel;
2652      imageLabel = new JLabel(getIcon("working.gif"));
2653      imageLabel.setOpaque(false);
2654      imageLabel.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
2655    }
2656
2657    public boolean isActive(){
2658      boolean res;
2659      synchronized(lock){
2660        res = active;
2661      }
2662      return res;
2663    }
2664
2665    public void activate(){
2666      //add the label in the panel
2667      SwingUtilities.invokeLater(new Runnable(){
2668        public void run(){
2669          targetPanel.add(imageLabel);
2670        }
2671      });
2672      //wake the dorment thread
2673      synchronized(lock){
2674        active = true;
2675      }
2676    }
2677
2678    public void deactivate(){
2679      //send the thread to sleep
2680      synchronized(lock){
2681        active = false;
2682      }
2683      //clear the panel
2684      SwingUtilities.invokeLater(new Runnable(){
2685        public void run(){
2686          targetPanel.removeAll();
2687          targetPanel.repaint();
2688        }
2689      });
2690    }
2691
2692    public void dispose(){
2693      synchronized(lock){
2694        dying = true;
2695      }
2696    }
2697
2698    public void run(){
2699      boolean isDying;
2700      synchronized(lock){
2701        isDying = dying;
2702      }
2703      while(!isDying){
2704        boolean isActive;
2705        synchronized(lock){
2706          isActive = active;
2707        }
2708        if(isActive && targetPanel.isVisible()){
2709          SwingUtilities.invokeLater(new Runnable(){
2710            public void run(){
2711//              targetPanel.getParent().validate();
2712//              targetPanel.getParent().repaint();
2713//              ((JComponent)targetPanel.getParent()).paintImmediately(((JComponent)targetPanel.getParent()).getBounds());
2714//              targetPanel.doLayout();
2715
2716//              targetPanel.requestFocus();
2717              targetPanel.getParent().getParent().invalidate();
2718              targetPanel.getParent().getParent().repaint();
2719//              targetPanel.paintImmediately(targetPanel.getBounds());
2720            }
2721          });
2722        }
2723        //sleep
2724        try{
2725          Thread.sleep(300);
2726        }catch(InterruptedException ie){}
2727
2728        synchronized(lock){
2729          isDying = dying;
2730        }
2731      }//while(!isDying)
2732    }
2733
2734    boolean dying;
2735    boolean active;
2736    String lock = "lock";
2737    JPanel targetPanel;
2738    JLabel imageLabel;
2739  }
2740
2741/*
2742  class JGateMenuItem extends JMenuItem {
2743    JGateMenuItem(javax.swing.Action a){
2744      super(a);
2745      this.addMouseListener(new MouseAdapter() {
2746        public void mouseEntered(MouseEvent e) {
2747          oldText = statusBar.getText();
2748          statusChanged((String)getAction().
2749                        getValue(javax.swing.Action.SHORT_DESCRIPTION));
2750        }
2751
2752        public void mouseExited(MouseEvent e) {
2753          statusChanged(oldText);
2754        }
2755      });
2756    }
2757    String oldText;
2758  }
2759
2760  class JGateButton extends JButton {
2761    JGateButton(javax.swing.Action a){
2762      super(a);
2763      this.addMouseListener(new MouseAdapter() {
2764        public void mouseEntered(MouseEvent e) {
2765          oldText = statusBar.getText();
2766          statusChanged((String)getAction().
2767                        getValue(javax.swing.Action.SHORT_DESCRIPTION));
2768        }
2769
2770        public void mouseExited(MouseEvent e) {
2771          statusChanged(oldText);
2772        }
2773      });
2774    }
2775    String oldText;
2776  }
2777*/
2778  class LocaleSelectorMenuItem extends JRadioButtonMenuItem {
2779    public LocaleSelectorMenuItem(Locale locale) {
2780      super(locale.getDisplayName());
2781      me = this;
2782      myLocale = locale;
2783      this.addActionListener(new ActionListener()  {
2784        public void actionPerformed(ActionEvent e) {
2785          Iterator rootIter = MainFrame.getGuiRoots().iterator();
2786          while(rootIter.hasNext()){
2787            Object aRoot = rootIter.next();
2788            if(aRoot instanceof Window){
2789              me.setSelected(((Window)aRoot).getInputContext().
2790                              selectInputMethod(myLocale));
2791            }
2792          }
2793        }
2794      });
2795    }
2796
2797    public LocaleSelectorMenuItem() {
2798      super("System default  >>" +
2799            Locale.getDefault().getDisplayName() + "<<");
2800      me = this;
2801      myLocale = Locale.getDefault();
2802      this.addActionListener(new ActionListener()  {
2803        public void actionPerformed(ActionEvent e) {
2804          Iterator rootIter = MainFrame.getGuiRoots().iterator();
2805          while(rootIter.hasNext()){
2806            Object aRoot = rootIter.next();
2807            if(aRoot instanceof Window){
2808              me.setSelected(((Window)aRoot).getInputContext().
2809                              selectInputMethod(myLocale));
2810            }
2811          }
2812        }
2813      });
2814    }
2815
2816    Locale myLocale;
2817    JRadioButtonMenuItem me;
2818  }////class LocaleSelectorMenuItem extends JRadioButtonMenuItem
2819
2820  /**ontotext.bp
2821   * This class represent an action which brings up the Ontology Editor tool*/
2822  class NewOntologyEditorAction extends AbstractAction {
2823    public NewOntologyEditorAction(){
2824      super("Ontology Editor", getIcon("controller.gif"));
2825      putValue(SHORT_DESCRIPTION,"Start the Ontology Editor");
2826    }// NewAnnotDiffAction
2827
2828    public void actionPerformed(ActionEvent e) {
2829      OntologyEditorImpl editor = new OntologyEditorImpl();
2830      try {
2831        JFrame frame = new JFrame();
2832        editor.init();
2833        frame.setTitle("Ontology Editor");
2834        frame.getContentPane().add(editor);
2835        /*
2836          SET ONTOLOGY LIST AND ONTOLOGY
2837        */
2838        Set ontologies = new HashSet(Gate.getCreoleRegister().getLrInstances(
2839          "gate.creole.ontology.Ontology"));
2840
2841        editor.setOntologyList(new Vector(ontologies));
2842
2843        frame.setSize(OntologyEditorImpl.SIZE_X,OntologyEditorImpl.SIZE_Y);
2844        frame.setLocation(OntologyEditorImpl.POSITION_X,OntologyEditorImpl.POSITION_Y);
2845        frame.setVisible(true);
2846        editor.visualize();
2847      } catch ( ResourceInstantiationException ex ) {
2848        ex.printStackTrace(Err.getPrintWriter());
2849      }
2850    }// actionPerformed();
2851  }//class NewOntologyEditorAction
2852
2853  /** This class represent an action which brings up the Gazetteer Editor tool*/
2854  class NewGazetteerEditorAction extends AbstractAction {
2855    public NewGazetteerEditorAction(){
2856      super("Gazetteer Editor", getIcon("controller.gif"));
2857      putValue(SHORT_DESCRIPTION,"Start the Gazetteer Editor");
2858    }
2859
2860    public void actionPerformed(ActionEvent e) {
2861      com.ontotext.gate.vr.Gaze editor = new com.ontotext.gate.vr.Gaze();
2862      try {
2863        JFrame frame = new JFrame();
2864        editor.init();
2865        frame.setTitle("Gazetteer Editor");
2866        frame.getContentPane().add(editor);
2867
2868        Set gazetteers = new HashSet(Gate.getCreoleRegister().getLrInstances(
2869          "gate.creole.gazetteer.DefaultGazetteer"));
2870        if (gazetteers == null || gazetteers.isEmpty())
2871          return;
2872        Iterator iter = gazetteers.iterator();
2873        while (iter.hasNext()) {
2874          gate.creole.gazetteer.Gazetteer gaz =
2875            (gate.creole.gazetteer.Gazetteer) iter.next();
2876          if (gaz.getListsURL().toString().endsWith(System.getProperty("gate.slug.gazetteer")))
2877           editor.setTarget(gaz);
2878        }
2879
2880        frame.setSize(Gaze.SIZE_X,Gaze.SIZE_Y);
2881        frame.setLocation(Gaze.POSITION_X,Gaze.POSITION_Y);
2882        frame.setVisible(true);
2883        editor.setVisible(true);
2884      } catch ( ResourceInstantiationException ex ) {
2885        ex.printStackTrace(Err.getPrintWriter());
2886      }
2887    }// actionPerformed();
2888  }//class NewOntologyEditorAction
2889
2890} // class MainFrame
2891