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