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