0001 /*
0002 * Copyright (c) 1995-2010, The University of Sheffield. See the file
0003 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
0004 *
0005 * This file is part of GATE (see http://gate.ac.uk/), and is free
0006 * software, licenced under the GNU Library General Public License,
0007 * Version 2, June 1991 (in the distribution as file licence.html,
0008 * and also available at http://gate.ac.uk/gate/licence.html).
0009 *
0010 * Valentin Tablan 22/01/2001
0011 *
0012 * $Id: MainFrame.java 13697 2011-04-19 08:30:16Z valyt $
0013 *
0014 */
0015
0016 package gate.gui;
0017
0018 import java.awt.*;
0019 import java.awt.datatransfer.Transferable;
0020 import java.awt.datatransfer.StringSelection;
0021 import java.awt.datatransfer.DataFlavor;
0022 import java.awt.event.*;
0023 import java.beans.PropertyChangeEvent;
0024 import java.beans.PropertyChangeListener;
0025 import java.io.*;
0026 import java.net.MalformedURLException;
0027 import java.net.URL;
0028 import java.text.NumberFormat;
0029 import java.util.*;
0030 import java.util.List;
0031 import java.util.Timer;
0032 import java.util.regex.Matcher;
0033 import java.util.regex.Pattern;
0034 import java.lang.reflect.Constructor;
0035 import java.lang.reflect.Proxy;
0036 import java.lang.reflect.Method;
0037 import java.lang.reflect.InvocationHandler;
0038 import java.lang.SecurityException;
0039
0040 import javax.swing.*;
0041 import javax.swing.event.*;
0042 import javax.swing.tree.*;
0043
0044 import org.apache.log4j.*;
0045
0046 import junit.framework.Assert;
0047
0048 import com.ontotext.gate.vr.Gaze;
0049
0050 import gate.*;
0051 import gate.creole.*;
0052 import gate.creole.gazetteer.Gazetteer;
0053 import gate.creole.annic.Constants;
0054 import gate.event.*;
0055 import gate.persist.PersistenceException;
0056 import gate.security.*;
0057 import gate.swing.*;
0058 import gate.util.*;
0059 import gate.util.persistence.PersistenceManager;
0060 import gate.util.reporting.*;
0061 import gate.util.reporting.exceptions.BenchmarkReportException;
0062
0063 /**
0064 * The main Gate GUI frame.
0065 */
0066 public class MainFrame extends JFrame implements ProgressListener,
0067 StatusListener, CreoleListener {
0068
0069 protected static final Logger log = Logger.getLogger(MainFrame.class);
0070
0071 protected JMenuBar menuBar;
0072
0073 protected JSplitPane mainSplit;
0074
0075 protected JSplitPane leftSplit;
0076
0077 protected JLabel statusBar;
0078
0079 protected JButton alertButton;
0080
0081 protected JProgressBar progressBar;
0082
0083 protected JProgressBar globalProgressBar;
0084
0085 protected XJTabbedPane mainTabbedPane;
0086
0087 protected JScrollPane lowerScroll;
0088
0089 /**
0090 * Popup used for right click actions on the Applications node.
0091 */
0092 protected JPopupMenu appsPopup;
0093
0094 /**
0095 * Popup used for right click actions on the Datastores node.
0096 */
0097 protected JPopupMenu dssPopup;
0098
0099 /**
0100 * Popup used for right click actions on the LRs node.
0101 */
0102 protected JPopupMenu lrsPopup;
0103
0104 /**
0105 * Popup used for right click actions on the PRs node.
0106 */
0107 protected JPopupMenu prsPopup;
0108
0109 protected JCheckBoxMenuItem verboseModeItem;
0110
0111 protected JTree resourcesTree;
0112
0113 protected JScrollPane resourcesTreeScroll;
0114
0115 protected DefaultTreeModel resourcesTreeModel;
0116
0117 protected DefaultMutableTreeNode resourcesTreeRoot;
0118
0119 protected DefaultMutableTreeNode applicationsRoot;
0120
0121 protected DefaultMutableTreeNode languageResourcesRoot;
0122
0123 protected DefaultMutableTreeNode processingResourcesRoot;
0124
0125 protected DefaultMutableTreeNode datastoresRoot;
0126
0127 protected Splash splash;
0128
0129 protected PluginManagerUI pluginManager;
0130
0131 protected LogArea logArea;
0132
0133 protected JScrollPane logScroll;
0134
0135 protected JToolBar toolbar;
0136
0137 protected static XJFileChooser fileChooser;
0138
0139 static private MainFrame instance;
0140
0141 protected OptionsDialog optionsDialog;
0142
0143 protected CartoonMinder animator;
0144
0145 protected TabHighlighter logHighlighter;
0146
0147 protected NewResourceDialog newResourceDialog;
0148
0149 protected HelpFrame helpFrame;
0150
0151 /**
0152 * Holds all the icons used in the Gate GUI indexed by filename. This
0153 * is needed so we do not need to decode the icon everytime we need it
0154 * as that would use unnecessary CPU time and memory. Access to this
0155 * data is available through the {@link #getIcon(String)} method.
0156 */
0157 protected static Map<String, Icon> iconByName = new HashMap<String, Icon>();
0158
0159 protected static java.util.Collection<Component> guiRoots =
0160 new ArrayList<Component>();
0161
0162 /**
0163 * Extensions for icon files to be tried in this order.
0164 */
0165 protected static final String[] ICON_EXTENSIONS = {"", ".png", ".gif"};
0166
0167 private static JDialog guiLock = null;
0168
0169 static public Icon getIcon(String baseName) {
0170 Icon result = iconByName.get(baseName);
0171 for(int i = 0; i < ICON_EXTENSIONS.length && result == null; i++) {
0172 String extension = ICON_EXTENSIONS[i];
0173 String fileName = baseName + extension;
0174 URL iconURL;
0175 // if the ICON is an absolute path starting with '/', then just
0176 // load
0177 // it from that path. If it does not start with '/', treat it as
0178 // relative to gate/resources/img for backwards compatibility
0179 if(fileName.charAt(0) == '/') {
0180 iconURL = Files.getResource(fileName);
0181 }
0182 else {
0183 iconURL = Files.getGateResource("/img/" + fileName);
0184 }
0185 if(iconURL != null) {
0186 result = new ImageIcon(iconURL);
0187 iconByName.put(baseName, result);
0188 }
0189 }
0190 return result;
0191 }
0192
0193 static public MainFrame getInstance() {
0194 if(instance == null) instance = new MainFrame();
0195 return instance;
0196 }
0197
0198 /**
0199 * Get the file chooser.
0200 * @return the current file chooser
0201 */
0202 static public XJFileChooser getFileChooser() {
0203 return fileChooser;
0204 }
0205
0206 /**
0207 * Gets the original system output stream, which was later redirected
0208 * to the messages pane.
0209 *
0210 * @return a {@link PrintStream} value.
0211 */
0212 public PrintStream getOriginalOut() {
0213 return logArea.getOriginalOut();
0214 }
0215
0216 /**
0217 * Gets the original system error output stream, which was later
0218 * redirected to the messages pane.
0219 *
0220 * @return a {@link PrintStream} value.
0221 */
0222 public PrintStream getOriginalErr() {
0223 return logArea.getOriginalErr();
0224 }
0225
0226 /**
0227 * Locates the handle for a given resource.
0228 * @param res the resource for which the handle is sought.
0229 * @return the {@link Handle} for the resource, if it it was found.
0230 */
0231 protected Handle findHandleForResource(Resource res){
0232 Handle handle = null;
0233 // go through all the nodes
0234 Enumeration nodesEnum = resourcesTreeRoot.breadthFirstEnumeration();
0235 while(nodesEnum.hasMoreElements() && handle == null) {
0236 Object node = nodesEnum.nextElement();
0237 if(node instanceof DefaultMutableTreeNode) {
0238 DefaultMutableTreeNode dmtNode = (DefaultMutableTreeNode)node;
0239 if(dmtNode.getUserObject() instanceof Handle) {
0240 if(((Handle)dmtNode.getUserObject()).getTarget() == res) {
0241 handle = (Handle)dmtNode.getUserObject();
0242 }
0243 }
0244 }
0245 }
0246 return handle;
0247 }
0248
0249 /**
0250 * Selects a resource if loaded in the system and not invisible.
0251 *
0252 * @param res the resource to be selected.
0253 * @return the {@link Handle} for the resource, null if not found.
0254 */
0255 public Handle select(Resource res) {
0256 // first find the handle for the resource
0257 Handle handle = findHandleForResource(res);
0258 // now select the handle if found
0259 if(handle != null) {
0260 select(handle);
0261 }
0262 return handle;
0263 }
0264
0265 protected void select(Handle handle) {
0266 final JComponent largeView = handle.getLargeView();
0267 if(handle.viewsBuilt()
0268 && mainTabbedPane.indexOfComponent(handle.getLargeView()) != -1) {
0269 // select
0270 if(largeView != null) {
0271 mainTabbedPane.setSelectedComponent(largeView);
0272 }
0273 }
0274 else {
0275 // show
0276 if(largeView != null) {
0277 mainTabbedPane.addTab(handle.getTitle(), handle.getIcon(), largeView,
0278 handle.getTooltipText());
0279 mainTabbedPane.setSelectedComponent(handle.getLargeView());
0280 // put the focus on the new tab
0281 SwingUtilities.invokeLater(new Runnable() {
0282 public void run() {
0283 if (largeView != null) {
0284 if ((largeView instanceof JTabbedPane)
0285 && (((JTabbedPane)largeView).getSelectedComponent() != null)) {
0286 ((JTabbedPane)largeView).getSelectedComponent().requestFocus();
0287 } else {
0288 largeView.requestFocus();
0289 }
0290 }
0291 }
0292 });
0293 }
0294 }
0295 // show the small view
0296 JComponent smallView = handle.getSmallView();
0297 if(smallView != null) {
0298 lowerScroll.getViewport().setView(smallView);
0299 }
0300 else {
0301 lowerScroll.getViewport().setView(null);
0302 }
0303 }// protected void select(ResourceHandle handle)
0304
0305 public MainFrame() {
0306 this(null);
0307 }
0308
0309 public MainFrame(GraphicsConfiguration gc) {
0310 this(false, gc);
0311 } // MainFrame
0312
0313 /**
0314 * Construct the frame.
0315 * @param isShellSlacGIU true for embedded uses of GATE where a simpler GUI
0316 * should be displayed.
0317 * @param gc graphics configuration used,
0318 * see {@link javax.swing.JFrame#JFrame(java.awt.GraphicsConfiguration)}
0319 */
0320 public MainFrame(boolean isShellSlacGIU, GraphicsConfiguration gc) {
0321 super(gc);
0322 instance = this;
0323 guiRoots.add(this);
0324 if(fileChooser == null) {
0325 fileChooser = new XJFileChooser();
0326 fileChooser.setMultiSelectionEnabled(false);
0327 fileChooser.setAcceptAllFileFilterUsed(true);
0328 guiRoots.add(fileChooser);
0329
0330 // the JFileChooser seems to size itself better once it's been
0331 // added to a top level container such as a dialog.
0332 JDialog dialog = new JDialog(this, "", true);
0333 java.awt.Container contentPane = dialog.getContentPane();
0334 contentPane.setLayout(new BorderLayout());
0335 contentPane.add(fileChooser, BorderLayout.CENTER);
0336 dialog.pack();
0337 dialog.getContentPane().removeAll();
0338 dialog.dispose();
0339 dialog = null;
0340 }
0341 enableEvents(AWTEvent.WINDOW_EVENT_MASK);
0342 initLocalData(isShellSlacGIU);
0343 initGuiComponents(isShellSlacGIU);
0344 initListeners(isShellSlacGIU);
0345 } // MainFrame(boolean simple)
0346
0347 protected void initLocalData(boolean isShellSlacGIU) {
0348 resourcesTreeRoot = new DefaultMutableTreeNode("GATE", true);
0349 applicationsRoot = new DefaultMutableTreeNode("Applications", true);
0350 if(isShellSlacGIU) {
0351 languageResourcesRoot = new DefaultMutableTreeNode("Documents", true);
0352 }
0353 else {
0354 languageResourcesRoot =
0355 new DefaultMutableTreeNode("Language Resources", true);
0356 } // if
0357 processingResourcesRoot =
0358 new DefaultMutableTreeNode("Processing Resources", true);
0359 datastoresRoot = new DefaultMutableTreeNode("Datastores", true);
0360 resourcesTreeRoot.add(applicationsRoot);
0361 resourcesTreeRoot.add(languageResourcesRoot);
0362 resourcesTreeRoot.add(processingResourcesRoot);
0363 resourcesTreeRoot.add(datastoresRoot);
0364
0365 resourcesTreeModel = new ResourcesTreeModel(resourcesTreeRoot, true);
0366 }
0367
0368 protected void initGuiComponents(boolean isShellSlacGUI) {
0369 this.getContentPane().setLayout(new BorderLayout());
0370
0371 Integer width = Gate.getUserConfig().getInt(GateConstants.MAIN_FRAME_WIDTH);
0372 Integer height =
0373 Gate.getUserConfig().getInt(GateConstants.MAIN_FRAME_HEIGHT);
0374 this.setSize(new Dimension(width == null ? 800 : width,
0375 height == null ? 600 : height));
0376
0377 // TODO: when upgrading to Java 1.6 use setIconImages() instead
0378 this.setIconImage(Toolkit.getDefaultToolkit().getImage(
0379 Files.getGateResource("/img/gate-icon.png")));
0380 resourcesTree = new ResourcesTree();
0381 resourcesTree.setModel(resourcesTreeModel);
0382 resourcesTree.setRowHeight(0);
0383
0384 resourcesTree.setEditable(true);
0385 ResourcesTreeCellRenderer treeCellRenderer =
0386 new ResourcesTreeCellRenderer();
0387 resourcesTree.setCellRenderer(treeCellRenderer);
0388 resourcesTree.setCellEditor(new ResourcesTreeCellEditor(resourcesTree,
0389 treeCellRenderer));
0390
0391 resourcesTree.setRowHeight(0);
0392 // expand all nodes
0393 resourcesTree.expandRow(0);
0394 resourcesTree.expandRow(1);
0395 resourcesTree.expandRow(2);
0396 resourcesTree.expandRow(3);
0397 resourcesTree.expandRow(4);
0398 resourcesTree.getSelectionModel().setSelectionMode(
0399 TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
0400 resourcesTree.setEnabled(true);
0401 ToolTipManager.sharedInstance().registerComponent(resourcesTree);
0402 resourcesTreeScroll = new JScrollPane(resourcesTree);
0403
0404 resourcesTree.setDragEnabled(true);
0405 resourcesTree.setTransferHandler(new TransferHandler() {
0406 // drag and drop that export a list of the selected documents
0407 public int getSourceActions(JComponent c) {
0408 return COPY;
0409 }
0410 protected Transferable createTransferable(JComponent c) {
0411 TreePath[] paths = resourcesTree.getSelectionPaths();
0412 if(paths == null) { return new StringSelection(""); }
0413 Handle handle;
0414 List<String> documentsNames = new ArrayList<String>();
0415 for(TreePath path : paths) {
0416 if(path != null) {
0417 Object value = path.getLastPathComponent();
0418 value = ((DefaultMutableTreeNode)value).getUserObject();
0419 if(value instanceof Handle) {
0420 handle = (Handle)value;
0421 if(handle.getTarget() instanceof Document) {
0422 documentsNames.add(((Document)handle.getTarget()).getName());
0423 }
0424 }
0425 }
0426 }
0427 return new StringSelection("ResourcesTree"
0428 + Arrays.toString(documentsNames.toArray()));
0429 }
0430 protected void exportDone(JComponent c, Transferable data, int action) {
0431 }
0432 public boolean canImport(JComponent c, DataFlavor[] flavors) {
0433 return false;
0434 }
0435 public boolean importData(JComponent c, Transferable t) {
0436 return false;
0437 }
0438 });
0439
0440 lowerScroll = new JScrollPane();
0441 JPanel lowerPane = new JPanel();
0442 lowerPane.setLayout(new OverlayLayout(lowerPane));
0443
0444 JPanel animationPane = new JPanel();
0445 animationPane.setOpaque(false);
0446 animationPane.setLayout(new BoxLayout(animationPane, BoxLayout.X_AXIS));
0447
0448 JPanel vBox = new JPanel();
0449 vBox.setLayout(new BoxLayout(vBox, BoxLayout.Y_AXIS));
0450 vBox.setOpaque(false);
0451
0452 JPanel hBox = new JPanel();
0453 hBox.setLayout(new BoxLayout(hBox, BoxLayout.X_AXIS));
0454 hBox.setOpaque(false);
0455
0456 vBox.add(Box.createVerticalGlue());
0457 vBox.add(animationPane);
0458
0459 hBox.add(vBox);
0460 hBox.add(Box.createHorizontalGlue());
0461
0462 lowerPane.add(hBox);
0463 lowerPane.add(lowerScroll);
0464
0465 animator = new CartoonMinder(animationPane);
0466 Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
0467 animator, "MainFrame animation");
0468 thread.setDaemon(true);
0469 thread.setPriority(Thread.MIN_PRIORITY);
0470 thread.start();
0471
0472 leftSplit =
0473 new JSplitPane(JSplitPane.VERTICAL_SPLIT, resourcesTreeScroll, lowerPane);
0474 leftSplit.setResizeWeight(0.7);
0475 leftSplit.setContinuousLayout(true);
0476 leftSplit.setOneTouchExpandable(true);
0477
0478 // Create a new logArea and redirect the Out and Err output to it.
0479 logArea = new LogArea();
0480 logScroll = new JScrollPane(logArea);
0481 // Out has been redirected to the logArea
0482
0483 Out.prln("GATE " + Main.version + " build " + Main.build + " started at "
0484 + new Date().toString());
0485 Out.prln("and using Java " + System.getProperty("java.version") + " " +
0486 System.getProperty("java.vendor") + " on " +
0487 System.getProperty("os.name") + " " +
0488 System.getProperty("os.arch") + " " +
0489 System.getProperty("os.version") + ".");
0490 mainTabbedPane = new XJTabbedPane(JTabbedPane.TOP);
0491 mainTabbedPane.insertTab("Messages", null, logScroll, "GATE log", 0);
0492
0493 logHighlighter = new TabHighlighter(mainTabbedPane, logScroll, Color.red);
0494
0495 mainSplit =
0496 new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftSplit, mainTabbedPane);
0497 mainSplit.setDividerLocation(leftSplit.getPreferredSize().width + 10);
0498 this.getContentPane().add(mainSplit, BorderLayout.CENTER);
0499 mainSplit.setContinuousLayout(true);
0500 mainSplit.setOneTouchExpandable(true);
0501
0502 // status and progress bars
0503 statusBar = new JLabel();
0504 statusBar.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
0505
0506 UIManager.put("ProgressBar.cellSpacing", 0);
0507 progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
0508 progressBar.setBorder(BorderFactory.createEmptyBorder());
0509 progressBar.setForeground(new Color(150, 75, 150));
0510 progressBar.setStringPainted(false);
0511
0512 globalProgressBar = new JProgressBar(JProgressBar.HORIZONTAL);
0513 globalProgressBar.setBorder(BorderFactory.createEmptyBorder());
0514 globalProgressBar.setForeground(new Color(150, 75, 150));
0515 globalProgressBar.setStringPainted(true);
0516
0517 Icon alertIcon = getIcon("crystal-clear-app-error");
0518 alertButton = new JButton(alertIcon);
0519 alertButton.setToolTipText("There was no error");
0520 alertButton.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 5));
0521 alertButton.setPreferredSize(new Dimension(alertIcon.getIconWidth(),
0522 alertIcon.getIconHeight()));
0523 alertButton.setEnabled(false);
0524
0525 JPanel southBox = new JPanel(new GridBagLayout());
0526 GridBagConstraints gbc = new GridBagConstraints();
0527 gbc.fill = GridBagConstraints.BOTH;
0528 gbc.anchor = GridBagConstraints.WEST;
0529 gbc.weightx = 1;
0530 southBox.add(statusBar, gbc);
0531 gbc.insets = new Insets(0, 3, 0, 3);
0532 gbc.anchor = GridBagConstraints.EAST;
0533 gbc.weightx = 0;
0534 southBox.add(progressBar, gbc);
0535 southBox.add(globalProgressBar, gbc);
0536 southBox.add(alertButton, gbc);
0537
0538 this.getContentPane().add(southBox, BorderLayout.SOUTH);
0539 progressBar.setVisible(false);
0540 globalProgressBar.setVisible(false);
0541
0542 // extra stuff
0543 newResourceDialog =
0544 new NewResourceDialog(this, "Resource parameters", true);
0545
0546 // build the Help->About dialog
0547 JPanel splashBox = new JPanel();
0548 splashBox.setBackground(Color.WHITE);
0549
0550 splashBox.setLayout(new GridBagLayout());
0551 GridBagConstraints constraints = new GridBagConstraints();
0552 constraints.weightx = 1;
0553 constraints.insets = new Insets(2, 2, 2, 2);
0554 constraints.gridy = 0;
0555 constraints.fill = GridBagConstraints.BOTH;
0556
0557 JLabel gifLbl = new JLabel(getIcon("splash"));
0558 splashBox.add(gifLbl, constraints);
0559
0560 constraints.gridy = 2;
0561 constraints.gridwidth = 2;
0562 constraints.fill = GridBagConstraints.HORIZONTAL;
0563 String splashHtml;
0564 try {
0565 splashHtml = Files.getGateResourceAsString("splash.html");
0566 }
0567 catch(IOException e) {
0568 splashHtml = "GATE";
0569 log.error("Couldn't get splash.html resource.", e);
0570 }
0571 JLabel htmlLbl = new JLabel(splashHtml);
0572 htmlLbl.setHorizontalAlignment(SwingConstants.CENTER);
0573 splashBox.add(htmlLbl, constraints);
0574
0575 constraints.gridy = 3;
0576 htmlLbl =
0577 new JLabel("<HTML><FONT color=\"blue\">Version <B>" + Main.version
0578 + "</B></FONT>" + ", <FONT color=\"red\">build <B>" + Main.build
0579 + "</B></FONT>" + "<P><B>JVM version</B>: "
0580 + System.getProperty("java.version") + " from "
0581 + System.getProperty("java.vendor") + "</HTML>");
0582 constraints.fill = GridBagConstraints.HORIZONTAL;
0583 splashBox.add(htmlLbl, constraints);
0584
0585 constraints.gridy = 4;
0586 constraints.gridwidth = 2;
0587 constraints.fill = GridBagConstraints.NONE;
0588 final JButton okButton = new JButton("OK");
0589 okButton.addActionListener(new ActionListener() {
0590 public void actionPerformed(ActionEvent e) {
0591 splash.setVisible(false);
0592 }
0593 });
0594 okButton.setBackground(Color.white);
0595 splashBox.add(okButton, constraints);
0596 splash = new Splash(this, splashBox);
0597 // make Enter and Escape keys closing the splash window
0598 splash.getRootPane().setDefaultButton(okButton);
0599 InputMap inputMap = ((JComponent)splash.getContentPane())
0600 .getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
0601 ActionMap actionMap = ((JComponent)splash.getContentPane()).getActionMap();
0602 inputMap.put(KeyStroke.getKeyStroke("ENTER"), "Apply");
0603 actionMap.put("Apply", new AbstractAction() {
0604 public void actionPerformed(ActionEvent e) {
0605 okButton.doClick();
0606 }
0607 });
0608 inputMap.put(KeyStroke.getKeyStroke("ESCAPE"), "Cancel");
0609 actionMap.put("Cancel", new AbstractAction() {
0610 public void actionPerformed(ActionEvent e) {
0611 okButton.doClick();
0612 }
0613 });
0614
0615 // MENUS
0616 menuBar = new JMenuBar();
0617
0618 JMenu fileMenu = new XJMenu("File", null, this);
0619 fileMenu.setMnemonic(KeyEvent.VK_F);
0620
0621 LiveMenu newAPPMenu = new LiveMenu(LiveMenu.APP);
0622 newAPPMenu.setText("New Application");
0623 newAPPMenu.setIcon(getIcon("applications"));
0624 fileMenu.add(newAPPMenu);
0625
0626 LiveMenu newLRMenu = new LiveMenu(LiveMenu.LR);
0627 newLRMenu.setText("New Language Resource");
0628 newLRMenu.setIcon(getIcon("lrs"));
0629 fileMenu.add(newLRMenu);
0630
0631 LiveMenu newPRMenu = new LiveMenu(LiveMenu.PR);
0632 newPRMenu.setText("New Processing Resource");
0633 newPRMenu.setIcon(getIcon("prs"));
0634 fileMenu.add(newPRMenu);
0635
0636 final JMenu dsMenu = new XJMenu("Datastores",
0637 "Repositories for large data", this);
0638 dsMenu.setIcon(getIcon("datastores"));
0639 dsMenu.add(new XJMenuItem(new NewDSAction(), this));
0640 dsMenu.add(new XJMenuItem(new OpenDSAction(), this));
0641 fileMenu.add(dsMenu);
0642
0643 fileMenu.addSeparator();
0644 fileMenu.add(new XJMenuItem(new LoadResourceFromFileAction(), this));
0645
0646 RecentAppsMenu recentAppsMenu = new RecentAppsMenu();
0647 recentAppsMenu.setText("Recent Applications");
0648 recentAppsMenu.setIcon(getIcon("open-application"));
0649 fileMenu.add(recentAppsMenu);
0650
0651 final JMenu loadANNIEMenu = new XJMenu("Load ANNIE System",
0652 "Application that adds morphosyntaxic and semantic annotations", this);
0653 loadANNIEMenu.setIcon(getIcon("annie-application"));
0654 loadANNIEMenu.add(new XJMenuItem(new LoadANNIEWithDefaultsAction(), this));
0655 loadANNIEMenu
0656 .add(new XJMenuItem(new LoadANNIEWithoutDefaultsAction(), this));
0657 fileMenu.add(loadANNIEMenu);
0658
0659 // fileMenu.add(new XJMenuItem(new LoadCreoleRepositoryAction(),
0660 // this));
0661
0662 // LingPipe action
0663 fileMenu.add(new XJMenuItem(new LoadApplicationAction(
0664 "Load LingPipe System", "LingPipe", "resources/lingpipe.gapp"),
0665 this));
0666
0667 // OpenNLP action
0668 fileMenu.add(new XJMenuItem(new LoadApplicationAction(
0669 "Load OpenNLP System", "OpenNLP", "resources/opennlp.gapp"), this));
0670
0671 fileMenu.add(new XJMenuItem(new ManagePluginsAction(), this));
0672
0673 if(!Gate.runningOnMac()) {
0674 fileMenu.addSeparator();
0675 fileMenu.add(new XJMenuItem(new ExitGateAction(), this));
0676 }
0677
0678 menuBar.add(fileMenu);
0679
0680 JMenu optionsMenu = new XJMenu("Options", null, this);
0681 optionsMenu.setMnemonic(KeyEvent.VK_O);
0682
0683 boolean optionsMenuHasEntries = false;
0684
0685 optionsDialog = new OptionsDialog(MainFrame.this);
0686 if(!Gate.runningOnMac()) {
0687 optionsMenu.add(new XJMenuItem(new AbstractAction("Configuration") {
0688 private static final long serialVersionUID = 1L;
0689 {
0690 putValue(SHORT_DESCRIPTION, "Edit GATE options");
0691 }
0692
0693 public void actionPerformed(ActionEvent evt) {
0694 optionsDialog.showDialog();
0695 optionsDialog.dispose();
0696 }
0697 }, this));
0698 optionsMenuHasEntries = true;
0699 }
0700
0701 JMenu imMenu = null;
0702 List<Locale> installedLocales = new ArrayList<Locale>();
0703 try {
0704 // if this fails guk is not present
0705 Class.forName("guk.im.GateIMDescriptor");
0706 // add the Gate input methods
0707 installedLocales.addAll(Arrays.asList(new guk.im.GateIMDescriptor()
0708 .getAvailableLocales()));
0709 }
0710 catch(Exception e) {
0711 // something happened; most probably guk not present.
0712 // just drop it, is not vital.
0713 }
0714 try {
0715 // add the MPI IMs
0716 // if this fails mpi IM is not present
0717 Class.forName("mpi.alt.java.awt.im.spi.lookup.LookupDescriptor");
0718
0719 installedLocales.addAll(Arrays
0720 .asList(new mpi.alt.java.awt.im.spi.lookup.LookupDescriptor()
0721 .getAvailableLocales()));
0722 }
0723 catch(Exception e) {
0724 // something happened; most probably MPI not present.
0725 // just drop it, is not vital.
0726 }
0727
0728 Collections.sort(installedLocales, new Comparator<Locale>() {
0729 public int compare(Locale o1, Locale o2) {
0730 return o1.getDisplayName().compareTo(o2.getDisplayName());
0731 }
0732 });
0733 JMenuItem item;
0734 if(!installedLocales.isEmpty()) {
0735 imMenu = new XJMenu("Input Methods");
0736 ButtonGroup bg = new ButtonGroup();
0737 item = new LocaleSelectorMenuItem();
0738 imMenu.add(item);
0739 item.setSelected(true);
0740 imMenu.addSeparator();
0741 bg.add(item);
0742 for(Locale locale : installedLocales) {
0743 item = new LocaleSelectorMenuItem(locale);
0744 imMenu.add(item);
0745 bg.add(item);
0746 }
0747 }
0748 if(imMenu != null) {
0749 optionsMenu.add(imMenu);
0750 optionsMenuHasEntries = true;
0751 }
0752
0753 if(optionsMenuHasEntries) {
0754 menuBar.add(optionsMenu);
0755 }
0756
0757 ToolsMenu toolsMenu = new ToolsMenu("Tools", null, this);
0758 toolsMenu.setMnemonic(KeyEvent.VK_T);
0759 toolsMenu.add(new XJMenuItem(new NewAnnotDiffAction(), this));
0760
0761 final JMenuItem reportClearMenuItem = new XJMenuItem(
0762 new AbstractAction("Clear Profiling History") {
0763 { putValue(SHORT_DESCRIPTION,
0764 "Clear profiling history otherwise the report is cumulative."); }
0765 public void actionPerformed(ActionEvent evt) {
0766 // create a new log file
0767 File logFile = new File(System.getProperty("java.io.tmpdir"),
0768 "gate-benchmark-log.txt");
0769 logFile.deleteOnExit();
0770 if (logFile.exists() && !logFile.delete()) {
0771 log.info("Error when deleting the file:\n" +
0772 logFile.getAbsolutePath());
0773 }
0774 }
0775 }, this);
0776 JMenu reportMenu = new XJMenu("Profiling Reports",
0777 "Generates profiling reports from processing resources", this);
0778 reportMenu.setIcon(getIcon("gazetteer"));
0779 reportMenu.add(new XJMenuItem(
0780 new AbstractAction("Start Profiling Applications") {
0781 { putValue(SHORT_DESCRIPTION,
0782 "Toggles the profiling of processing resources"); }
0783
0784 // stores the value held by the benchmarking switch before we started
0785 // this profiling run.
0786 boolean benchmarkWasEnabled;
0787
0788 public void actionPerformed(ActionEvent evt) {
0789 if (getValue(NAME).equals("Start Profiling Applications")) {
0790 reportClearMenuItem.setEnabled(false);
0791 // store old value of benchmark switch
0792 benchmarkWasEnabled = Benchmark.isBenchmarkingEnabled();
0793 Benchmark.setBenchmarkingEnabled(true);
0794 Layout layout = new PatternLayout("%m%n");
0795 File logFile = new File(System.getProperty("java.io.tmpdir"),
0796 "gate-benchmark-log.txt");
0797 logFile.deleteOnExit();
0798 Appender appender;
0799 try {
0800 appender =
0801 new FileAppender(layout, logFile.getAbsolutePath(), true);
0802 } catch (IOException e) {
0803 e.printStackTrace();
0804 return;
0805 }
0806 appender.setName("gate-benchmark");
0807 Benchmark.logger.addAppender(appender);
0808 putValue(NAME, "Stop Profiling Applications");
0809 } else {
0810 // reset old value of benchmark switch - i.e. if benchmarking was
0811 // disabled before the user selected "start profiling" then we
0812 // disable it again now, but if it was already enabled before they
0813 // started profiling then we assume it was turned on explicitly and
0814 // leave it alone.
0815 Benchmark.setBenchmarkingEnabled(benchmarkWasEnabled);
0816 Benchmark.logger.removeAppender("gate-benchmark");
0817 putValue(NAME, "Start Profiling Applications");
0818 reportClearMenuItem.setEnabled(true);
0819 }
0820 }
0821 }, this));
0822 reportMenu.add(reportClearMenuItem);
0823 reportMenu.add(new XJMenuItem(new AbstractAction("Help on this tool") {
0824 public void actionPerformed(ActionEvent e) {
0825 showHelpFrame("chap:profiling", "Profiling Processing Resources");
0826 }
0827 }, this));
0828 reportMenu.addSeparator();
0829
0830 final JCheckBoxMenuItem reportZeroTimesCheckBox = new JCheckBoxMenuItem();
0831 reportZeroTimesCheckBox.setAction(
0832 new AbstractAction("Report Zero Time Entries") {
0833 public void actionPerformed(ActionEvent evt) {
0834 Gate.getUserConfig().put(MainFrame.class.getName()+".reportzerotime",
0835 reportZeroTimesCheckBox.isSelected());
0836 }
0837 });
0838 reportZeroTimesCheckBox.setSelected(Gate.getUserConfig().getBoolean(
0839 MainFrame.class.getName()+".reportzerotimes"));
0840 ButtonGroup group = new ButtonGroup();
0841 final JRadioButtonMenuItem reportSortExecution = new JRadioButtonMenuItem();
0842 reportSortExecution.setAction(new AbstractAction("Sort by Execution") {
0843 public void actionPerformed(ActionEvent evt) {
0844 Gate.getUserConfig().put(
0845 MainFrame.class.getName()+".reportsorttime", false);
0846 }
0847 });
0848 reportSortExecution.setSelected(!Gate.getUserConfig().getBoolean(
0849 MainFrame.class.getName()+".reportsorttime"));
0850 group.add(reportSortExecution);
0851 final JRadioButtonMenuItem reportSortTime = new JRadioButtonMenuItem();
0852 reportSortTime.setAction(new AbstractAction("Sort by Time") {
0853 public void actionPerformed(ActionEvent evt) {
0854 Gate.getUserConfig().put(
0855 MainFrame.class.getName()+".reportsorttime", true);
0856 }
0857 });
0858 reportSortTime.setSelected(Gate.getUserConfig().getBoolean(
0859 MainFrame.class.getName()+".reportsorttime"));
0860 group.add(reportSortTime);
0861 reportMenu.add(new XJMenuItem(
0862 new AbstractAction("Report on Processing Resources") {
0863 { putValue(SHORT_DESCRIPTION,
0864 "Report time taken by each processing resource"); }
0865 public void actionPerformed(ActionEvent evt) {
0866 PRTimeReporter report = new PRTimeReporter();
0867 report.setBenchmarkFile(new File(System.getProperty("java.io.tmpdir"),
0868 "gate-benchmark-log.txt"));
0869 report.setSuppressZeroTimeEntries(!reportZeroTimesCheckBox.isSelected());
0870 report.setSortOrder(reportSortTime.isSelected() ?
0871 PRTimeReporter.SORT_TIME_TAKEN : PRTimeReporter.SORT_EXEC_ORDER);
0872 try {
0873 report.executeReport();
0874 } catch (BenchmarkReportException e) {
0875 e.printStackTrace();
0876 return;
0877 }
0878 showHelpFrame("file://" + report.getReportFile(),
0879 "processing times report");
0880 }
0881 }, this));
0882 reportMenu.add(reportZeroTimesCheckBox);
0883 reportMenu.add(reportSortTime);
0884 reportMenu.add(reportSortExecution);
0885 reportMenu.addSeparator();
0886
0887 reportMenu.add(new XJMenuItem(
0888 new AbstractAction("Report on Documents Processed") {
0889 { putValue(SHORT_DESCRIPTION, "Report most time consuming documents"); }
0890 public void actionPerformed(ActionEvent evt) {
0891 DocTimeReporter report = new DocTimeReporter();
0892 report.setBenchmarkFile(new File(System.getProperty("java.io.tmpdir"),
0893 "gate-benchmark-log.txt"));
0894 String maxDocs = Gate.getUserConfig().getString(
0895 MainFrame.class.getName()+".reportmaxdocs");
0896 if (maxDocs != null) {
0897 report.setMaxDocumentInReport((maxDocs.equals("All")) ?
0898 DocTimeReporter.ALL_DOCS : Integer.valueOf(maxDocs));
0899 }
0900 String prRegex = Gate.getUserConfig().getString(
0901 MainFrame.class.getName()+".reportprregex");
0902 if (prRegex != null) {
0903 report.setPRMatchingRegex((prRegex.equals("")) ?
0904 DocTimeReporter.MATCH_ALL_PR_REGEX : prRegex);
0905 }
0906 try {
0907 report.executeReport();
0908 } catch (BenchmarkReportException e) {
0909 e.printStackTrace();
0910 return;
0911 }
0912 showHelpFrame("file://" + report.getReportFile(),
0913 "documents time report");
0914 }
0915 }, this));
0916 String maxDocs = Gate.getUserConfig().getString(
0917 MainFrame.class.getName()+".reportmaxdocs");
0918 if (maxDocs == null) { maxDocs = "10"; }
0919 reportMenu.add(new XJMenuItem(
0920 new AbstractAction("Set Max Documents (" + maxDocs + ")") {
0921 public void actionPerformed(ActionEvent evt) {
0922 Object response = JOptionPane.showInputDialog(instance,
0923 "Set the maximum of documents to report", "Report options",
0924 JOptionPane.QUESTION_MESSAGE, null,
0925 new Object[]{"All", "10", "20", "30", "40", "50", "100"}, "10");
0926 if (response != null) {
0927 Gate.getUserConfig().put(
0928 MainFrame.class.getName()+".reportmaxdocs",response);
0929 putValue(NAME, "Set Max Documents (" + response + ")");
0930 }
0931 }
0932 }, this));
0933 String prRegex = Gate.getUserConfig().getString(
0934 MainFrame.class.getName()+".reportprregex");
0935 if (prRegex == null || prRegex.equals("")) { prRegex = "All"; }
0936 reportMenu.add(new XJMenuItem(
0937 new AbstractAction("Set PR Matching Regex (" + prRegex + ")") {
0938 public void actionPerformed(ActionEvent evt) {
0939 Object response = JOptionPane.showInputDialog(instance,
0940 "Set the processing resource regex filter\n" +
0941 "Leave empty to not filter", "Report options",
0942 JOptionPane.QUESTION_MESSAGE);
0943 if (response != null) {
0944 Gate.getUserConfig().put(
0945 MainFrame.class.getName()+".reportprregex",response);
0946 if (response.equals("")) { response = "All"; }
0947 putValue(NAME, "Set PR Matching Regex (" + response + ")");
0948 }
0949 }
0950 }, this));
0951 toolsMenu.add(reportMenu);
0952
0953 toolsMenu.add(new XJMenuItem(new NewBootStrapAction(), this));
0954 final JMenu corpusEvalMenu = new XJMenu("Corpus Benchmark",
0955 "Compares processed and human-annotated annotations", this);
0956 corpusEvalMenu.setIcon(getIcon("corpus-benchmark"));
0957 toolsMenu.add(corpusEvalMenu);
0958 corpusEvalMenu.add(new XJMenuItem(new NewCorpusEvalAction(), this));
0959 corpusEvalMenu.addSeparator();
0960 corpusEvalMenu.add(new XJMenuItem(
0961 new GenerateStoredCorpusEvalAction(), this));
0962 corpusEvalMenu.addSeparator();
0963 corpusEvalMenu.add(new XJMenuItem(
0964 new StoredMarkedCorpusEvalAction(), this));
0965 corpusEvalMenu.add(new XJMenuItem(new CleanMarkedCorpusEvalAction(), this));
0966 corpusEvalMenu.addSeparator();
0967 verboseModeItem =
0968 new JCheckBoxMenuItem(new VerboseModeCorpusEvalToolAction());
0969 corpusEvalMenu.add(verboseModeItem);
0970 toolsMenu.add(new XJMenuItem(
0971 new AbstractAction("Unicode Editor", getIcon("unicode")) {
0972 { putValue(SHORT_DESCRIPTION, "Editor for testing character encoding"); }
0973 private static final long serialVersionUID = 1L;
0974 public void actionPerformed(ActionEvent evt) {
0975 new guk.Editor();
0976 }
0977 }, this));
0978
0979 // add separator. plugin menu items will appear after this separator
0980 toolsMenu.addSeparator();
0981 toolsMenu.staticItemsAdded();
0982 if (toolsMenu.getMenuComponent(toolsMenu.getMenuComponentCount()-1)
0983 instanceof JSeparator) { // remove separator if no tools
0984 toolsMenu.remove(toolsMenu.getMenuComponentCount()-1);
0985 }
0986
0987 menuBar.add(toolsMenu);
0988
0989 JMenu helpMenu = new XJMenu("Help", null, MainFrame.this);
0990 helpMenu.setMnemonic(KeyEvent.VK_H);
0991 helpMenu.add(new XJMenuItem(new HelpUserGuideAction(), this));
0992 helpMenu.add(new XJMenuItem(new HelpUserGuideInContextAction(), this));
0993 helpMenu.add(new XJMenuItem(new AbstractAction("Keyboard Shortcuts") {
0994 public void actionPerformed(ActionEvent e) {
0995 showHelpFrame("sec:developer:keyboard", "shortcuts");
0996 }
0997 }, this));
0998 helpMenu.addSeparator();
0999 helpMenu.add(new XJMenuItem(new AbstractAction("Using GATE Developer") {
1000 { this.putValue(Action.SHORT_DESCRIPTION, "To read first"); }
1001 public void actionPerformed(ActionEvent e) {
1002 showHelpFrame("chap:developer", "Using GATE Developer");
1003 }
1004 }, this));
1005 helpMenu.add(new XJMenuItem(new AbstractAction("Demo Movies") {
1006 { this.putValue(Action.SHORT_DESCRIPTION, "Movie tutorials"); }
1007 public void actionPerformed(ActionEvent e) {
1008 showHelpFrame("http://gate.ac.uk/demos/developer-videos/", "movies");
1009 }
1010 }, this));
1011 helpMenu.add(new XJMenuItem(new HelpMailingListAction(), this));
1012 helpMenu.addSeparator();
1013 JCheckBoxMenuItem toggleToolTipsCheckBoxMenuItem =
1014 new JCheckBoxMenuItem(new ToggleToolTipsAction());
1015 javax.swing.ToolTipManager toolTipManager =
1016 ToolTipManager.sharedInstance();
1017 if (Gate.getUserConfig().getBoolean(
1018 MainFrame.class.getName()+".hidetooltips")) {
1019 toolTipManager.setEnabled(false);
1020 toggleToolTipsCheckBoxMenuItem.setSelected(false);
1021 } else {
1022 toolTipManager.setEnabled(true);
1023 toggleToolTipsCheckBoxMenuItem.setSelected(true);
1024 }
1025 helpMenu.add(toggleToolTipsCheckBoxMenuItem);
1026 helpMenu.add(new XJMenuItem(new AbstractAction("What's New") {
1027 { this.putValue(Action.SHORT_DESCRIPTION,
1028 "List new features and important changes"); }
1029 public void actionPerformed(ActionEvent e) {
1030 showHelpFrame("chap:changes", "changes");
1031 }
1032 }, this));
1033 if(!Gate.runningOnMac()) {
1034 helpMenu.add(new XJMenuItem(new HelpAboutAction(), this));
1035 }
1036 menuBar.add(helpMenu);
1037
1038 this.setJMenuBar(menuBar);
1039
1040 // popups
1041 lrsPopup = new XJPopupMenu();
1042 LiveMenu lrsMenu = new LiveMenu(LiveMenu.LR);
1043 lrsMenu.setText("New");
1044 lrsPopup.add(lrsMenu);
1045 guiRoots.add(lrsPopup);
1046 guiRoots.add(lrsMenu);
1047
1048 prsPopup = new XJPopupMenu();
1049 LiveMenu prsMenu = new LiveMenu(LiveMenu.PR);
1050 prsMenu.setText("New");
1051 prsPopup.add(prsMenu);
1052 guiRoots.add(prsPopup);
1053 guiRoots.add(prsMenu);
1054
1055 dssPopup = new XJPopupMenu();
1056 dssPopup.add(new NewDSAction());
1057 dssPopup.add(new OpenDSAction());
1058 guiRoots.add(dssPopup);
1059
1060 // TOOLBAR
1061 toolbar = new JToolBar(JToolBar.HORIZONTAL);
1062 toolbar.setFloatable(false);
1063 JButton button = new JButton(new LoadResourceFromFileAction());
1064 button.setToolTipText(button.getText());
1065 button.setText("");
1066 toolbar.add(button);
1067 toolbar.addSeparator();
1068
1069 JPopupMenu annieMenu = new JPopupMenu();
1070 annieMenu.add(new LoadANNIEWithDefaultsAction());
1071 annieMenu.add(new LoadANNIEWithoutDefaultsAction());
1072 JMenuButton menuButton = new JMenuButton(annieMenu);
1073 menuButton.setIcon(getIcon("annie-application"));
1074 menuButton.setToolTipText("Load ANNIE System");
1075 toolbar.add(menuButton);
1076 toolbar.addSeparator();
1077
1078 LiveMenu tbNewLRMenu = new LiveMenu(LiveMenu.LR);
1079 menuButton = new JMenuButton(tbNewLRMenu);
1080 menuButton.setToolTipText("New Language Resource");
1081 menuButton.setIcon(getIcon("lrs"));
1082 toolbar.add(menuButton);
1083
1084 LiveMenu tbNewPRMenu = new LiveMenu(LiveMenu.PR);
1085 menuButton = new JMenuButton(tbNewPRMenu);
1086 menuButton.setToolTipText("New Processing Resource");
1087 menuButton.setIcon(getIcon("prs"));
1088 toolbar.add(menuButton);
1089
1090 LiveMenu tbNewAppMenu = new LiveMenu(LiveMenu.APP);
1091 menuButton = new JMenuButton(tbNewAppMenu);
1092 menuButton.setToolTipText("New Application");
1093 menuButton.setIcon(getIcon("applications"));
1094 toolbar.add(menuButton);
1095 toolbar.addSeparator();
1096
1097 JPopupMenu tbDsMenu = new JPopupMenu();
1098 tbDsMenu.add(new NewDSAction());
1099 tbDsMenu.add(new OpenDSAction());
1100 menuButton = new JMenuButton(tbDsMenu);
1101 menuButton.setToolTipText("Datastores");
1102 menuButton.setIcon(getIcon("datastores"));
1103 toolbar.add(menuButton);
1104
1105 toolbar.addSeparator();
1106 button = new JButton(new ManagePluginsAction());
1107 button.setToolTipText(button.getText());
1108 button.setText("");
1109 toolbar.add(button);
1110 toolbar.addSeparator();
1111 button = new JButton(new NewAnnotDiffAction());
1112 button.setToolTipText(button.getText());
1113 button.setText("");
1114 toolbar.add(button);
1115 toolbar.add(Box.createHorizontalGlue());
1116
1117 this.getContentPane().add(toolbar, BorderLayout.NORTH);
1118 }
1119
1120 protected void initListeners(boolean isShellSlacGIU) {
1121 Gate.getCreoleRegister().addCreoleListener(this);
1122
1123 resourcesTree.addKeyListener(new KeyAdapter() {
1124 public void keyPressed(KeyEvent e) {
1125 if(e.getKeyCode() == KeyEvent.VK_ENTER) {
1126 // shows in the central tabbed pane, the selected resources
1127 // in the resource tree when the Enter key is pressed
1128 (new ShowSelectedResourcesAction()).actionPerformed(null);
1129 } else if(e.getKeyCode() == KeyEvent.VK_DELETE) {
1130 // close selected resources from GATE
1131 (new CloseSelectedResourcesAction()).actionPerformed(null);
1132 } else if(e.getKeyCode() == KeyEvent.VK_DELETE
1133 && e.getModifiers() == InputEvent.SHIFT_DOWN_MASK) {
1134 // close recursively selected resources from GATE
1135 (new CloseRecursivelySelectedResourcesAction()).actionPerformed(null);
1136 }
1137 }
1138 });
1139
1140 resourcesTree.addMouseListener(new MouseAdapter() {
1141 public void mousePressed(MouseEvent e) {
1142 TreePath path =
1143 resourcesTree.getClosestPathForLocation(e.getX(), e.getY());
1144 if(e.isPopupTrigger()
1145 && !resourcesTree.isPathSelected(path)) {
1146 // if right click outside the selection then reset selection
1147 resourcesTree.getSelectionModel().setSelectionPath(path);
1148 }
1149 processMouseEvent(e);
1150 }
1151 public void mouseReleased(MouseEvent e) {
1152 processMouseEvent(e);
1153 }
1154 public void mouseClicked(MouseEvent e) {
1155 processMouseEvent(e);
1156 }
1157 protected void processMouseEvent(MouseEvent e){
1158 // where inside the tree?
1159 int x = e.getX();
1160 int y = e.getY();
1161 TreePath path = resourcesTree.getClosestPathForLocation(x, y);
1162 JPopupMenu popup = null;
1163 Handle handle = null;
1164 if(path != null) {
1165 Object value = path.getLastPathComponent();
1166 if(value == resourcesTreeRoot) {
1167 // no default item for this menu
1168 }
1169 else if(value == applicationsRoot) {
1170 appsPopup = new XJPopupMenu();
1171 LiveMenu appsMenu = new LiveMenu(LiveMenu.APP);
1172 appsMenu.setText("New");
1173 appsPopup.add(appsMenu);
1174 guiRoots.add(appsPopup);
1175 guiRoots.add(appsMenu);
1176 appsPopup.add(new XJMenuItem(new LoadResourceFromFileAction(),
1177 MainFrame.this));
1178 Component[] components = new RecentAppsMenu().getMenuComponents();
1179 if (components.length > 0) {
1180 appsPopup.addSeparator();
1181 appsPopup.add("Recent Applications:");
1182 }
1183 for (Component menuItem : components) {
1184 // add each menu item from the application recent menu
1185 appsPopup.add(menuItem);
1186 }
1187 popup = appsPopup;
1188 }
1189 else if(value == languageResourcesRoot) {
1190 popup = lrsPopup;
1191 }
1192 else if(value == processingResourcesRoot) {
1193 popup = prsPopup;
1194 }
1195 else if(value == datastoresRoot) {
1196 popup = dssPopup;
1197 }
1198 else {
1199 value = ((DefaultMutableTreeNode)value).getUserObject();
1200 if(value instanceof Handle) {
1201 handle = (Handle)value;
1202 fileChooser.setResource(handle.getTarget().getClass().getName());
1203 if(e.isPopupTrigger()) { popup = handle.getPopup(); }
1204 }
1205 }
1206 }
1207 // popup menu
1208 if(e.isPopupTrigger()) {
1209 if(resourcesTree.getSelectionCount() > 1) {
1210 // multiple selection in tree
1211 popup = new XJPopupMenu();
1212
1213 // add a close all action
1214 popup.add(new XJMenuItem(new CloseSelectedResourcesAction(),
1215 MainFrame.this));
1216
1217 // add a close recursively all action
1218 TreePath[] selectedPaths = resourcesTree.getSelectionPaths();
1219 for(TreePath selectedPath : selectedPaths) {
1220 Object userObject = ((DefaultMutableTreeNode)
1221 selectedPath.getLastPathComponent()).getUserObject();
1222 if(userObject instanceof NameBearerHandle
1223 && ((NameBearerHandle)userObject).getTarget()
1224 instanceof Controller) {
1225 // there is at least one application
1226 popup.add(new XJMenuItem(new
1227 CloseRecursivelySelectedResourcesAction(), MainFrame.this));
1228 break;
1229 }
1230 }
1231
1232 // add a show all action
1233 selectedPaths = resourcesTree.getSelectionPaths();
1234 for(TreePath selectedPath : selectedPaths) {
1235 Object userObject = ((DefaultMutableTreeNode)
1236 selectedPath.getLastPathComponent()).getUserObject();
1237 if (userObject instanceof Handle
1238 && ( ((Handle)userObject).getLargeView() == null
1239 || (mainTabbedPane.indexOfComponent(
1240 ((Handle)userObject).getLargeView()) == -1)) ) {
1241 // there is at least one resource not shown
1242 popup.add(new XJMenuItem(new ShowSelectedResourcesAction(),
1243 MainFrame.this));
1244 break;
1245 }
1246 }
1247
1248 // add a hide all action
1249 selectedPaths = resourcesTree.getSelectionPaths();
1250 for(TreePath selectedPath : selectedPaths) {
1251 Object userObject = ((DefaultMutableTreeNode)
1252 selectedPath.getLastPathComponent()).getUserObject();
1253 if (userObject instanceof Handle
1254 && ((Handle)userObject).viewsBuilt()
1255 && ((Handle)userObject).getLargeView() != null
1256 && (mainTabbedPane.indexOfComponent(
1257 ((Handle)userObject).getLargeView()) != -1)) {
1258 // there is at least one resource shown
1259 popup.add(new XJMenuItem(new CloseViewsForSelectedResourcesAction(),
1260 MainFrame.this));
1261 break;
1262 }
1263 }
1264
1265 popup.show(resourcesTree, e.getX(), e.getY());
1266 }
1267 else if(popup != null) {
1268 if(handle != null) {
1269
1270 // add a close action
1271 if(handle instanceof NameBearerHandle) {
1272 popup.insert(new XJMenuItem(((NameBearerHandle)handle)
1273 .getCloseAction(), MainFrame.this), 0);
1274 }
1275
1276 // if application then add a close recursively action
1277 if(handle instanceof NameBearerHandle
1278 && handle.getTarget() instanceof Controller) {
1279 popup.insert(new XJMenuItem(((NameBearerHandle)handle)
1280 .getCloseRecursivelyAction(), MainFrame.this), 1);
1281 }
1282
1283 // add a show/hide action
1284 if (handle.viewsBuilt() &&
1285 handle.getLargeView() != null
1286 && (mainTabbedPane.indexOfComponent(
1287 handle.getLargeView()) != -1)) {
1288 popup.insert(new XJMenuItem(new CloseViewAction(handle),
1289 MainFrame.this), 2);
1290 } else {
1291 popup.insert(new XJMenuItem(new ShowResourceAction(handle),
1292 MainFrame.this), 2);
1293 }
1294
1295 // add a rename action
1296 popup.insert(new XJMenuItem(new RenameResourceAction(path),
1297 MainFrame.this), 3);
1298
1299 // add a help action
1300 if(handle instanceof NameBearerHandle) {
1301 popup.insert(new XJMenuItem(new HelpOnItemTreeAction(
1302 (NameBearerHandle)handle), MainFrame.this), 4);
1303 }
1304 }
1305
1306 popup.show(resourcesTree, e.getX(), e.getY());
1307 }
1308 }
1309 else if(e.getID() == MouseEvent.MOUSE_CLICKED
1310 && e.getClickCount() == 2
1311 && handle != null) {
1312 // double click - show the resource
1313 select(handle);
1314 }
1315 }
1316 });
1317
1318 resourcesTree.addTreeSelectionListener(new TreeSelectionListener() {
1319 public void valueChanged(TreeSelectionEvent e) {
1320 if (!Gate.getUserConfig().getBoolean(
1321 MainFrame.class.getName()+".treeselectview")) {
1322 return;
1323 }
1324 // synchronise the selected tabbed pane with
1325 // the resource tree selection
1326 if (resourcesTree.getSelectionPaths() != null
1327 && resourcesTree.getSelectionPaths().length == 1) {
1328 Object value = e.getPath().getLastPathComponent();
1329 Object object = ((DefaultMutableTreeNode)value).getUserObject();
1330 if (object instanceof Handle
1331 && ((Handle)object).viewsBuilt()
1332 && (mainTabbedPane.indexOfComponent(
1333 ((Handle)object).getLargeView()) != -1)) {
1334 select((Handle)object);
1335 }
1336 }
1337 }
1338 });
1339
1340 // define keystrokes action bindings at the level of the main window
1341 InputMap inputMap = ((JComponent)this.getContentPane()).
1342 getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
1343 inputMap.put(KeyStroke.getKeyStroke("control F4"), "Close resource");
1344 inputMap.put(KeyStroke.getKeyStroke("shift F4"), "Close recursively");
1345 inputMap.put(KeyStroke.getKeyStroke("control H"), "Hide");
1346 inputMap.put(KeyStroke.getKeyStroke("control shift H"), "Hide all");
1347 inputMap.put(KeyStroke.getKeyStroke("control S"), "Save As XML");
1348
1349 // add the support of the context menu key in tables and trees
1350 // TODO: remove when Swing will take care of the context menu key
1351 if (inputMap.get(KeyStroke.getKeyStroke("CONTEXT_MENU")) == null) {
1352 inputMap.put(KeyStroke.getKeyStroke("CONTEXT_MENU"), "Show context menu");
1353 }
1354 ActionMap actionMap =
1355 ((JComponent)instance.getContentPane()).getActionMap();
1356 actionMap.put("Show context menu", new AbstractAction() {
1357 public void actionPerformed(ActionEvent e) {
1358 KeyboardFocusManager focusManager =
1359 KeyboardFocusManager.getCurrentKeyboardFocusManager();
1360 // get the current focused component
1361 Component focusedComponent = focusManager.getFocusOwner();
1362 if (focusedComponent != null) {
1363 Point menuLocation = null;
1364 Rectangle selectionRectangle = null;
1365 if (focusedComponent instanceof JTable
1366 && ((JTable)focusedComponent).getSelectedRowCount() > 0) {
1367 // selection in a JTable
1368 JTable table = (JTable)focusedComponent;
1369 selectionRectangle = table.getCellRect(
1370 table.getSelectionModel().getLeadSelectionIndex(),
1371 table.convertColumnIndexToView(table.getSelectedColumn()),
1372 false);
1373 } else if (focusedComponent instanceof JTree
1374 && ((JTree)focusedComponent).getSelectionCount() > 0) {
1375 // selection in a JTree
1376 JTree tree = (JTree)focusedComponent;
1377 selectionRectangle = tree.getRowBounds(
1378 tree.getSelectionModel().getLeadSelectionRow());
1379 } else {
1380 // for other component set the menu location at the top left corner
1381 menuLocation = new Point(focusedComponent.getX()-1,
1382 focusedComponent.getY()-1);
1383 }
1384 if (menuLocation == null) {
1385 // menu location at the bottom left of the JTable or JTree
1386 menuLocation = new Point(
1387 new Double(selectionRectangle.getMinX()+1).intValue(),
1388 new Double(selectionRectangle.getMaxY()-1).intValue());
1389 }
1390
1391 // generate a right/button 3/popup menu mouse click
1392 focusedComponent.dispatchEvent(
1393 new MouseEvent(focusedComponent, MouseEvent.MOUSE_PRESSED,
1394 e.getWhen(), MouseEvent.BUTTON3_DOWN_MASK,
1395 menuLocation.x, menuLocation.y,
1396 1, true, MouseEvent.BUTTON3));
1397 }
1398 }
1399 });
1400
1401 mainTabbedPane.getModel().addChangeListener(new ChangeListener() {
1402 public void stateChanged(ChangeEvent e) {
1403 // find the handle in the resources tree for the main view
1404 JComponent largeView =
1405 (JComponent)mainTabbedPane.getSelectedComponent();
1406 Enumeration nodesEnum = resourcesTreeRoot.preorderEnumeration();
1407 boolean done = false;
1408 DefaultMutableTreeNode node = resourcesTreeRoot;
1409 while(!done && nodesEnum.hasMoreElements()) {
1410 node = (DefaultMutableTreeNode)nodesEnum.nextElement();
1411 done =
1412 node.getUserObject() instanceof Handle
1413 && ((Handle)node.getUserObject()).viewsBuilt()
1414 && ((Handle)node.getUserObject()).getLargeView() == largeView;
1415 }
1416 ActionMap actionMap =
1417 ((JComponent)instance.getContentPane()).getActionMap();
1418 if(done) {
1419 Handle handle = (Handle)node.getUserObject();
1420 if (Gate.getUserConfig().getBoolean(
1421 MainFrame.class.getName()+".viewselecttree")) {
1422 // synchronise the selection in the tabbed pane with
1423 // the one in the resources tree
1424 TreePath nodePath = new TreePath(node.getPath());
1425 resourcesTree.setSelectionPath(nodePath);
1426 resourcesTree.scrollPathToVisible(nodePath);
1427 }
1428 lowerScroll.getViewport().setView(handle.getSmallView());
1429
1430 // redefine MainFrame actionMaps for the selected tab
1431 JComponent resource =
1432 (JComponent)mainTabbedPane.getSelectedComponent();
1433 actionMap.put("Close resource",
1434 resource.getActionMap().get("Close resource"));
1435 actionMap.put("Close recursively",
1436 resource.getActionMap().get("Close recursively"));
1437 actionMap.put("Hide", new CloseViewAction(handle));
1438 actionMap.put("Hide all", new HideAllAction());
1439 actionMap.put("Save As XML",
1440 resource.getActionMap().get("Save As XML"));
1441 }
1442 else {
1443 // the selected item is not a resource (maybe the log area?)
1444 lowerScroll.getViewport().setView(null);
1445 // disabled actions on the selected tabbed pane
1446 actionMap.put("Close resource", null);
1447 actionMap.put("Close recursively", null);
1448 actionMap.put("Hide", null);
1449 actionMap.put("Hide all", null);
1450 actionMap.put("Save As XML", null);
1451 }
1452 }
1453 });
1454
1455 mainTabbedPane.addMouseListener(new MouseAdapter() {
1456 public void mousePressed(MouseEvent e) {
1457 processMouseEvent(e);
1458 }
1459 public void mouseReleased(MouseEvent e) {
1460 processMouseEvent(e);
1461 }
1462 protected void processMouseEvent(MouseEvent e){
1463 if(e.isPopupTrigger()) {
1464 int index = mainTabbedPane.getIndexAt(e.getPoint());
1465 if(index != -1) {
1466 JComponent view = (JComponent)mainTabbedPane.getComponentAt(index);
1467 Enumeration nodesEnum = resourcesTreeRoot.preorderEnumeration();
1468 boolean done = false;
1469 DefaultMutableTreeNode node = resourcesTreeRoot;
1470 while(!done && nodesEnum.hasMoreElements()) {
1471 node = (DefaultMutableTreeNode)nodesEnum.nextElement();
1472 done = node.getUserObject() instanceof Handle
1473 && ((Handle)node.getUserObject()).viewsBuilt()
1474 && ((Handle)node.getUserObject()).getLargeView() == view;
1475 }
1476 if(done) {
1477 Handle handle = (Handle)node.getUserObject();
1478 JPopupMenu popup = handle.getPopup();
1479
1480 // add a hide action
1481 CloseViewAction cva = new CloseViewAction(handle);
1482 XJMenuItem menuItem = new XJMenuItem(cva, MainFrame.this);
1483 popup.insert(menuItem, 0);
1484
1485 // add a hide all action
1486 if (mainTabbedPane.getTabCount() > 2) {
1487 HideAllAction haa = new HideAllAction();
1488 menuItem = new XJMenuItem(haa, MainFrame.this);
1489 popup.insert(menuItem, 1);
1490 }
1491
1492 popup.show(mainTabbedPane, e.getX(), e.getY());
1493 }
1494 }
1495 }
1496 }
1497 });
1498
1499 addComponentListener(new ComponentAdapter() {
1500 public void componentShown(ComponentEvent e) {
1501 leftSplit.setDividerLocation(0.7);
1502 }
1503 public void componentResized(ComponentEvent e) {
1504 // resize proportionally the status bar elements
1505 int width = MainFrame.this.getWidth();
1506 statusBar.setPreferredSize(new Dimension(width*65/100,
1507 statusBar.getPreferredSize().height));
1508 progressBar.setPreferredSize(new Dimension(width*20/100,
1509 progressBar.getPreferredSize().height));
1510 progressBar.setMinimumSize(new Dimension(80, 0));
1511 globalProgressBar.setPreferredSize(new Dimension(width*10/100,
1512 globalProgressBar.getPreferredSize().height));
1513 globalProgressBar.setMinimumSize(new Dimension(80, 0));
1514 }
1515 });
1516
1517 if(isShellSlacGIU) {
1518 mainSplit.setDividerSize(0);
1519 mainSplit.getTopComponent().setVisible(false);
1520 mainSplit.getTopComponent().addComponentListener(new ComponentAdapter() {
1521 public void componentHidden(ComponentEvent e) {
1522 }
1523
1524 public void componentMoved(ComponentEvent e) {
1525 mainSplit.setDividerLocation(0);
1526 }
1527
1528 public void componentResized(ComponentEvent e) {
1529 mainSplit.setDividerLocation(0);
1530 }
1531
1532 public void componentShown(ComponentEvent e) {
1533 mainSplit.setDividerLocation(0);
1534 }
1535 });
1536 } // if
1537
1538 // blink the messages tab when new information is displayed
1539 logArea.getDocument().addDocumentListener(
1540 new javax.swing.event.DocumentListener() {
1541 public void insertUpdate(javax.swing.event.DocumentEvent e) {
1542 changeOccured();
1543 }
1544
1545 public void removeUpdate(javax.swing.event.DocumentEvent e) {
1546 changeOccured();
1547 }
1548
1549 public void changedUpdate(javax.swing.event.DocumentEvent e) {
1550 }
1551
1552 protected void changeOccured() {
1553 logHighlighter.highlight();
1554 }
1555 });
1556
1557 logArea.addPropertyChangeListener("document", new PropertyChangeListener() {
1558 public void propertyChange(PropertyChangeEvent evt) {
1559 // add the document listener
1560 logArea.getDocument().addDocumentListener(
1561 new javax.swing.event.DocumentListener() {
1562 public void insertUpdate(javax.swing.event.DocumentEvent e) {
1563 changeOccured();
1564 }
1565
1566 public void removeUpdate(javax.swing.event.DocumentEvent e) {
1567 changeOccured();
1568 }
1569
1570 public void changedUpdate(javax.swing.event.DocumentEvent e) {
1571 changeOccured();
1572 }
1573
1574 protected void changeOccured() {
1575 logHighlighter.highlight();
1576 }
1577 });
1578 }
1579 });
1580
1581 Gate.listeners.put("gate.event.StatusListener", MainFrame.this);
1582 Gate.listeners.put("gate.event.ProgressListener", MainFrame.this);
1583 if(Gate.runningOnMac()) {
1584 // mac-specific initialisation
1585 initMacListeners();
1586 }
1587 }// protected void initListeners()
1588
1589 /**
1590 * Set up the handlers to support the Macintosh Application menu. This
1591 * makes the About, Quit and Preferences menu items map to their
1592 * equivalents in GATE. If an exception occurs during this process we
1593 * print a warning.
1594 */
1595 protected void initMacListeners() {
1596 // What this method effectively does is:
1597 //
1598 // com.apple.eawt.Application app = Application.getApplication();
1599 // app.addApplicationListener(new ApplicationAdapter() {
1600 // public void handleAbout(ApplicationEvent e) {
1601 // e.setHandled(true);
1602 // new HelpAboutAction().actionPerformed(null);
1603 // }
1604 // public void handleQuit(ApplicationEvent e) {
1605 // e.setHandled(false);
1606 // new ExitGateAction().actionPerformed(null);
1607 // }
1608 // public void handlePreferences(ApplicationEvent e) {
1609 // e.setHandled(true);
1610 // optionsDialog.showDialog();
1611 // optionsDialog.dispose();
1612 // }
1613 // });
1614 //
1615 // app.setEnabledPreferencesMenu(true);
1616 //
1617 // except that it does it all by reflection so as not to
1618 // compile-time
1619 // depend on Apple classes.
1620 try {
1621 // load the Apple classes
1622 final Class eawtApplicationClass =
1623 Gate.getClassLoader().loadClass("com.apple.eawt.Application");
1624 final Class eawtApplicationListenerInterface =
1625 Gate.getClassLoader().loadClass("com.apple.eawt.ApplicationListener");
1626 final Class eawtApplicationEventClass =
1627 Gate.getClassLoader().loadClass("com.apple.eawt.ApplicationEvent");
1628
1629 // method used in the InvocationHandler
1630 final Method appEventSetHandledMethod =
1631 eawtApplicationEventClass.getMethod("setHandled", boolean.class);
1632
1633 // Invocation handler used to process Apple application events
1634 InvocationHandler handler = new InvocationHandler() {
1635 private Action aboutAction = new HelpAboutAction();
1636
1637 private Action exitAction = new ExitGateAction();
1638
1639 public Object invoke(Object proxy, Method method, Object[] args)
1640 throws Throwable {
1641 Object appEvent = args[0];
1642 if("handleAbout".equals(method.getName())) {
1643 appEventSetHandledMethod.invoke(appEvent, Boolean.TRUE);
1644 aboutAction.actionPerformed(null);
1645 }
1646 else if("handleQuit".equals(method.getName())) {
1647 appEventSetHandledMethod.invoke(appEvent, Boolean.FALSE);
1648 exitAction.actionPerformed(null);
1649 }
1650 else if("handlePreferences".equals(method.getName())) {
1651 appEventSetHandledMethod.invoke(appEvent, Boolean.TRUE);
1652 optionsDialog.showDialog();
1653 optionsDialog.dispose();
1654 }
1655
1656 return null;
1657 }
1658 };
1659
1660 // Create an ApplicationListener proxy instance
1661 Object applicationListenerObject =
1662 Proxy.newProxyInstance(Gate.getClassLoader(),
1663 new Class[]{eawtApplicationListenerInterface}, handler);
1664
1665 // get hold of the Application object
1666 Method getApplicationMethod =
1667 eawtApplicationClass.getMethod("getApplication");
1668 Object applicationObject = getApplicationMethod.invoke(null);
1669
1670 // enable the preferences menu item
1671 Method setEnabledPreferencesMenuMethod =
1672 eawtApplicationClass.getMethod("setEnabledPreferencesMenu",
1673 boolean.class);
1674 setEnabledPreferencesMenuMethod.invoke(applicationObject, Boolean.TRUE);
1675
1676 // Register our proxy instance as an ApplicationListener
1677 Method addApplicationListenerMethod =
1678 eawtApplicationClass.getMethod("addApplicationListener",
1679 eawtApplicationListenerInterface);
1680 addApplicationListenerMethod.invoke(applicationObject,
1681 applicationListenerObject);
1682 }
1683 catch(Throwable error) {
1684 // oh well, we tried
1685 String message =
1686 "There was a problem setting up the Mac "
1687 + "application\nmenu. Your options/session will not be saved if "
1688 + "you exit\nwith \u2318Q, use the close button at the top-left"
1689 + "corner\nof this window instead.";
1690 alertButton.setAction(new AlertAction(error, message, null));
1691 }
1692 }
1693
1694 public void progressChanged(int i) {
1695 // progressBar.setStringPainted(true);
1696 int oldValue = progressBar.getValue();
1697 // if((!stopAction.isEnabled()) &&
1698 // (Gate.getExecutable() != null)){
1699 // stopAction.setEnabled(true);
1700 // SwingUtilities.invokeLater(new Runnable(){
1701 // public void run(){
1702 // southBox.add(stopBtn, 0);
1703 // }
1704 // });
1705 // }
1706 if(!animator.isActive()) animator.activate();
1707 if(oldValue != i) {
1708 SwingUtilities.invokeLater(new ProgressBarUpdater(i));
1709 }
1710 }
1711
1712 /**
1713 * Called when the process is finished.
1714 *
1715 */
1716 public void processFinished() {
1717 // progressBar.setStringPainted(false);
1718 // if(stopAction.isEnabled()){
1719 // stopAction.setEnabled(false);
1720 // SwingUtilities.invokeLater(new Runnable(){
1721 // public void run(){
1722 // southBox.remove(stopBtn);
1723 // }
1724 // });
1725 // }
1726 SwingUtilities.invokeLater(new ProgressBarUpdater(0));
1727 SwingUtilities.invokeLater(new Runnable() { public void run() {
1728 globalProgressBar.setVisible(false);
1729 }});
1730 animator.deactivate();
1731 }
1732
1733 /**
1734 * Regular expression pattern for the "Start running" message.
1735 */
1736 private static final Pattern START_RUNNING_PATTERN =
1737 Pattern.compile("Start running .* on (\\d+) documents?");
1738
1739 public void statusChanged(String text) {
1740 SwingUtilities.invokeLater(new StatusBarUpdater(text));
1741 if (text != null) {
1742 Matcher m = START_RUNNING_PATTERN.matcher(text);
1743 if (m.matches()) {
1744 // get the corpus size from the status text
1745 final int corpusSize = Integer.valueOf(m.group(1));
1746 SwingUtilities.invokeLater(new Runnable() { public void run() {
1747 // initialise the progress bar
1748 globalProgressBar.setMaximum(corpusSize);
1749 globalProgressBar.setValue(0);
1750 globalProgressBar.setString("0/" + corpusSize);
1751 globalProgressBar.setVisible(true);
1752 }});
1753 } else if (text.startsWith("Finished running ")) {
1754 SwingUtilities.invokeLater(new Runnable() { public void run() {
1755 // update the progress bar with one document processed
1756 globalProgressBar.setValue(globalProgressBar.getValue() + 1);
1757 globalProgressBar.setString(globalProgressBar.getValue() + "/"
1758 + globalProgressBar.getMaximum());
1759 }});
1760 }
1761 }
1762 }
1763
1764 public void resourceLoaded(CreoleEvent e) {
1765 final Resource res = e.getResource();
1766 if(Gate.getHiddenAttribute(res.getFeatures())
1767 || res instanceof VisualResource) return;
1768 SwingUtilities.invokeLater(new Runnable() {
1769 public void run() {
1770 NameBearerHandle handle = new NameBearerHandle(res, MainFrame.this);
1771 DefaultMutableTreeNode node = new DefaultMutableTreeNode(handle, false);
1772 if(res instanceof Controller) {
1773 resourcesTreeModel.insertNodeInto(node, applicationsRoot, 0);
1774 } else if(res instanceof ProcessingResource) {
1775 resourcesTreeModel.insertNodeInto(node, processingResourcesRoot, 0);
1776 }
1777 else if(res instanceof LanguageResource) {
1778 resourcesTreeModel.insertNodeInto(node, languageResourcesRoot, 0);
1779 }
1780
1781 handle.addProgressListener(MainFrame.this);
1782 handle.addStatusListener(MainFrame.this);
1783 }
1784 });
1785
1786 // JPopupMenu popup = handle.getPopup();
1787 //
1788 // // Create a CloseViewAction and a menu item based on it
1789 // CloseViewAction cva = new CloseViewAction(handle);
1790 // XJMenuItem menuItem = new XJMenuItem(cva, this);
1791 // // Add an accelerator ATL+F4 for this action
1792 // menuItem.setAccelerator(KeyStroke.getKeyStroke(
1793 // KeyEvent.VK_H, ActionEvent.CTRL_MASK));
1794 // popup.insert(menuItem, 1);
1795 // popup.insert(new JPopupMenu.Separator(), 2);
1796 //
1797 // popup.insert(new XJMenuItem(
1798 // new RenameResourceAction(
1799 // new TreePath(resourcesTreeModel.getPathToRoot(node))),
1800 // MainFrame.this) , 3);
1801 //
1802 // // Put the action command in the component's action map
1803 // if (handle.getLargeView() != null)
1804 // handle.getLargeView().getActionMap().put("Hide current
1805 // view",cva);
1806 //
1807 }// resourceLoaded();
1808
1809 public void resourceUnloaded(CreoleEvent e) {
1810 final Resource res = e.getResource();
1811 if(Gate.getHiddenAttribute(res.getFeatures())) return;
1812 Runnable runner = new Runnable() {
1813 public void run() {
1814 DefaultMutableTreeNode node;
1815 DefaultMutableTreeNode parent = null;
1816 if(res instanceof Controller) {
1817 parent = applicationsRoot;
1818 }else if(res instanceof ProcessingResource) {
1819 parent = processingResourcesRoot;
1820 }
1821 else if(res instanceof LanguageResource) {
1822 parent = languageResourcesRoot;
1823 }
1824 if(parent != null) {
1825 Enumeration children = parent.children();
1826 while(children.hasMoreElements()) {
1827 node = (DefaultMutableTreeNode)children.nextElement();
1828 if(((NameBearerHandle)node.getUserObject()).getTarget() == res) {
1829 resourcesTreeModel.removeNodeFromParent(node);
1830 Handle handle = (Handle)node.getUserObject();
1831 if(handle.viewsBuilt()) {
1832 if(mainTabbedPane.indexOfComponent(handle.getLargeView()) != -1)
1833 mainTabbedPane.remove(handle.getLargeView());
1834 if(lowerScroll.getViewport().getView() == handle.getSmallView())
1835 lowerScroll.getViewport().setView(null);
1836 }
1837 handle.cleanup();
1838 return;
1839 }
1840 }
1841 }
1842 }
1843 };
1844 SwingUtilities.invokeLater(runner);
1845 }
1846
1847 /** Called when a {@link gate.DataStore} has been opened */
1848 public void datastoreOpened(CreoleEvent e) {
1849 DataStore ds = e.getDatastore();
1850 if(ds.getName() == null || ds.getName().length() == 0){
1851 String name = ds.getStorageUrl();
1852 StringBuilder nameBuilder = new StringBuilder();
1853 //quick and dirty FSA
1854 int state = 0;
1855 for(int i = name.length() -1; i >= 0 && state != 2 ; i--){
1856 char currentChar = name.charAt(i);
1857 switch (state) {
1858 case 0:
1859 //consuming slashes at the end
1860 if(currentChar == '/'){
1861 //consume
1862 }else{
1863 //we got the first non-slash char
1864 state = 1;
1865 nameBuilder.insert(0, currentChar);
1866 }
1867 break;
1868 case 1:
1869 //eating up name chars
1870 if(currentChar == '/'){
1871 //we're done!
1872 state = 2;
1873 }else{
1874 //we got a non-slash char
1875 nameBuilder.insert(0, currentChar);
1876 }
1877 break;
1878 default:
1879 throw new LuckyException("A phanthom state of things!");
1880 }
1881 }
1882 if(nameBuilder.length() > 0) name = nameBuilder.toString();
1883 ds.setName(name);
1884 }
1885
1886 NameBearerHandle handle = new NameBearerHandle(ds, MainFrame.this);
1887 DefaultMutableTreeNode node = new DefaultMutableTreeNode(handle, false);
1888 resourcesTreeModel.insertNodeInto(node, datastoresRoot, 0);
1889 handle.addProgressListener(MainFrame.this);
1890 handle.addStatusListener(MainFrame.this);
1891
1892 // JPopupMenu popup = handle.getPopup();
1893 // popup.addSeparator();
1894 // // Create a CloseViewAction and a menu item based on it
1895 // CloseViewAction cva = new CloseViewAction(handle);
1896 // XJMenuItem menuItem = new XJMenuItem(cva, this);
1897 // // Add an accelerator ATL+F4 for this action
1898 // menuItem.setAccelerator(KeyStroke.getKeyStroke(
1899 // KeyEvent.VK_H, ActionEvent.CTRL_MASK));
1900 // popup.add(menuItem);
1901 // // Put the action command in the component's action map
1902 // if (handle.getLargeView() != null)
1903 // handle.getLargeView().getActionMap().put("Hide current
1904 // view",cva);
1905 }// datastoreOpened();
1906
1907 /** Called when a {@link gate.DataStore} has been created */
1908 public void datastoreCreated(CreoleEvent e) {
1909 datastoreOpened(e);
1910 }
1911
1912 /** Called when a {@link gate.DataStore} has been closed */
1913 public void datastoreClosed(CreoleEvent e) {
1914 DataStore ds = e.getDatastore();
1915 DefaultMutableTreeNode node;
1916 DefaultMutableTreeNode parent = datastoresRoot;
1917 if(parent != null) {
1918 Enumeration children = parent.children();
1919 while(children.hasMoreElements()) {
1920 node = (DefaultMutableTreeNode)children.nextElement();
1921 if(((NameBearerHandle)node.getUserObject()).getTarget() == ds) {
1922 resourcesTreeModel.removeNodeFromParent(node);
1923 NameBearerHandle handle = (NameBearerHandle)node.getUserObject();
1924
1925 if(handle.viewsBuilt()
1926 && mainTabbedPane.indexOfComponent(handle.getLargeView()) != -1) {
1927 mainTabbedPane.remove(handle.getLargeView());
1928 }
1929 if(lowerScroll.getViewport().getView() == handle.getSmallView()) {
1930 lowerScroll.getViewport().setView(null);
1931 }
1932 return;
1933 }
1934 }
1935 }
1936 }
1937
1938 public void resourceRenamed(Resource resource, String oldName, String newName) {
1939 //first find the handle for the renamed resource
1940 Handle handle = findHandleForResource(resource);
1941 if(handle != null){
1942 //next see if there is a tab for this resource and rename it
1943 for(int i = 0; i < mainTabbedPane.getTabCount(); i++) {
1944 if(mainTabbedPane.getTitleAt(i).equals(oldName) &&
1945 mainTabbedPane.getComponentAt(i) == handle.getLargeView()) {
1946 mainTabbedPane.setTitleAt(i, newName);
1947 return;
1948 }
1949 }
1950 }
1951 }
1952
1953 /**
1954 * Overridden so we can exit when window is closed
1955 */
1956 protected void processWindowEvent(WindowEvent e) {
1957 if(e.getID() == WindowEvent.WINDOW_CLOSING) {
1958 new ExitGateAction().actionPerformed(null);
1959 }
1960 super.processWindowEvent(e);
1961 }// processWindowEvent(WindowEvent e)
1962
1963 /**
1964 * Returns the listeners map, a map that holds all the listeners that
1965 * are singletons (e.g. the status listener that updates the status
1966 * bar on the main frame or the progress listener that updates the
1967 * progress bar on the main frame). The keys used are the class names
1968 * of the listener interface and the values are the actual listeners
1969 * (e.g "gate.event.StatusListener" -> this). The returned map is the
1970 * actual data member used to store the listeners so any changes in
1971 * this map will be visible to everyone.
1972 * @return the listeners map
1973 * @deprecated Use {@link Gate#getListeners()} instead
1974 */
1975 public static java.util.Map<String, EventListener> getListeners() {
1976 return Gate.getListeners();
1977 }
1978
1979 public static java.util.Collection<Component> getGuiRoots() {
1980 return guiRoots;
1981 }
1982
1983 /**
1984 * This method will lock all input to the gui by means of a modal
1985 * dialog. If Gate is not currently running in GUI mode this call will
1986 * be ignored. A call to this method while the GUI is locked will
1987 * cause the GUI to be unlocked and then locked again with the new
1988 * message. If a message is provided it will show in the dialog.
1989 *
1990 * @param message the message to be displayed while the GUI is locked
1991 */
1992 public synchronized static void lockGUI(final String message) {
1993 // check whether GUI is up
1994 if(getGuiRoots() == null || getGuiRoots().isEmpty()) return;
1995 // if the GUI is locked unlock it so we can show the new message
1996 unlockGUI();
1997
1998 // this call needs to return so we'll show the dialog from a
1999 // different thread
2000 // the Swing thread sounds good for that
2001 SwingUtilities.invokeLater(new Runnable() {
2002 public void run() {
2003 // build the dialog contents
2004 Object[] options = new Object[]{new JButton(new StopAction())};
2005 JOptionPane pane =
2006 new JOptionPane(message, JOptionPane.WARNING_MESSAGE,
2007 JOptionPane.DEFAULT_OPTION, null, options, null);
2008
2009 // build the dialog
2010 Component parentComp = (Component)((ArrayList)getGuiRoots()).get(0);
2011 JDialog dialog;
2012 Window parentWindow;
2013 if(parentComp instanceof Window)
2014 parentWindow = (Window)parentComp;
2015 else parentWindow = SwingUtilities.getWindowAncestor(parentComp);
2016 if(parentWindow instanceof Frame) {
2017 dialog = new JDialog((Frame)parentWindow, "Please wait", true) {
2018 private static final long serialVersionUID = 1L;
2019 protected void processWindowEvent(WindowEvent e) {
2020 if(e.getID() == WindowEvent.WINDOW_CLOSING) {
2021 getToolkit().beep();
2022 }
2023 }
2024 };
2025 }
2026 else if(parentWindow instanceof Dialog) {
2027 dialog = new JDialog((Dialog)parentWindow, "Please wait", true) {
2028 private static final long serialVersionUID = 1L;
2029 protected void processWindowEvent(WindowEvent e) {
2030 if(e.getID() == WindowEvent.WINDOW_CLOSING) {
2031 getToolkit().beep();
2032 }
2033 }
2034 };
2035 }
2036 else {
2037 dialog = new JDialog(JOptionPane.getRootFrame(), "Please wait", true) {
2038 private static final long serialVersionUID = 1L;
2039 protected void processWindowEvent(WindowEvent e) {
2040 if(e.getID() == WindowEvent.WINDOW_CLOSING) {
2041 getToolkit().beep();
2042 }
2043 }
2044 };
2045 }
2046 dialog.getContentPane().setLayout(new BorderLayout());
2047 dialog.getContentPane().add(pane, BorderLayout.CENTER);
2048 dialog.pack();
2049 dialog.setLocationRelativeTo(parentComp);
2050 dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
2051 guiLock = dialog;
2052
2053 guiLock.setVisible(true);
2054 }
2055 });
2056
2057 // this call should not return until the dialog is up to ensure
2058 // proper
2059 // sequentiality for lock - unlock calls
2060 while(guiLock == null || !guiLock.isShowing()) {
2061 try {
2062 Thread.sleep(100);
2063 }
2064 catch(InterruptedException ie) {
2065 log.debug("Interrupted sleep when the GUI is locked.", ie);
2066 }
2067 }
2068 }
2069
2070 public synchronized static void unlockGUI() {
2071 // check whether GUI is up
2072 if(getGuiRoots() == null || getGuiRoots().isEmpty()) return;
2073
2074 if(guiLock != null) {
2075 guiLock.setVisible(false);
2076 // completely dispose the dialog (causes it to disappear even if
2077 // displayed on a non-visible virtual display on Linux)
2078 // fix for bug 1369096
2079 // (http://sourceforge.net/tracker/index.php?func=detail&aid=1369096&group_id=143829&atid=756796)
2080 guiLock.dispose();
2081 }
2082 guiLock = null;
2083 }
2084
2085 /** Flag to protect Frame title to be changed */
2086 private boolean titleChangable = false;
2087
2088 public void setTitleChangable(boolean isChangable) {
2089 titleChangable = isChangable;
2090 } // setTitleChangable(boolean isChangable)
2091
2092 /** Override to avoid Protege to change Frame title */
2093 public synchronized void setTitle(String title) {
2094 if(titleChangable) {
2095 super.setTitle(title);
2096 } // if
2097 } // setTitle(String title)
2098
2099 /**
2100 * Method is used in NewDSAction
2101 * @return the new datastore or null if an error occurs
2102 */
2103 protected DataStore createSerialDataStore() {
2104 DataStore ds = null;
2105
2106 // get the URL (a file in this case)
2107 fileChooser.setDialogTitle("Please create a new empty directory");
2108 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2109 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
2110 fileChooser.setResource("gate.persist.SerialDataStore");
2111 if(fileChooser.showOpenDialog(MainFrame.this)
2112 == JFileChooser.APPROVE_OPTION) {
2113 try {
2114 URL dsURL = fileChooser.getSelectedFile().toURI().toURL();
2115 ds =
2116 Factory.createDataStore("gate.persist.SerialDataStore", dsURL
2117 .toExternalForm());
2118 }
2119 catch(MalformedURLException mue) {
2120 JOptionPane.showMessageDialog(MainFrame.this,
2121 "Invalid location for the datastore\n " + mue.toString(), "GATE",
2122 JOptionPane.ERROR_MESSAGE);
2123 }
2124 catch(PersistenceException pe) {
2125 JOptionPane.showMessageDialog(MainFrame.this,
2126 "Datastore creation error!\n " + pe.toString(), "GATE",
2127 JOptionPane.ERROR_MESSAGE);
2128 } // catch
2129 } // if
2130
2131 return ds;
2132 } // createSerialDataStore()
2133
2134 /**
2135 * Method is used in OpenDSAction
2136 * @return the opened datastore or null if an error occurs
2137 */
2138 protected DataStore openSerialDataStore() {
2139 DataStore ds = null;
2140
2141 // get the URL (a file in this case)
2142 fileChooser.setDialogTitle("Select the datastore directory");
2143 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2144 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
2145 fileChooser.setResource("gate.persist.SerialDataStore");
2146 if(fileChooser.showOpenDialog(MainFrame.this)
2147 == JFileChooser.APPROVE_OPTION) {
2148 try {
2149 URL dsURL = fileChooser.getSelectedFile().toURI().toURL();
2150 ds =
2151 Factory.openDataStore("gate.persist.SerialDataStore", dsURL
2152 .toExternalForm());
2153 }
2154 catch(MalformedURLException mue) {
2155 JOptionPane.showMessageDialog(MainFrame.this,
2156 "Invalid location for the datastore\n " + mue.toString(), "GATE",
2157 JOptionPane.ERROR_MESSAGE);
2158 }
2159 catch(PersistenceException pe) {
2160 JOptionPane.showMessageDialog(MainFrame.this,
2161 "Datastore opening error!\n " + pe.toString(), "GATE",
2162 JOptionPane.ERROR_MESSAGE);
2163 } // catch
2164 } // if
2165
2166 return ds;
2167 } // openSerialDataStore()
2168
2169 /**
2170 * Method is used in ....OpenDSAction
2171 * @return the opened datastore or null if an error occurs
2172 */
2173 protected DataStore openDocServiceDataStore() {
2174 DataStore ds = null;
2175 try {
2176 String DSLocation =
2177 JOptionPane.showInputDialog(MainFrame.this,
2178 "Enter document service URL",
2179 "http://localhost:8080/docservice/services/docservice");
2180 // System.out.println("DEBUG: MainFrame.openDocServiceDataStore()
2181 // DSLocation='" + DSLocation + "'");
2182 ds =
2183 Factory.openDataStore("gleam.docservice.gate.DocServiceDataStore",
2184 DSLocation);
2185 }
2186 catch(Exception error) {
2187 String message = "Error when opening the Datastore.";
2188 alertButton.setAction(new AlertAction(error, message, null));
2189 }
2190 return ds;
2191 } // openWSDataStore()
2192
2193 /*
2194 * synchronized void showWaitDialog() { Point location =
2195 * getLocationOnScreen(); location.translate(10, getHeight() -
2196 * waitDialog.getHeight() - southBox.getHeight() - 10);
2197 * waitDialog.setLocation(location); waitDialog.showDialog(new
2198 * Component[]{}); }
2199 *
2200 * synchronized void hideWaitDialog() { waitDialog.goAway(); }
2201 */
2202
2203 /*
2204 * class NewProjectAction extends AbstractAction { public
2205 * NewProjectAction(){ super("New Project", new
2206 * ImageIcon(MainFrame.class.getResource(
2207 * "/gate/resources/img/newProject")));
2208 * putValue(SHORT_DESCRIPTION,"Create a new project"); } public void
2209 * actionPerformed(ActionEvent e){ fileChooser.setDialogTitle("Select
2210 * new project file");
2211 * fileChooser.setFileSelectionMode(fileChooser.FILES_ONLY);
2212 * if(fileChooser.showOpenDialog(parentFrame) ==
2213 * fileChooser.APPROVE_OPTION){ ProjectData pData = new
2214 * ProjectData(fileChooser.getSelectedFile(), parentFrame);
2215 * addProject(pData); } } }
2216 */
2217
2218 /** This class represent an action which brings up the Annot Diff tool */
2219 class NewAnnotDiffAction extends AbstractAction {
2220 private static final long serialVersionUID = 1L;
2221 public NewAnnotDiffAction() {
2222 super("Annotation Diff", getIcon("annotation-diff"));
2223 putValue(SHORT_DESCRIPTION,
2224 "Compare annotations and features in one or two documents");
2225 }
2226 public void actionPerformed(ActionEvent e) {
2227 // find the handle in the resource tree for the displayed view
2228 Enumeration nodesEnum = resourcesTreeRoot.preorderEnumeration();
2229 DefaultMutableTreeNode node;
2230 Handle handle = null;
2231 while(nodesEnum.hasMoreElements()) {
2232 node = (DefaultMutableTreeNode)nodesEnum.nextElement();
2233 if ((node.getUserObject() instanceof Handle)
2234 && (mainTabbedPane.getSelectedComponent().equals(
2235 ((Handle)node.getUserObject()).getLargeView()))) {
2236 handle = (Handle)node.getUserObject();
2237 break;
2238 }
2239 }
2240 String documentName = null;
2241 if(handle != null
2242 && handle.getTarget() instanceof Document) {
2243 documentName = ((Document)handle.getTarget()).getName();
2244 }
2245 AnnotationDiffGUI frame;
2246 if (documentName != null) {
2247 // use the document displayed in the view to compute the differences
2248 frame = new AnnotationDiffGUI("Annotation Diff Tool",
2249 documentName, documentName, null, null, null, null);
2250 } else {
2251 frame = new AnnotationDiffGUI("Annotation Diff Tool");
2252 }
2253 frame.pack();
2254 frame.setLocationRelativeTo(MainFrame.this);
2255 frame.setVisible(true);
2256 }
2257 }
2258
2259 /**
2260 * This class represent an action which brings up the corpus
2261 * evaluation tool
2262 */
2263 class NewCorpusEvalAction extends AbstractAction {
2264 private static final long serialVersionUID = 1L;
2265 public NewCorpusEvalAction() {
2266 super("Default Mode");
2267 putValue(SHORT_DESCRIPTION, "Compares stored processed set with current" +
2268 " processed set and human-annotated set");
2269 putValue(SMALL_ICON, getIcon("corpus-benchmark"));
2270 }// newCorpusEvalAction
2271
2272 public void actionPerformed(ActionEvent e) {
2273 Runnable runnable = new Runnable() {
2274 public void run() {
2275 fileChooser.setDialogTitle("Please select a directory which contains "
2276 + "the documents to be evaluated");
2277 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2278 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
2279 fileChooser.setResource(CorpusBenchmarkTool.class.getName());
2280 int state = fileChooser.showOpenDialog(MainFrame.this);
2281 File startDir = fileChooser.getSelectedFile();
2282 if(state == JFileChooser.CANCEL_OPTION || startDir == null) return;
2283
2284 fileChooser.setDialogTitle(
2285 "Please select the application that you want to run");
2286 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
2287 fileChooser.setResource(
2288 CorpusBenchmarkTool.class.getName() + ".application");
2289 state = fileChooser.showOpenDialog(MainFrame.this);
2290 File testApp = fileChooser.getSelectedFile();
2291 if(state == JFileChooser.CANCEL_OPTION || testApp == null) return;
2292
2293 // first create the tool and set its parameters
2294 CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
2295 theTool.setStartDirectory(startDir);
2296 theTool.setApplicationFile(testApp);
2297 theTool.setVerboseMode(verboseModeItem.isSelected());
2298
2299 Out.prln("Please wait while GATE tools are initialised.");
2300 // initialise the tool
2301 theTool.init();
2302 // and execute it
2303 theTool.execute();
2304 theTool.printStatistics();
2305
2306 Out.prln("<BR>Overall average precision: "
2307 + theTool.getPrecisionAverage());
2308 Out.prln("<BR>Overall average recall: " + theTool.getRecallAverage());
2309 Out.prln("<BR>Overall average fMeasure : "
2310 + theTool.getFMeasureAverage());
2311 Out.prln("<BR>Finished!");
2312 theTool.unloadPRs();
2313 }
2314 };
2315 Thread thread =
2316 new Thread(Thread.currentThread().getThreadGroup(), runnable,
2317 "NewCorpusEvalAction");
2318 thread.setPriority(Thread.MIN_PRIORITY);
2319 thread.start();
2320 }// actionPerformed();
2321 }// class NewCorpusEvalAction
2322
2323 /**
2324 * This class represent an action which brings up the corpus
2325 * evaluation tool
2326 */
2327 class StoredMarkedCorpusEvalAction extends AbstractAction {
2328 private static final long serialVersionUID = 1L;
2329 public StoredMarkedCorpusEvalAction() {
2330 super("Human Marked Against Stored Processing Results");
2331 putValue(SHORT_DESCRIPTION,
2332 "Compares stored processed set with human-annotated set");
2333 putValue(SMALL_ICON, getIcon("corpus-benchmark"));
2334 }// newCorpusEvalAction
2335
2336 public void actionPerformed(ActionEvent e) {
2337 Runnable runnable = new Runnable() {
2338 public void run() {
2339 fileChooser.setDialogTitle("Please select a directory which contains "
2340 + "the documents to be evaluated");
2341 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2342 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
2343 fileChooser.setResource(CorpusBenchmarkTool.class.getName());
2344 int state = fileChooser.showOpenDialog(MainFrame.this);
2345 File startDir = fileChooser.getSelectedFile();
2346 if(state == JFileChooser.CANCEL_OPTION || startDir == null) return;
2347
2348 // first create the tool and set its parameters
2349 CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
2350 theTool.setStartDirectory(startDir);
2351 theTool.setMarkedStored(true);
2352 theTool.setVerboseMode(verboseModeItem.isSelected());
2353 // theTool.setMarkedDS(
2354 // MainFrame.this.datastoreModeCorpusEvalToolAction.isDatastoreMode());
2355
2356 Out
2357 .prln("Evaluating human-marked documents against pre-stored results.");
2358 // initialise the tool
2359 theTool.init();
2360 // and execute it
2361 theTool.execute();
2362 theTool.printStatistics();
2363
2364 Out.prln("<BR>Overall average precision: "
2365 + theTool.getPrecisionAverage());
2366 Out.prln("<BR>Overall average recall: " + theTool.getRecallAverage());
2367 Out.prln("<BR>Overall average fMeasure : "
2368 + theTool.getFMeasureAverage());
2369 Out.prln("<BR>Finished!");
2370 theTool.unloadPRs();
2371 }
2372 };
2373 Thread thread =
2374 new Thread(Thread.currentThread().getThreadGroup(), runnable,
2375 "StoredMarkedCorpusEvalAction");
2376 thread.setPriority(Thread.MIN_PRIORITY);
2377 thread.start();
2378 }// actionPerformed();
2379 }// class StoredMarkedCorpusEvalActionpusEvalAction
2380
2381 /**
2382 * This class represent an action which brings up the corpus
2383 * evaluation tool
2384 */
2385 class CleanMarkedCorpusEvalAction extends AbstractAction {
2386 private static final long serialVersionUID = 1L;
2387 public CleanMarkedCorpusEvalAction() {
2388 super("Human Marked Against Current Processing Results");
2389 putValue(SHORT_DESCRIPTION,
2390 "Compares current processed set with human-annotated set");
2391 putValue(SMALL_ICON, getIcon("corpus-benchmark"));
2392 }// newCorpusEvalAction
2393
2394 public void actionPerformed(ActionEvent e) {
2395 Runnable runnable = new Runnable() {
2396 public void run() {
2397 fileChooser.setDialogTitle("Please select a directory which contains "
2398 + "the documents to be evaluated");
2399 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2400 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
2401 fileChooser.setResource(CorpusBenchmarkTool.class.getName());
2402 int state = fileChooser.showOpenDialog(MainFrame.this);
2403 File startDir = fileChooser.getSelectedFile();
2404 if(state == JFileChooser.CANCEL_OPTION || startDir == null) return;
2405
2406 fileChooser.setDialogTitle(
2407 "Please select the application that you want to run");
2408 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
2409 fileChooser.setResource(
2410 CorpusBenchmarkTool.class.getName() + ".application");
2411 state = fileChooser.showOpenDialog(MainFrame.this);
2412 File testApp = fileChooser.getSelectedFile();
2413 if(state == JFileChooser.CANCEL_OPTION || testApp == null) return;
2414
2415 // first create the tool and set its parameters
2416 CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
2417 theTool.setStartDirectory(startDir);
2418 theTool.setApplicationFile(testApp);
2419 theTool.setMarkedClean(true);
2420 theTool.setVerboseMode(verboseModeItem.isSelected());
2421
2422 Out.prln("Evaluating human-marked documents against current processing results.");
2423 // initialise the tool
2424 theTool.init();
2425 // and execute it
2426 theTool.execute();
2427 theTool.printStatistics();
2428
2429 Out.prln("Overall average precision: "
2430 + theTool.getPrecisionAverage());
2431 Out.prln("Overall average recall: " + theTool.getRecallAverage());
2432 Out
2433 .prln("Overall average fMeasure : " + theTool.getFMeasureAverage());
2434 Out.prln("Finished!");
2435 theTool.unloadPRs();
2436 }
2437 };
2438 Thread thread =
2439 new Thread(Thread.currentThread().getThreadGroup(), runnable,
2440 "CleanMarkedCorpusEvalAction");
2441 thread.setPriority(Thread.MIN_PRIORITY);
2442 thread.start();
2443 }// actionPerformed();
2444 }// class CleanMarkedCorpusEvalActionpusEvalAction
2445
2446 /**
2447 * This class represent an action which brings up the corpus
2448 * evaluation tool
2449 */
2450 class GenerateStoredCorpusEvalAction extends AbstractAction {
2451 private static final long serialVersionUID = 1L;
2452 public GenerateStoredCorpusEvalAction() {
2453 super("Store Corpus for Future Evaluation");
2454 putValue(SHORT_DESCRIPTION, "Store corpus for future evaluation");
2455 putValue(SMALL_ICON, getIcon("corpus-benchmark"));
2456 }// newCorpusEvalAction
2457
2458 public void actionPerformed(ActionEvent e) {
2459 Runnable runnable = new Runnable() {
2460 public void run() {
2461 fileChooser.setDialogTitle("Please select a directory which contains "
2462 + "the documents to be evaluated");
2463 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2464 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
2465 fileChooser.setResource(CorpusBenchmarkTool.class.getName());
2466 int state = fileChooser.showOpenDialog(MainFrame.this);
2467 File startDir = fileChooser.getSelectedFile();
2468 if(state == JFileChooser.CANCEL_OPTION || startDir == null) return;
2469
2470 fileChooser.setDialogTitle(
2471 "Please select the application that you want to run");
2472 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
2473 fileChooser.setResource(
2474 CorpusBenchmarkTool.class.getName() + ".application");
2475 state = fileChooser.showOpenDialog(MainFrame.this);
2476 File testApp = fileChooser.getSelectedFile();
2477 if(state == JFileChooser.CANCEL_OPTION || testApp == null) return;
2478
2479 // first create the tool and set its parameters
2480 CorpusBenchmarkTool theTool = new CorpusBenchmarkTool();
2481 theTool.setStartDirectory(startDir);
2482 theTool.setApplicationFile(testApp);
2483 theTool.setGenerateMode(true);
2484
2485 Out.prln("Processing and storing documents for future evaluation.");
2486 // initialise the tool
2487 theTool.init();
2488 // and execute it
2489 theTool.execute();
2490 theTool.unloadPRs();
2491 Out.prln("Finished!");
2492 }
2493 };
2494 Thread thread =
2495 new Thread(Thread.currentThread().getThreadGroup(), runnable,
2496 "GenerateStoredCorpusEvalAction");
2497 thread.setPriority(Thread.MIN_PRIORITY);
2498 thread.start();
2499 }// actionPerformed();
2500 }// class GenerateStoredCorpusEvalAction
2501
2502 /**
2503 * This class represent an action which brings up the corpus
2504 * evaluation tool
2505 */
2506 class VerboseModeCorpusEvalToolAction extends AbstractAction {
2507 private static final long serialVersionUID = 1L;
2508 public VerboseModeCorpusEvalToolAction() {
2509 super("Verbose Mode");
2510 }// VerboseModeCorpusEvalToolAction
2511
2512 public boolean isVerboseMode() {
2513 return verboseMode;
2514 }
2515
2516 public void actionPerformed(ActionEvent e) {
2517 if(!(e.getSource() instanceof JCheckBoxMenuItem)) return;
2518 verboseMode = ((JCheckBoxMenuItem)e.getSource()).getState();
2519 }// actionPerformed();
2520
2521 protected boolean verboseMode = false;
2522 }// class f
2523
2524 /**
2525 * This class represent an action which brings up the corpus
2526 * evaluation tool
2527 */
2528 /*
2529 * class DatastoreModeCorpusEvalToolAction extends AbstractAction {
2530 * public DatastoreModeCorpusEvalToolAction() { super("Use a datastore
2531 * for human annotated texts"); putValue(SHORT_DESCRIPTION,"Use a
2532 * datastore for the human annotated texts"); }//
2533 * DatastoreModeCorpusEvalToolAction
2534 *
2535 * public boolean isDatastoreMode() {return datastoreMode;}
2536 *
2537 * public void actionPerformed(ActionEvent e) { if (! (e.getSource()
2538 * instanceof JCheckBoxMenuItem)) return; datastoreMode =
2539 * ((JCheckBoxMenuItem)e.getSource()).getState(); }//
2540 * actionPerformed(); protected boolean datastoreMode = false;
2541 * }//class DatastoreModeCorpusEvalToolListener
2542 */
2543
2544 /**
2545 * Loads ANNIE with default parameters.
2546 */
2547 class LoadANNIEWithDefaultsAction extends AbstractAction implements
2548 ANNIEConstants {
2549 private static final long serialVersionUID = 1L;
2550
2551 public LoadANNIEWithDefaultsAction() {
2552 super("with Defaults");
2553 putValue(SHORT_DESCRIPTION, "Load ANNIE with default parameters");
2554 putValue(SMALL_ICON, getIcon("annie-application"));
2555 }
2556
2557 public void actionPerformed(ActionEvent e) {
2558 Runnable runnable = new Runnable() {
2559 public void run() {
2560 lockGUI("ANNIE is being loaded...");
2561 try {
2562 long startTime = System.currentTimeMillis();
2563
2564 // load ANNIE as an application from a gapp file
2565 PersistenceManager.loadObjectFromFile(new File(new File(
2566 Gate.getPluginsHome(), ANNIEConstants.PLUGIN_DIR),
2567 ANNIEConstants.DEFAULT_FILE));
2568
2569 long endTime = System.currentTimeMillis();
2570 statusChanged("ANNIE loaded in "
2571 + NumberFormat.getInstance().format(
2572 (double)(endTime - startTime) / 1000) + " seconds");
2573 }
2574 catch(Exception error) {
2575 String message =
2576 "There was an error when loading the ANNIE application.";
2577 alertButton.setAction(new AlertAction(error, message, null));
2578 }
2579 finally {
2580 unlockGUI();
2581 }
2582 }
2583 };
2584 Thread thread = new Thread(runnable, "LoadANNIEWithDefaultsAction");
2585 thread.setPriority(Thread.MIN_PRIORITY);
2586 thread.start();
2587 }
2588 }// class LoadANNIEWithDefaultsAction
2589
2590 /**
2591 * Loads ANNIE without default parameters.
2592 */
2593 class LoadANNIEWithoutDefaultsAction extends AbstractAction implements
2594 ANNIEConstants {
2595 private static final long serialVersionUID = 1L;
2596
2597 public LoadANNIEWithoutDefaultsAction() {
2598 super("without Defaults");
2599 putValue(SHORT_DESCRIPTION, "Load ANNIE without default parameters");
2600 putValue(SMALL_ICON, getIcon("annie-application"));
2601 }
2602
2603 public void actionPerformed(ActionEvent e) {
2604 Runnable runnable = new Runnable() {
2605 public void run() {
2606 lockGUI("ANNIE is being loaded...");
2607 final SerialAnalyserController controller;
2608 try {
2609 // load ANNIE as an application from a gapp file
2610 controller = (SerialAnalyserController)
2611 PersistenceManager.loadObjectFromFile(new File(new File(
2612 Gate.getPluginsHome(), ANNIEConstants.PLUGIN_DIR),
2613 ANNIEConstants.DEFAULT_FILE));
2614
2615 statusChanged("ANNIE loaded!");
2616 unlockGUI();
2617 }
2618 catch(Exception error) {
2619 unlockGUI();
2620 String message =
2621 "There was an error when loading the ANNIE application.";
2622 alertButton.setAction(new AlertAction(error, message, null));
2623 return;
2624 }
2625
2626 SwingUtilities.invokeLater(new Runnable() {
2627 public void run() {
2628 List<ProcessingResource> prs =
2629 new ArrayList<ProcessingResource>(controller.getPRs());
2630 for(ProcessingResource pr : prs) {
2631 try {
2632 SwingUtilities.invokeLater(new Runnable() {
2633 public void run() {
2634 // select last processing resource in resources tree
2635 int selectedRow = resourcesTree.getRowForPath(
2636 new TreePath(processingResourcesRoot.getPath()));
2637 selectedRow += processingResourcesRoot.getChildCount();
2638 resourcesTree.setSelectionRow(selectedRow);
2639 resourcesTree.scrollRowToVisible(selectedRow);
2640 }
2641 });
2642 // get the parameters for each ANNIE PR
2643 ResourceData resData = Gate.getCreoleRegister()
2644 .get(pr.getClass().getName());
2645 if (resData == null) {
2646 throw new ResourceInstantiationException(
2647 pr.getName() + " was not possible to load.");
2648 }
2649 fileChooser.setResource(resData.getClassName());
2650 if(newResourceDialog.show(resData, "Parameters for the new "
2651 + resData.getName())) {
2652 // add the PR with user parameters
2653 controller.add((ProcessingResource)
2654 Factory.createResource(pr.getClass().getName(),
2655 newResourceDialog.getSelectedParameters()));
2656 }
2657 // remove the PR with default parameters
2658 Factory.deleteResource(pr);
2659 }
2660 catch(ResourceInstantiationException error) {
2661 String message = "There was an error when creating"
2662 + " the resource: " + pr.getName() + ".";
2663 alertButton.setAction(new AlertAction(error, message, null));
2664 }
2665 } // for(Object loadedPR : loadedPRs)
2666 }
2667 });
2668 }
2669 };
2670 Thread thread = new Thread(runnable, "LoadANNIEWithoutDefaultsAction");
2671 thread.setPriority(Thread.MIN_PRIORITY);
2672 thread.start();
2673 }
2674 }// class LoadANNIEWithoutDefaultsAction
2675
2676 /**
2677 * Loads the application.
2678 */
2679 class LoadApplicationAction extends AbstractAction {
2680 private static final long serialVersionUID = 1L;
2681
2682 private String pluginDir = null;
2683
2684 private String applicationFile = null;
2685
2686 public LoadApplicationAction(String caption, String pluginDir,
2687 String applicationFile) {
2688 super("Load " + pluginDir + " System");
2689 this.pluginDir = pluginDir;
2690 this.applicationFile = applicationFile;
2691 putValue(SHORT_DESCRIPTION, "Load " + pluginDir
2692 + " with default parameters");
2693 putValue(SMALL_ICON, getIcon("open-application"));
2694 }
2695
2696 public void actionPerformed(ActionEvent e) {
2697 Runnable runnable = new Runnable() {
2698 public void run() {
2699 lockGUI(pluginDir + " is being loaded...");
2700 try {
2701 long startTime = System.currentTimeMillis();
2702
2703 // load LingPipe as an application from a gapp file
2704 PersistenceManager.loadObjectFromFile(new File(new File(Gate
2705 .getPluginsHome(), pluginDir), applicationFile));
2706
2707 long endTime = System.currentTimeMillis();
2708 statusChanged(pluginDir
2709 + " loaded in "
2710 + NumberFormat.getInstance().format(
2711 (double)(endTime - startTime) / 1000) + " seconds");
2712 } catch(Exception error) {
2713 String message =
2714 "There was an error when loading the " + pluginDir
2715 + " application.";
2716 alertButton.setAction(new AlertAction(error, message, null));
2717 } finally {
2718 unlockGUI();
2719 }
2720 }
2721 };
2722 Thread thread = new Thread(runnable, "LoadApplicationAction");
2723 thread.setPriority(Thread.MIN_PRIORITY);
2724 thread.start();
2725 }
2726 }// class LoadApplicationAction
2727
2728 class NewBootStrapAction extends AbstractAction {
2729 private static final long serialVersionUID = 1L;
2730 public NewBootStrapAction() {
2731 super("BootStrap Wizard", getIcon("application"));
2732 putValue(SHORT_DESCRIPTION, "Create a generic resource to be completed");
2733 }// NewBootStrapAction
2734
2735 public void actionPerformed(ActionEvent e) {
2736 BootStrapDialog bootStrapDialog = new BootStrapDialog(MainFrame.this);
2737 bootStrapDialog.setVisible(true);
2738 }// actionPerformed();
2739 }// class NewBootStrapAction
2740
2741 class ManagePluginsAction extends AbstractAction {
2742 private static final long serialVersionUID = 1L;
2743 public ManagePluginsAction() {
2744 super("Manage CREOLE Plugins");
2745 putValue(SHORT_DESCRIPTION,
2746 "Load, unload, add and remove CREOLE plugins");
2747 putValue(SMALL_ICON, getIcon("creole-plugins"));
2748 }
2749
2750 public void actionPerformed(ActionEvent e) {
2751 if(pluginManager == null) {
2752 pluginManager = new PluginManagerUI(MainFrame.this);
2753 // pluginManager.setLocationRelativeTo(MainFrame.this);
2754 pluginManager.setModal(true);
2755 getGuiRoots().add(pluginManager);
2756 pluginManager.pack();
2757 // size the window so that it doesn't go off-screen
2758 Dimension screenSize = /* Toolkit.getDefaultToolkit().getScreenSize(); */
2759 getGraphicsConfiguration().getBounds().getSize();
2760 Dimension dialogSize = pluginManager.getPreferredSize();
2761 int width =
2762 dialogSize.width > screenSize.width
2763 ? screenSize.width * 3 / 4
2764 : dialogSize.width;
2765 int height =
2766 dialogSize.height > screenSize.height
2767 ? screenSize.height * 3 / 4
2768 : dialogSize.height;
2769 pluginManager.setSize(width, height);
2770 pluginManager.validate();
2771 // center the window on screen
2772 int x = (screenSize.width - width) / 2;
2773 int y = (screenSize.height - height) / 2;
2774 pluginManager.setLocation(x, y);
2775 }
2776 fileChooser.setResource(PluginManagerUI.class.getName());
2777 pluginManager.setVisible(true);
2778 // free resources after the dialog is hidden
2779 pluginManager.dispose();
2780 }
2781 }
2782
2783 /**
2784 * TODO: delete this method as it has moved to {@link PluginManagerUI}
2785 * @deprecated
2786 */
2787 class LoadCreoleRepositoryAction extends AbstractAction {
2788 private static final long serialVersionUID = 1L;
2789 public LoadCreoleRepositoryAction() {
2790 super("Load a CREOLE Repository");
2791 }
2792
2793 public void actionPerformed(ActionEvent e) {
2794 Box messageBox = Box.createHorizontalBox();
2795 Box leftBox = Box.createVerticalBox();
2796 JTextField urlTextField = new JTextField(20);
2797 leftBox.add(new JLabel("Type an URL"));
2798 leftBox.add(urlTextField);
2799 messageBox.add(leftBox);
2800
2801 messageBox.add(Box.createHorizontalStrut(10));
2802 messageBox.add(new JLabel("or"));
2803 messageBox.add(Box.createHorizontalStrut(10));
2804
2805 class URLfromFileAction extends AbstractAction {
2806 private static final long serialVersionUID = 1L;
2807 URLfromFileAction(JTextField textField) {
2808 super(null, getIcon("open-file"));
2809 putValue(SHORT_DESCRIPTION, "Click to select a directory");
2810 this.textField = textField;
2811 }
2812
2813 public void actionPerformed(ActionEvent e) {
2814 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
2815 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
2816 fileChooser.setResource("gate.CreoleRegister");
2817 int result = fileChooser.showOpenDialog(MainFrame.this);
2818 if(result == JFileChooser.APPROVE_OPTION) {
2819 try {
2820 textField.setText(fileChooser.getSelectedFile().toURI().toURL()
2821 .toExternalForm());
2822 }
2823 catch(MalformedURLException mue) {
2824 throw new GateRuntimeException(mue.toString());
2825 }
2826 }
2827 }
2828
2829 JTextField textField;
2830 } // class URLfromFileAction extends AbstractAction
2831
2832 Box rightBox = Box.createVerticalBox();
2833 rightBox.add(new JLabel("Select a directory"));
2834 JButton fileBtn = new JButton(new URLfromFileAction(urlTextField));
2835 rightBox.add(fileBtn);
2836 messageBox.add(rightBox);
2837
2838 // JOptionPane.showInputDialog(
2839 // MainFrame.this,
2840 // "Select type of Datastore",
2841 // "Gate", JOptionPane.QUESTION_MESSAGE,
2842 // null, names,
2843 // names[0]);
2844
2845 int res =
2846 JOptionPane.showConfirmDialog(MainFrame.this, messageBox,
2847 "Enter an URL to the directory containig the "
2848 + "\"creole.xml\" file", JOptionPane.OK_CANCEL_OPTION,
2849 JOptionPane.QUESTION_MESSAGE, null);
2850 if(res == JOptionPane.OK_OPTION) {
2851 try {
2852 URL creoleURL = new URL(urlTextField.getText());
2853 Gate.getCreoleRegister().registerDirectories(creoleURL);
2854 }
2855 catch(Exception error) {
2856 String message =
2857 "There was a problem when registering your CREOLE directory.";
2858 alertButton.setAction(new AlertAction(error, message, null));
2859 }
2860 }
2861 }
2862 }// class LoadCreoleRepositoryAction extends AbstractAction
2863
2864 class NewResourceAction extends AbstractAction {
2865 private static final long serialVersionUID = 1L;
2866 /** Used for creation of resource menu item and creation dialog */
2867 ResourceData rData;
2868
2869 public NewResourceAction(ResourceData rData) {
2870 super(rData.getName());
2871 putValue(SHORT_DESCRIPTION, rData.getComment());
2872 this.rData = rData;
2873 putValue(SMALL_ICON, getIcon(rData.getIcon()));
2874 } // NewResourceAction(ResourceData rData)
2875
2876 public void actionPerformed(ActionEvent evt) {
2877 Runnable runnable = new Runnable() {
2878 public void run() {
2879 newResourceDialog.setTitle("Parameters for the new "
2880 + rData.getName());
2881 fileChooser.setResource(rData.getClassName());
2882 newResourceDialog.show(rData);
2883 }
2884 };
2885 SwingUtilities.invokeLater(runnable);
2886 } // actionPerformed
2887 } // class NewResourceAction extends AbstractAction
2888
2889 static class StopAction extends AbstractAction {
2890 private static final long serialVersionUID = 1L;
2891 public StopAction() {
2892 super(" Stop! ");
2893 putValue(SHORT_DESCRIPTION, "Stops the current action");
2894 }
2895
2896 public boolean isEnabled() {
2897 return Gate.getExecutable() != null;
2898 }
2899
2900 public void actionPerformed(ActionEvent e) {
2901 Executable ex = Gate.getExecutable();
2902 if(ex != null) ex.interrupt();
2903 }
2904 }
2905
2906 /**
2907 * Method is used in NewDSAction
2908 * @return the new datastore or null if an error occurs
2909 */
2910 protected DataStore createSearchableDataStore() {
2911 try {
2912
2913 JPanel mainPanel = new JPanel(new GridBagLayout());
2914
2915 final JTextField dsLocation = new JTextField("", 20);
2916 dsLocation.setEditable(false);
2917
2918 final JTextField indexLocation = new JTextField("", 20);
2919 indexLocation.setToolTipText("directory to store the the lucene index");
2920
2921 JTextField btat = new JTextField("Token", 20);
2922 btat.setToolTipText("Examples: Token, AnnotationSetName.Token, "
2923 + Constants.DEFAULT_ANNOTATION_SET_NAME + ".Token");
2924 JCheckBox createTokensAutomatically =
2925 new JCheckBox("Create Tokens Automatically");
2926 createTokensAutomatically.setSelected(true);
2927 JTextField iuat = new JTextField("", 20);
2928 iuat.setToolTipText("Examples: Sentence, AnnotationSetName.Sentence, "
2929 + Constants.DEFAULT_ANNOTATION_SET_NAME + ".Sentence");
2930
2931 final List<String> inputASList = new ArrayList<String>();
2932 inputASList.add("Key");
2933 inputASList.add(Constants.DEFAULT_ANNOTATION_SET_NAME);
2934
2935 final JTextField inputAS = new JTextField("", 20);
2936 inputAS.setText("Key;"+Constants.DEFAULT_ANNOTATION_SET_NAME);
2937 inputAS.setEditable(false);
2938
2939 JButton editInputAS = new JButton(getIcon("edit-list"));
2940 editInputAS.addActionListener(new ActionListener() {
2941 public void actionPerformed(ActionEvent ae) {
2942 ListEditorDialog listEditor =
2943 new ListEditorDialog(instance, inputASList, "java.lang.String");
2944 List result = listEditor.showDialog();
2945 if(result != null) {
2946 inputASList.clear();
2947 inputASList.addAll(result);
2948 if(inputASList.size() > 0) {
2949 String text =
2950 inputASList.get(0) == null
2951 ? Constants.DEFAULT_ANNOTATION_SET_NAME
2952 : inputASList.get(0);
2953 for(int j = 1; j < inputASList.size(); j++) {
2954 text +=
2955 ";"
2956 + (inputASList.get(j) == null
2957 ? Constants.DEFAULT_ANNOTATION_SET_NAME
2958 : inputASList.get(j));
2959 }
2960 inputAS.setText(text);
2961 }
2962 else {
2963 inputAS.setText("");
2964 }
2965 }
2966 }
2967 });
2968
2969 JComboBox asie = new JComboBox(new String[]{"include", "exclude"});
2970 inputAS.setToolTipText("Leave blank for indexing all annotation sets. \""
2971 + Constants.DEFAULT_ANNOTATION_SET_NAME +
2972 "\" indicates the default annotation set");
2973
2974 final List<String> fteList = new ArrayList<String>();
2975 fteList.add("SpaceToken");
2976 fteList.add("Split");
2977 final JTextField fte = new JTextField("", 20);
2978 fte.setText("SpaceToken;Split");
2979 fte.setEditable(false);
2980 JButton editFTE = new JButton(getIcon("edit-list"));
2981 editFTE.addActionListener(new ActionListener() {
2982 public void actionPerformed(ActionEvent ae) {
2983 ListEditorDialog listEditor =
2984 new ListEditorDialog(instance, fteList, "java.lang.String");
2985 List result = listEditor.showDialog();
2986 if(result != null) {
2987 fteList.clear();
2988 fteList.addAll(result);
2989 if(fteList.size() > 0) {
2990 String text =
2991 fteList.get(0) == null
2992 ? Constants.DEFAULT_ANNOTATION_SET_NAME
2993 : fteList.get(0);
2994 for(int j = 1; j < fteList.size(); j++) {
2995 text +=
2996 ";"
2997 + (fteList.get(j) == null
2998 ? Constants.DEFAULT_ANNOTATION_SET_NAME
2999 : fteList.get(j));
3000 }
3001 fte.setText(text);
3002 }
3003 else {
3004 fte.setText("");
3005 }
3006 }
3007 }
3008 });
3009
3010 JComboBox ftie = new JComboBox(new String[]{"include", "exclude"});
3011 ftie.setSelectedIndex(1);
3012 fte.setToolTipText("Leave blank for inclusion of all features");
3013
3014 JButton indexBrowse = new JButton(getIcon("open-file"));
3015 indexBrowse.addActionListener(new ActionListener() {
3016 public void actionPerformed(ActionEvent ae) {
3017 // first we need to ask for a new empty directory
3018 fileChooser.setDialogTitle(
3019 "Please create a new empty directory for datastore");
3020 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
3021 fileChooser.setResource("gate.DataStore.index");
3022 if(fileChooser.showOpenDialog(MainFrame.this)
3023 == JFileChooser.APPROVE_OPTION) {
3024 try {
3025 indexLocation.setText(fileChooser.getSelectedFile().toURI()
3026 .toURL().toExternalForm());
3027 }
3028 catch(Exception e) {
3029 indexLocation.setText("");
3030 }
3031 }
3032 }
3033 });
3034
3035 GridBagConstraints constraints = new GridBagConstraints();
3036 constraints.gridx = GridBagConstraints.RELATIVE;
3037 constraints.gridy = 0;
3038 constraints.gridwidth = 3;
3039 constraints.anchor = GridBagConstraints.WEST;
3040 constraints.fill = GridBagConstraints.NONE;
3041 constraints.insets = new Insets(0, 0, 0, 5);
3042 mainPanel.add(new JLabel("Datastore URL:"), constraints);
3043
3044 constraints = new GridBagConstraints();
3045 constraints.gridx = GridBagConstraints.RELATIVE;
3046 constraints.gridy = 0;
3047 constraints.gridwidth = 6;
3048 constraints.fill = GridBagConstraints.HORIZONTAL;
3049 constraints.insets = new Insets(0, 0, 0, 10);
3050 mainPanel.add(dsLocation, constraints);
3051
3052 // second row
3053 constraints = new GridBagConstraints();
3054 constraints.gridx = GridBagConstraints.RELATIVE;
3055 constraints.gridy = 1;
3056 constraints.gridwidth = 3;
3057 constraints.anchor = GridBagConstraints.WEST;
3058 constraints.fill = GridBagConstraints.NONE;
3059 constraints.insets = new Insets(0, 0, 0, 5);
3060 mainPanel.add(new JLabel("Index Location:"), constraints);
3061
3062 constraints = new GridBagConstraints();
3063 constraints.gridx = GridBagConstraints.RELATIVE;
3064 constraints.gridy = 1;
3065 constraints.gridwidth = 5;
3066 constraints.fill = GridBagConstraints.HORIZONTAL;
3067 constraints.insets = new Insets(0, 0, 0, 10);
3068 mainPanel.add(indexLocation, constraints);
3069
3070 constraints = new GridBagConstraints();
3071 constraints.gridx = GridBagConstraints.RELATIVE;
3072 constraints.gridy = 1;
3073 constraints.gridwidth = 1;
3074 constraints.anchor = GridBagConstraints.NORTHWEST;
3075 mainPanel.add(indexBrowse, constraints);
3076 indexBrowse.setBorderPainted(false);
3077 indexBrowse.setContentAreaFilled(false);
3078
3079 // third row row
3080 constraints = new GridBagConstraints();
3081 constraints.gridx = GridBagConstraints.RELATIVE;
3082 constraints.gridy = 2;
3083 constraints.gridwidth = 2;
3084 constraints.anchor = GridBagConstraints.WEST;
3085 constraints.fill = GridBagConstraints.NONE;
3086 constraints.insets = new Insets(0, 0, 0, 5);
3087 mainPanel.add(new JLabel("Annotation Sets:"), constraints);
3088
3089 constraints = new GridBagConstraints();
3090 constraints.gridx = GridBagConstraints.RELATIVE;
3091 constraints.gridy = 2;
3092 constraints.gridwidth = 1;
3093 constraints.fill = GridBagConstraints.HORIZONTAL;
3094 constraints.insets = new Insets(0, 0, 0, 10);
3095 mainPanel.add(asie, constraints);
3096
3097 constraints = new GridBagConstraints();
3098 constraints.gridx = GridBagConstraints.RELATIVE;
3099 constraints.gridy = 2;
3100 constraints.gridwidth = 5;
3101 constraints.fill = GridBagConstraints.HORIZONTAL;
3102 constraints.insets = new Insets(0, 0, 0, 10);
3103 mainPanel.add(inputAS, constraints);
3104
3105 constraints = new GridBagConstraints();
3106 constraints.gridx = GridBagConstraints.RELATIVE;
3107 constraints.gridy = 2;
3108 constraints.gridwidth = 1;
3109 constraints.anchor = GridBagConstraints.NORTHWEST;
3110 mainPanel.add(editInputAS, constraints);
3111 editInputAS.setBorderPainted(false);
3112 editInputAS.setContentAreaFilled(false);
3113
3114 // fourth row row
3115 constraints = new GridBagConstraints();
3116 constraints.gridx = GridBagConstraints.RELATIVE;
3117 constraints.gridy = 3;
3118 constraints.gridwidth = 3;
3119 constraints.anchor = GridBagConstraints.WEST;
3120 constraints.fill = GridBagConstraints.NONE;
3121 constraints.insets = new Insets(0, 0, 0, 5);
3122 mainPanel.add(new JLabel("Base Token Type:"), constraints);
3123
3124 constraints = new GridBagConstraints();
3125 constraints.gridx = GridBagConstraints.RELATIVE;
3126 constraints.gridy = 3;
3127 constraints.gridwidth = 5;
3128 constraints.anchor = GridBagConstraints.NORTHWEST;
3129 mainPanel.add(btat, constraints);
3130
3131 // fifth row
3132 constraints = new GridBagConstraints();
3133 constraints.gridx = 4;
3134 constraints.gridy = 4;
3135 constraints.gridwidth = 5;
3136 constraints.anchor = GridBagConstraints.WEST;
3137 constraints.fill = GridBagConstraints.NONE;
3138 constraints.insets = new Insets(0, 0, 0, 5);
3139 mainPanel.add(createTokensAutomatically, constraints);
3140
3141 // sixth row
3142 constraints = new GridBagConstraints();
3143 constraints.gridx = GridBagConstraints.RELATIVE;
3144 constraints.gridy = 5;
3145 constraints.gridwidth = 3;
3146 constraints.anchor = GridBagConstraints.WEST;
3147 constraints.fill = GridBagConstraints.NONE;
3148 constraints.insets = new Insets(0, 0, 0, 5);
3149 mainPanel.add(new JLabel("Index Unit Type:"), constraints);
3150
3151 constraints = new GridBagConstraints();
3152 constraints.gridx = GridBagConstraints.RELATIVE;
3153 constraints.gridy = 5;
3154 constraints.gridwidth = 5;
3155 constraints.anchor = GridBagConstraints.NORTHWEST;
3156 mainPanel.add(iuat, constraints);
3157
3158 // seventh row
3159 constraints = new GridBagConstraints();
3160 constraints.gridx = GridBagConstraints.RELATIVE;
3161 constraints.gridy = 6;
3162 constraints.gridwidth = 2;
3163 constraints.anchor = GridBagConstraints.WEST;
3164 constraints.fill = GridBagConstraints.NONE;
3165 constraints.insets = new Insets(0, 0, 0, 5);
3166 mainPanel.add(new JLabel("Features:"), constraints);
3167
3168 constraints = new GridBagConstraints();
3169 constraints.gridx = GridBagConstraints.RELATIVE;
3170 constraints.gridy = 6;
3171 constraints.gridwidth = 1;
3172 constraints.fill = GridBagConstraints.HORIZONTAL;
3173 constraints.insets = new Insets(0, 0, 0, 10);
3174 mainPanel.add(ftie, constraints);
3175
3176 constraints = new GridBagConstraints();
3177 constraints.gridx = GridBagConstraints.RELATIVE;
3178 constraints.gridy = 6;
3179 constraints.gridwidth = 5;
3180 constraints.fill = GridBagConstraints.HORIZONTAL;
3181 constraints.insets = new Insets(0, 0, 0, 10);
3182 mainPanel.add(fte, constraints);
3183
3184 constraints = new GridBagConstraints();
3185 constraints.gridx = GridBagConstraints.RELATIVE;
3186 constraints.gridy = 6;
3187 constraints.gridwidth = 1;
3188 constraints.anchor = GridBagConstraints.NORTHWEST;
3189 mainPanel.add(editFTE, constraints);
3190 editFTE.setBorderPainted(false);
3191 editFTE.setContentAreaFilled(false);
3192
3193 // get the URL (a folder in this case)
3194 fileChooser.setDialogTitle("Please create a new empty directory");
3195 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
3196 fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
3197 fileChooser.setResource("gate.persist.LuceneDataStoreImpl");
3198 int response = fileChooser.showOpenDialog(MainFrame.this);
3199 if(response == JFileChooser.APPROVE_OPTION) {
3200 try {
3201 File dsFolder = fileChooser.getSelectedFile();
3202 dsLocation.setText(dsFolder.toURI().toURL().toExternalForm());
3203 File indexFolder =
3204 new File(dsFolder.getParentFile(), dsFolder.getName()+"-index");
3205 indexLocation.setText(indexFolder.toURI().toURL().toExternalForm());
3206 }
3207 catch(MalformedURLException mue) {
3208 JOptionPane.showMessageDialog(MainFrame.this,
3209 "Invalid location\n " + mue.toString(), "GATE",
3210 JOptionPane.ERROR_MESSAGE);
3211 }
3212 } else {
3213 return null;
3214 }
3215
3216
3217 boolean validEntry = false;
3218 while(!validEntry) {
3219 int returnValue =
3220 JOptionPane.showOptionDialog(MainFrame.this, mainPanel,
3221 "SearchableDataStore", JOptionPane.PLAIN_MESSAGE,
3222 JOptionPane.OK_CANCEL_OPTION, getIcon("empty"),
3223 new String[]{"OK", "Cancel"}, "OK");
3224
3225 if(returnValue == JOptionPane.OK_OPTION) {
3226
3227 // sanity check parameters
3228
3229 if(dsLocation.getText().equals(indexLocation.getText())) {
3230 JOptionPane.showMessageDialog(MainFrame.this,
3231 "Datastore and index cannot be stored in the same directory",
3232 "Error", JOptionPane.ERROR_MESSAGE);
3233 }
3234 else {
3235 // check if index folder can be created
3236 try {
3237 File indexDir =
3238 new File(new URL(indexLocation.getText()).getFile());
3239 if(indexDir.exists() && indexDir.isFile()) {
3240 JOptionPane.showMessageDialog(MainFrame.this,
3241 indexDir.getAbsolutePath() +
3242 " is a file on your disk. Index directory must be an" +
3243 " empty folder.",
3244 "Error", JOptionPane.ERROR_MESSAGE);
3245 continue;
3246 } else if(indexDir.isDirectory() && indexDir.list().length > 0) {
3247 JOptionPane.showMessageDialog(instance,
3248 "Index directory " + indexDir.getAbsolutePath() +
3249 " must be an empty folder. ",
3250 "Error", JOptionPane.ERROR_MESSAGE);
3251 continue;
3252 } else {
3253 if(!indexDir.exists()) {
3254 if(!indexDir.mkdirs()) {
3255 JOptionPane.showMessageDialog(MainFrame.this,
3256 "Cannot create index directory " +
3257 indexDir.getAbsolutePath() + "an empty folder. ",
3258 "Error", JOptionPane.ERROR_MESSAGE);
3259 continue;
3260 }
3261 }
3262 }
3263 } catch(MalformedURLException mue) {
3264 JOptionPane.showMessageDialog(MainFrame.this,
3265 "Invalid index location "+indexLocation.getText(),
3266 "Error", JOptionPane.ERROR_MESSAGE);
3267 continue;
3268 } catch(SecurityException se) {
3269 JOptionPane.showMessageDialog(MainFrame.this,
3270 "Could not create a directory "+indexLocation.getText() +
3271 " because "+se.getMessage(),
3272 "Error", JOptionPane.ERROR_MESSAGE);
3273 continue;
3274 }
3275
3276 // if here.. an empty index directory exists
3277 // break the loop by setting validEntry to true
3278 validEntry = true;
3279 DataStore ds =
3280 Factory.createDataStore("gate.persist.LuceneDataStoreImpl",
3281 dsLocation.getText());
3282
3283 // we need to set Indexer
3284 Class[] consParam = new Class[1];
3285 consParam[0] = URL.class;
3286 Constructor constructor =
3287 Class.forName("gate.creole.annic.lucene.LuceneIndexer", true,
3288 Gate.getClassLoader()).getConstructor(consParam);
3289 Object indexer =
3290 constructor.newInstance(new URL(indexLocation.getText()));
3291
3292 Map<String, Object> parameters = new HashMap<String, Object>();
3293 parameters.put(Constants.INDEX_LOCATION_URL, new URL(indexLocation
3294 .getText()));
3295 parameters.put(Constants.BASE_TOKEN_ANNOTATION_TYPE, btat.getText());
3296 parameters.put(Constants.INDEX_UNIT_ANNOTATION_TYPE, iuat.getText());
3297 parameters.put(Constants.CREATE_TOKENS_AUTOMATICALLY,
3298 createTokensAutomatically.isSelected());
3299
3300 if(inputAS.getText().trim().length() > 0) {
3301 ArrayList<String> inputASList1 = new ArrayList<String>();
3302 String[] inputASArray = inputAS.getText().trim().split(";");
3303 if(inputASArray != null && inputASArray.length > 0) {
3304 inputASList1.addAll(Arrays.asList(inputASArray));
3305 }
3306 if(asie.getSelectedIndex() == 0) {
3307 // user has provided values for inclusion
3308 parameters.put(Constants.ANNOTATION_SETS_NAMES_TO_INCLUDE,
3309 inputASList1);
3310 parameters.put(Constants.ANNOTATION_SETS_NAMES_TO_EXCLUDE,
3311 new ArrayList<String>());
3312 }
3313 else {
3314 // user has provided values for exclusion
3315 parameters.put(Constants.ANNOTATION_SETS_NAMES_TO_EXCLUDE,
3316 inputASList1);
3317 parameters.put(Constants.ANNOTATION_SETS_NAMES_TO_INCLUDE,
3318 new ArrayList<String>());
3319 }
3320 }
3321 else {
3322 parameters.put(Constants.ANNOTATION_SETS_NAMES_TO_EXCLUDE,
3323 new ArrayList<String>());
3324 parameters.put(Constants.ANNOTATION_SETS_NAMES_TO_INCLUDE,
3325 new ArrayList<String>());
3326 }
3327
3328 if(fte.getText().trim().length() > 0) {
3329 ArrayList<String> fteList1 = new ArrayList<String>();
3330 String[] inputASArray = fte.getText().trim().split(";");
3331 if(inputASArray != null && inputASArray.length > 0) {
3332 fteList1.addAll(Arrays.asList(inputASArray));
3333 }
3334 if(ftie.getSelectedIndex() == 0) {
3335 // user has provided values for inclusion
3336 parameters.put(Constants.FEATURES_TO_INCLUDE, fteList1);
3337 parameters.put(Constants.FEATURES_TO_EXCLUDE,
3338 new ArrayList<String>());
3339 }
3340 else {
3341 // user has provided values for exclusion
3342 parameters.put(Constants.FEATURES_TO_EXCLUDE, fteList1);
3343 parameters.put(Constants.FEATURES_TO_INCLUDE,
3344 new ArrayList<String>());
3345 }
3346 }
3347 else {
3348 parameters
3349 .put(Constants.FEATURES_TO_EXCLUDE, new ArrayList<String>());
3350 parameters
3351 .put(Constants.FEATURES_TO_INCLUDE, new ArrayList<String>());
3352 }
3353
3354 Class[] params = new Class[2];
3355 params[0] =
3356 Class.forName("gate.creole.annic.Indexer", true, Gate
3357 .getClassLoader());
3358 params[1] = Map.class;
3359 Method indexerMethod = ds.getClass().getMethod("setIndexer", params);
3360 indexerMethod.invoke(ds, indexer, parameters);
3361
3362 // Class[] searchConsParams = new Class[0];
3363 Constructor searcherConst =
3364 Class.forName("gate.creole.annic.lucene.LuceneSearcher", true,
3365 Gate.getClassLoader()).getConstructor();
3366 Object searcher = searcherConst.newInstance();
3367 Class[] searchParams = new Class[1];
3368 searchParams[0] =
3369 Class.forName("gate.creole.annic.Searcher", true, Gate
3370 .getClassLoader());
3371 Method searcherMethod =
3372 ds.getClass().getMethod("setSearcher", searchParams);
3373 searcherMethod.invoke(ds, searcher);
3374 return ds;
3375 }
3376 }
3377 else {
3378 validEntry = true;
3379 }
3380 }
3381 return null;
3382 }
3383 catch(Exception e) {
3384 throw new GateRuntimeException(e);
3385 }
3386 } // createSearchableDataStore()
3387
3388 /**
3389 * Method is used in OpenDSAction
3390 * @return the opened datastore or null if an error occurs
3391 */
3392 protected DataStore openSearchableDataStore() {
3393 DataStore ds = null;
3394
3395 // get the URL (a file in this case)
3396 fileChooser.setDialogTitle("Select the datastore directory");
3397 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
3398 fileChooser.setResource("gate.DataStore.data");
3399 if(fileChooser.showOpenDialog(MainFrame.this)
3400 == JFileChooser.APPROVE_OPTION) {
3401 try {
3402 URL dsURL = fileChooser.getSelectedFile().toURI().toURL();
3403 ds =
3404 Factory.openDataStore("gate.persist.LuceneDataStoreImpl", dsURL
3405 .toExternalForm());
3406 }
3407 catch(MalformedURLException mue) {
3408 JOptionPane.showMessageDialog(MainFrame.this,
3409 "Invalid location for the datastore\n " + mue.toString(), "GATE",
3410 JOptionPane.ERROR_MESSAGE);
3411 }
3412 catch(PersistenceException pe) {
3413 JOptionPane.showMessageDialog(MainFrame.this,
3414 "Datastore opening error!\n " + pe.toString(), "GATE",
3415 JOptionPane.ERROR_MESSAGE);
3416 } // catch
3417 } // if
3418
3419 return ds;
3420 } // openSerialDataStore()
3421
3422 class NewDSAction extends AbstractAction {
3423 private static final long serialVersionUID = 1L;
3424 public NewDSAction() {
3425 super("Create Datastore");
3426 putValue(SHORT_DESCRIPTION, "Create a new datastore");
3427 putValue(SMALL_ICON, getIcon("datastore"));
3428 }
3429
3430 public void actionPerformed(ActionEvent e) {
3431 Map<String,String> dsTypes = DataStoreRegister.getDataStoreClassNames();
3432 HashMap<String,String> dsTypeByName = new HashMap<String,String>();
3433 for(Map.Entry<String, String> entry : dsTypes.entrySet()) {
3434 dsTypeByName.put(entry.getValue(), entry.getKey());
3435 }
3436
3437 if(!dsTypeByName.isEmpty()) {
3438 JLabel label = new JLabel("Select a type of Datastore:");
3439 final JList list = new JList(dsTypeByName.keySet().toArray());
3440 String initialSelection = Gate.getUserConfig().getString(
3441 MainFrame.class.getName()+".datastoretype");
3442 if (dsTypeByName.containsKey(initialSelection)) {
3443 list.setSelectedValue(initialSelection, true);
3444 } else {
3445 list.setSelectedIndex(0);
3446 }
3447 list.setVisibleRowCount(Math.min(10, list.getModel().getSize()));
3448 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
3449 final JOptionPane optionPane = new JOptionPane(
3450 new Object[]{label, new JScrollPane(list)},
3451 JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION,
3452 getIcon("datastore"), new String[]{"OK", "Cancel", "Help"}, "OK");
3453 final JDialog dialog = new JDialog(
3454 MainFrame.this, "Create a datastore", true);
3455 dialog.setContentPane(optionPane);
3456 list.addMouseListener(new MouseAdapter() {
3457 public void mouseClicked(MouseEvent e) {
3458 if (e.getClickCount() == 2) {
3459 optionPane.setValue("OK");
3460 dialog.setVisible(false);
3461 }
3462 }
3463 });
3464 optionPane.addPropertyChangeListener(new PropertyChangeListener() {
3465 public void propertyChange(PropertyChangeEvent e) {
3466 Object value = optionPane.getValue();
3467 if (value == null || value.equals(JOptionPane.UNINITIALIZED_VALUE)) {
3468 return;
3469 }
3470 if (dialog.isVisible()
3471 && e.getSource() == optionPane
3472 && e.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) {
3473 if (optionPane.getValue().equals("Help")) {
3474 // don't close the dialog
3475 optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
3476 showHelpFrame("sec:datastores", "gate.persist.SerialDataStore");
3477 } else {
3478 dialog.setVisible(false);
3479 }
3480 }
3481 }
3482 });
3483 dialog.pack();
3484 dialog.setLocationRelativeTo(MainFrame.this);
3485 dialog.setVisible(true);
3486 Object answer = optionPane.getValue();
3487 if(answer == null) { return; }
3488 String className = dsTypeByName.get(list.getSelectedValue());
3489 if(answer.equals("OK") && !list.isSelectionEmpty()) {
3490 Gate.getUserConfig().put(MainFrame.class.getName()+".datastoretype",
3491 list.getSelectedValue());
3492 if(className.equals("gate.persist.SerialDataStore")) {
3493 createSerialDataStore();
3494 }
3495 else if(className.equals("gate.persist.LuceneDataStoreImpl")) {
3496 createSearchableDataStore();
3497 }
3498 else if(className.equals("gate.persist.OracleDataStore")) {
3499 JOptionPane.showMessageDialog(MainFrame.this,
3500 "Oracle datastores can only be created "
3501 + "by your Oracle administrator!", "GATE",
3502 JOptionPane.ERROR_MESSAGE);
3503 }
3504 else {
3505 throw new UnsupportedOperationException("Unimplemented option!\n"
3506 + "Use a serial datastore");
3507 }
3508 }
3509 }
3510 else {
3511 // no ds types
3512 JOptionPane.showMessageDialog(MainFrame.this,
3513 "Could not find any registered types " + "of datastores...\n"
3514 + "Check your GATE installation!", "GATE",
3515 JOptionPane.ERROR_MESSAGE);
3516
3517 }
3518 }
3519 }// class NewDSAction extends AbstractAction
3520
3521 class LoadResourceFromFileAction extends AbstractAction {
3522 private static final long serialVersionUID = 1L;
3523 public LoadResourceFromFileAction() {
3524 super("Restore Application from File");
3525 putValue(SHORT_DESCRIPTION,
3526 "Restores a previously saved application from a file");
3527 putValue(SMALL_ICON, getIcon("open-application"));
3528 }
3529
3530 public void actionPerformed(ActionEvent e) {
3531 ExtensionFileFilter filter = new ExtensionFileFilter(
3532 "GATE Application files (.gapp, .xgapp)", ".gapp", ".xgapp");
3533 fileChooser.addChoosableFileFilter(filter);
3534 fileChooser.setFileFilter(filter);
3535 fileChooser.setDialogTitle("Select a file for this resource");
3536 fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
3537 fileChooser.setResource("lastapplication");
3538
3539 if (fileChooser.showOpenDialog(MainFrame.this)
3540 == JFileChooser.APPROVE_OPTION) {
3541 final File file = fileChooser.getSelectedFile();
3542 Runnable runnable = new Runnable() { public void run() {
3543 try {
3544 Object resource = PersistenceManager.loadObjectFromFile(file);
3545 if(resource instanceof Resource) {
3546 Map<String, String> locations = fileChooser.getLocations();
3547 Resource res = (Resource) resource;
3548 // save also the location of the application with its name
3549 locations.put("application."+res.getName(),file.getCanonicalPath());
3550 locations.put("application.zip."+res.getName(),
3551 file.getCanonicalPath().replaceFirst("\\.[^.]{3,5}$", ".zip"));
3552 // add this application to the list of recent applications
3553 String list = locations.get("applications");
3554 if (list == null) { list = ""; }
3555 list = list.replaceFirst("\\Q"+res.getName()+"\\E(;|$)", "");
3556 list = res.getName() + ";" + list;
3557 locations.put("applications", list);
3558 fileChooser.setLocations(locations);
3559 }
3560 }
3561 catch(MalformedURLException e) {
3562 log.error("Error when saving the resource URL.", e);
3563 }
3564 catch (final Exception error) {
3565 SwingUtilities.invokeLater(new Runnable() {
3566 public void run() {
3567 String message = error.getMessage();
3568 alertButton.setAction(new AlertAction(error, message, null));
3569 }
3570 });
3571 }
3572 finally {
3573 processFinished();
3574 }
3575 }};
3576 Thread thread = new Thread(runnable, "LoadResourceFromFileAction");
3577 thread.setPriority(Thread.MIN_PRIORITY);
3578 thread.start();
3579 }
3580 }
3581 }
3582
3583 /**
3584 * Closes the view associated to a resource. Does not remove the
3585 * resource from the system, only its view.
3586 */
3587 class CloseViewAction extends AbstractAction {
3588 private static final long serialVersionUID = 1L;
3589 public CloseViewAction(Handle handle) {
3590 super("Hide");
3591 putValue(SHORT_DESCRIPTION, "Hide this resource view");
3592 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control H"));
3593 this.handle = handle;
3594 }
3595
3596 public void actionPerformed(ActionEvent e) {
3597 SwingUtilities.invokeLater(new Runnable() { public void run() {
3598 mainTabbedPane.remove(handle.getLargeView());
3599 mainTabbedPane.setSelectedIndex(mainTabbedPane.getTabCount() - 1);
3600 // remove all GUI resources used by this handle
3601 handle.removeViews();
3602 }});
3603 }
3604
3605 Handle handle;
3606 }
3607
3608 class CloseViewsForSelectedResourcesAction extends AbstractAction {
3609 private static final long serialVersionUID = 1L;
3610 public CloseViewsForSelectedResourcesAction() {
3611 super("Hide all");
3612 putValue(SHORT_DESCRIPTION, "Hide the selected resources");
3613 }
3614
3615 public void actionPerformed(ActionEvent e) {
3616 Runnable runner = new Runnable() {
3617 public void run() {
3618 TreePath[] paths = resourcesTree.getSelectionPaths();
3619 for(TreePath path : paths) {
3620 final Object value = ((DefaultMutableTreeNode)
3621 path.getLastPathComponent()).getUserObject();
3622 if(value instanceof Handle) {
3623 SwingUtilities.invokeLater(new Runnable() { public void run() {
3624 new CloseViewAction((Handle)value).actionPerformed(null);
3625 }});
3626 }
3627 }
3628 }
3629 };
3630 Thread thread = new Thread(runner,
3631 "CloseViewsForSelectedResourcesAction");
3632 thread.setPriority(Thread.MIN_PRIORITY);
3633 thread.start();
3634 }
3635 }
3636
3637 class RenameResourceAction extends AbstractAction {
3638 private static final long serialVersionUID = 1L;
3639 RenameResourceAction(TreePath path) {
3640 super("Rename");
3641 putValue(SHORT_DESCRIPTION, "Rename this resource");
3642 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("F2"));
3643 this.path = path;
3644 }
3645
3646 public void actionPerformed(ActionEvent e) {
3647 resourcesTree.startEditingAtPath(path);
3648 }
3649
3650 TreePath path;
3651 }
3652
3653 class CloseSelectedResourcesAction extends AbstractAction {
3654 private static final long serialVersionUID = 1L;
3655 public CloseSelectedResourcesAction() {
3656 super("Close all");
3657 putValue(SHORT_DESCRIPTION, "Close the selected resources");
3658 }
3659
3660 public void actionPerformed(ActionEvent e) {
3661 Runnable runner = new Runnable() {
3662 public void run() {
3663 TreePath[] paths = resourcesTree.getSelectionPaths();
3664 for(TreePath path : paths) {
3665 final Object userObject = ((DefaultMutableTreeNode)
3666 path.getLastPathComponent()).getUserObject();
3667 if(userObject instanceof NameBearerHandle) {
3668 SwingUtilities.invokeLater(new Runnable() { public void run() {
3669 ((NameBearerHandle)userObject).getCloseAction()
3670 .actionPerformed(null);
3671 }});
3672 }
3673 }
3674 }
3675 };
3676 Thread thread = new Thread(runner, "CloseSelectedResourcesAction");
3677 thread.setPriority(Thread.MIN_PRIORITY);
3678 thread.start();
3679 }
3680 }
3681
3682 class CloseRecursivelySelectedResourcesAction extends AbstractAction {
3683 private static final long serialVersionUID = 1L;
3684 public CloseRecursivelySelectedResourcesAction() {
3685 super("Close Recursively all");
3686 putValue(SHORT_DESCRIPTION, "Close recursively the selected resources");
3687 }
3688
3689 public void actionPerformed(ActionEvent e) {
3690 Runnable runner = new Runnable() {
3691 public void run() {
3692 TreePath[] paths = resourcesTree.getSelectionPaths();
3693 for(TreePath path : paths) {
3694 final Object userObject = ((DefaultMutableTreeNode)
3695 path.getLastPathComponent()).getUserObject();
3696 if(userObject instanceof NameBearerHandle) {
3697 SwingUtilities.invokeLater(new Runnable() { public void run() {
3698 ((NameBearerHandle)userObject).getCloseRecursivelyAction()
3699 .actionPerformed(null);
3700 }});
3701 }
3702 }
3703 }
3704 };
3705 Thread thread = new Thread(runner,
3706 "CloseRecursivelySelectedResourcesAction");
3707 thread.setPriority(Thread.MIN_PRIORITY);
3708 thread.start();
3709 }
3710 }
3711
3712 class HideAllAction extends AbstractAction {
3713 private static final long serialVersionUID = 1L;
3714 public HideAllAction() {
3715 super("Hide all");
3716 putValue(SHORT_DESCRIPTION, "Hide all resource views");
3717 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control shift H"));
3718 }
3719
3720 public void actionPerformed(ActionEvent e) {
3721 // for each element in the tree look if it is in the tab panel
3722 // if yes, remove it from the tab panel
3723 Enumeration nodesEnum = resourcesTreeRoot.preorderEnumeration();
3724 DefaultMutableTreeNode node;
3725 while(nodesEnum.hasMoreElements()) {
3726 node = (DefaultMutableTreeNode)nodesEnum.nextElement();
3727 if ((node.getUserObject() instanceof Handle)
3728 && (mainTabbedPane.indexOfComponent(
3729 ((Handle)node.getUserObject()).getLargeView()) != -1)) {
3730 final Handle handle = (Handle)node.getUserObject();
3731 SwingUtilities.invokeLater(new Runnable() { public void run() {
3732 (new CloseViewAction(handle)).actionPerformed(null);
3733 }});
3734 }
3735 }
3736 }
3737 }
3738
3739 class ShowSelectedResourcesAction extends AbstractAction {
3740 private static final long serialVersionUID = 1L;
3741 public ShowSelectedResourcesAction() {
3742 super("Show all");
3743 putValue(SHORT_DESCRIPTION, "Show the selected resources");
3744 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("Enter"));
3745 }
3746
3747 public void actionPerformed(ActionEvent e) {
3748 Runnable runner = new Runnable() {
3749 public void run() {
3750 TreePath[] paths = resourcesTree.getSelectionPaths();
3751 if (paths == null) { return; }
3752 if (paths.length > 10) {
3753 Object[] possibleValues =
3754 { "Open the "+paths.length+" objects", "Don't open" };
3755 int selectedValue =
3756 JOptionPane.showOptionDialog(instance, "Do you want to open "
3757 +paths.length+" objects in the central tabbed pane ?",
3758 "Warning", JOptionPane.DEFAULT_OPTION,
3759 JOptionPane.QUESTION_MESSAGE, null,
3760 possibleValues, possibleValues[1]);
3761 if (selectedValue == 1
3762 || selectedValue == JOptionPane.CLOSED_OPTION) {
3763 return;
3764 }
3765 }
3766 for (TreePath path : paths) {
3767 if(path != null) {
3768 Object value = path.getLastPathComponent();
3769 value = ((DefaultMutableTreeNode)value).getUserObject();
3770 if(value instanceof Handle) {
3771 final Handle handle = (Handle)value;
3772 SwingUtilities.invokeLater(new Runnable() { public void run() {
3773 select(handle);
3774 }});
3775 }
3776 }
3777 }
3778 }
3779 };
3780 Thread thread = new Thread(runner, "ShowSelectedResourcesAction");
3781 thread.setPriority(Thread.MIN_PRIORITY);
3782 thread.start();
3783 }
3784 }
3785
3786 class ShowResourceAction extends AbstractAction {
3787 private static final long serialVersionUID = 1L;
3788 Handle handle;
3789 public ShowResourceAction(Handle handle) {
3790 super("Show");
3791 putValue(SHORT_DESCRIPTION, "Show this resource");
3792 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("Enter"));
3793 this.handle = handle;
3794 }
3795
3796 public void actionPerformed(ActionEvent e) {
3797 SwingUtilities.invokeLater(new Runnable() {
3798 public void run() { select(handle); }
3799 });
3800 }
3801 }
3802
3803 /**
3804 * Closes the view associated to a resource. Does not remove the
3805 * resource from the system, only its view.
3806 */
3807 class ExitGateAction extends AbstractAction {
3808 private static final long serialVersionUID = 1L;
3809 public ExitGateAction() {
3810 super("Exit GATE");
3811 putValue(SHORT_DESCRIPTION, "Closes the application");
3812 putValue(SMALL_ICON, getIcon("crystal-clear-action-exit"));
3813 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt F4"));
3814 }
3815
3816 public void actionPerformed(ActionEvent e) {
3817 Runnable runnable = new Runnable() {
3818 public void run() {
3819 // save the options
3820 OptionsMap userConfig = Gate.getUserConfig();
3821 try {
3822 if(userConfig.getBoolean(GateConstants.SAVE_OPTIONS_ON_EXIT)) {
3823 // save the window size
3824 Integer width = MainFrame.this.getWidth();
3825 Integer height = MainFrame.this.getHeight();
3826 userConfig.put(GateConstants.MAIN_FRAME_WIDTH, width);
3827 userConfig.put(GateConstants.MAIN_FRAME_HEIGHT, height);
3828 Gate.writeUserConfig();
3829 }
3830 else {
3831 // don't save options on close
3832 // save the option not to save the options
3833 OptionsMap originalUserConfig = Gate.getOriginalUserConfig();
3834 originalUserConfig.put(GateConstants.SAVE_OPTIONS_ON_EXIT, false);
3835 userConfig.clear();
3836 userConfig.putAll(originalUserConfig);
3837 Gate.writeUserConfig();
3838 }
3839 }
3840 catch(GateException error) {
3841 String message = "Failed to save config data.";
3842 alertButton.setAction(new AlertAction(error, message, null));
3843 }
3844
3845 // save the session;
3846 File sessionFile = Gate.getUserSessionFile();
3847 if(userConfig.getBoolean(GateConstants.SAVE_SESSION_ON_EXIT)) {
3848 // save all the open applications
3849 try {
3850 ArrayList<Resource> appList = new ArrayList<Resource>(
3851 Gate.getCreoleRegister().getAllInstances("gate.Controller"));
3852 // remove all hidden instances
3853 Iterator appIter = appList.iterator();
3854 while(appIter.hasNext()) {
3855 if(Gate.getHiddenAttribute(((Controller)appIter.next())
3856 .getFeatures())) { appIter.remove(); }
3857 }
3858 // When saving the session file, save URLs relative to GATE home
3859 // but do not warn about them
3860 gate.util.persistence.PersistenceManager.saveObjectToFile(
3861 appList, sessionFile, true, false);
3862 }
3863 catch(Exception error) {
3864 String message = "Failed to save session data.";
3865 alertButton.setAction(new AlertAction(error, message, null));
3866 }
3867 }
3868 else {
3869 // we don't want to save the session
3870 if(sessionFile.exists() && !sessionFile.delete()) {
3871 log.error("Error when deleting the session file.");
3872 }
3873 }
3874
3875 // restore out and err streams as we're about to hide the
3876 // windows
3877 System.setErr(logArea.getOriginalErr());
3878 System.setOut(logArea.getOriginalOut());
3879 // now we need to dispose all GUI roots
3880 List<Component> roots = new ArrayList<Component>(getGuiRoots());
3881 while(!roots.isEmpty()) {
3882 Component aRoot = roots.remove(0);
3883 if(aRoot instanceof Window) {
3884 Window window = (Window)aRoot;
3885 roots.addAll(Arrays.asList(window.getOwnedWindows()));
3886 window.setVisible(false);
3887 window.dispose();
3888 }
3889 }
3890
3891 // only hidden when closed
3892 if(helpFrame != null) helpFrame.dispose();
3893
3894 // trying to release all resources occupied by all
3895 try {
3896 //make a list of lists of resources of various kinds
3897 List<List<Resource>> listOfListOfResources =
3898 new ArrayList<List<Resource>>();
3899 // listOfListOfResoruces.add(Gate.getCreoleRegister().getAllInstances(
3900 // gate.VisualResource.class.getName()));
3901 listOfListOfResources.add(Gate.getCreoleRegister().getAllInstances(
3902 gate.LanguageResource.class.getName()));
3903 listOfListOfResources.add(Gate.getCreoleRegister().getAllInstances(
3904 gate.ProcessingResource.class.getName()));
3905 listOfListOfResources.add(Gate.getCreoleRegister().getAllInstances(
3906 gate.Controller.class.getName()));
3907
3908 for(List<Resource> resources :listOfListOfResources){
3909 // we need to call the clean up method for each of these resources
3910 for(Resource aResource : resources) {
3911 try {
3912 Factory.deleteResource(aResource);
3913 } catch(Throwable e) {
3914 // this may throw somekind of exception
3915 // but we just ignore it as anyway we are closing everything
3916 log.error(
3917 "Some problems occurred when cleaning up the resources.", e);
3918 }
3919 }
3920 }
3921
3922 // close all the opened datastores
3923 if(Gate.getDataStoreRegister() != null) {
3924 Set dataStores = new HashSet(Gate.getDataStoreRegister());
3925 for(Object aDs : dataStores) {
3926 try {
3927 if(aDs instanceof DataStore) {
3928 ((DataStore)aDs).close();
3929 }
3930 }
3931 catch(Throwable e) {
3932 log.error(
3933 "Some problems occurred when closing the datastores.", e);
3934 }
3935 }
3936 }
3937
3938 }
3939 catch(GateException e) {
3940 // we just ignore this
3941 log.error("A problem occurred when exiting from GATE.", e);
3942 }
3943
3944 }// run
3945 };// Runnable
3946 Thread thread =
3947 new Thread(Thread.currentThread().getThreadGroup(), runnable,
3948 "Shutdown thread");
3949 thread.setPriority(Thread.MIN_PRIORITY);
3950 thread.start();
3951 }
3952 }
3953
3954 class OpenDSAction extends AbstractAction {
3955 private static final long serialVersionUID = 1L;
3956 public OpenDSAction() {
3957 super("Open Datastore");
3958 putValue(SHORT_DESCRIPTION, "Open a datastore");
3959 putValue(SMALL_ICON, getIcon("datastore"));
3960 }
3961
3962 public void actionPerformed(ActionEvent e) {
3963 Map<String,String> dsTypes = DataStoreRegister.getDataStoreClassNames();
3964 HashMap<String,String> dsTypeByName = new HashMap<String,String>();
3965 for(Map.Entry<String, String> entry : dsTypes.entrySet()) {
3966 dsTypeByName.put(entry.getValue(), entry.getKey());
3967 }
3968
3969 if(!dsTypeByName.isEmpty()) {
3970 JLabel label = new JLabel("Select a type of Datastore:");
3971 final JList list = new JList(dsTypeByName.keySet().toArray());
3972 String initialSelection = Gate.getUserConfig().getString(
3973 MainFrame.class.getName()+".datastoretype");
3974 if (dsTypeByName.containsKey(initialSelection)) {
3975 list.setSelectedValue(initialSelection, true);
3976 } else {
3977 list.setSelectedIndex(0);
3978 }
3979 list.setVisibleRowCount(Math.min(10, list.getModel().getSize()));
3980 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
3981 final JOptionPane optionPane = new JOptionPane(
3982 new Object[]{label, new JScrollPane(list)},
3983 JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION,
3984 getIcon("datastore"), new String[]{"OK", "Cancel", "Help"}, "OK");
3985 final JDialog dialog = new JDialog(
3986 MainFrame.this, "Open a datastore", true);
3987 dialog.setContentPane(optionPane);
3988 list.addMouseListener(new MouseAdapter() {
3989 public void mouseClicked(MouseEvent e) {
3990 if (e.getClickCount() == 2) {
3991 optionPane.setValue("OK");
3992 dialog.setVisible(false);
3993 }
3994 }
3995 });
3996 optionPane.addPropertyChangeListener(new PropertyChangeListener() {
3997 public void propertyChange(PropertyChangeEvent e) {
3998 Object value = optionPane.getValue();
3999 if (value == null || value.equals(JOptionPane.UNINITIALIZED_VALUE)) {
4000 return;
4001 }
4002 if (dialog.isVisible()
4003 && e.getSource() == optionPane
4004 && e.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) {
4005 if (optionPane.getValue().equals("Help")) {
4006 // don't close the dialog
4007 optionPane.setValue(JOptionPane.UNINITIALIZED_VALUE);
4008 showHelpFrame("sec:datastores", "gate.persist.SerialDataStore");
4009 } else {
4010 dialog.setVisible(false);
4011 }
4012 }
4013 }
4014 });
4015 dialog.pack();
4016 dialog.setLocationRelativeTo(MainFrame.this);
4017 dialog.setVisible(true);
4018 Object answer = optionPane.getValue();
4019 if(answer == null) { return; }
4020 String className = dsTypeByName.get(list.getSelectedValue());
4021 if(answer.equals("OK") && !list.isSelectionEmpty()) {
4022 Gate.getUserConfig().put(MainFrame.class.getName()
4023 + ".datastoretype", list.getSelectedValue());
4024 if(className.indexOf("SerialDataStore") != -1) {
4025 openSerialDataStore();
4026 }
4027 else if(className.indexOf("LuceneDataStoreImpl") != -1) {
4028 openSearchableDataStore();
4029 }
4030 else if(className.indexOf("DocServiceDataStore") != -1) {
4031 openDocServiceDataStore();
4032 }
4033 else if(className.equals("gate.persist.OracleDataStore")
4034 || className.equals("gate.persist.PostgresDataStore")) {
4035 List dbPaths = new ArrayList();
4036 for(Object o : DataStoreRegister.getConfigData().keySet()) {
4037 String keyName = (String) o;
4038 if(keyName.startsWith("url")) {
4039 dbPaths.add(DataStoreRegister.getConfigData().get(keyName));
4040 }
4041 }
4042 if(dbPaths.isEmpty())
4043 throw new GateRuntimeException(
4044 "JDBC URL not configured in gate.xml");
4045 // by default make it the first
4046 String storageURL = (String)dbPaths.get(0);
4047 if(dbPaths.size() > 1) {
4048 Object[] paths = dbPaths.toArray();
4049 answer =
4050 JOptionPane.showInputDialog(MainFrame.this,
4051 "Select a database", "GATE", JOptionPane.QUESTION_MESSAGE,
4052 null, paths, paths[0]);
4053 if(answer != null)
4054 storageURL = (String)answer;
4055 else return;
4056 }
4057 DataStore ds = null;
4058 AccessController ac = null;
4059 try {
4060 // 1. login the user
4061 // ac = new AccessControllerImpl(storageURL);
4062 ac = Factory.createAccessController(storageURL);
4063 Assert.assertNotNull(ac);
4064 ac.open();
4065
4066 Session mySession;
4067 User usr;
4068 Group grp;
4069 try {
4070 String userName = "";
4071 String userPass = "";
4072 String group = "";
4073
4074 JPanel listPanel = new JPanel();
4075 listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.X_AXIS));
4076
4077 JPanel panel1 = new JPanel();
4078 panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));
4079 panel1.add(new JLabel("User name: "));
4080 panel1.add(new JLabel("Password: "));
4081 panel1.add(new JLabel("Group: "));
4082
4083 JPanel panel2 = new JPanel();
4084 panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
4085 JTextField usrField = new JTextField(30);
4086 panel2.add(usrField);
4087 JPasswordField pwdField = new JPasswordField(30);
4088 panel2.add(pwdField);
4089 JComboBox grpField = new JComboBox(ac.listGroups().toArray());
4090 grpField.setSelectedIndex(0);
4091 panel2.add(grpField);
4092
4093 listPanel.add(panel1);
4094 listPanel.add(Box.createHorizontalStrut(20));
4095 listPanel.add(panel2);
4096
4097 if(OkCancelDialog.showDialog(MainFrame.this.getContentPane(),
4098 listPanel, "Please enter login details")) {
4099
4100 userName = usrField.getText();
4101 userPass = new String(pwdField.getPassword());
4102 group = (String)grpField.getSelectedItem();
4103
4104 if(userName.equals("") || userPass.equals("")
4105 || group.equals("")) {
4106 JOptionPane
4107 .showMessageDialog(
4108 MainFrame.this,
4109 "You must provide non-empty user name, password and group!",
4110 "Login error", JOptionPane.ERROR_MESSAGE);
4111 return;
4112 }
4113 }
4114 else if(OkCancelDialog.userHasPressedCancel) { return; }
4115
4116 grp = ac.findGroup(group);
4117 usr = ac.findUser(userName);
4118 mySession = ac.login(userName, userPass, grp.getID());
4119
4120 // save here the user name, pass and group in
4121 // local gate.xml
4122
4123 }
4124 catch(gate.security.SecurityException ex) {
4125 JOptionPane.showMessageDialog(MainFrame.this, ex.getMessage(),
4126 "Login error", JOptionPane.ERROR_MESSAGE);
4127 ac.close();
4128 return;
4129 }
4130
4131 if(!ac.isValidSession(mySession)) {
4132 JOptionPane.showMessageDialog(MainFrame.this,
4133 "Incorrect session obtained. "
4134 + "Probably there is a problem with the database!",
4135 "Login error", JOptionPane.ERROR_MESSAGE);
4136 ac.close();
4137 return;
4138 }
4139
4140 // 2. open the oracle datastore
4141 ds = Factory.openDataStore(className, storageURL);
4142 // set the session, so all get/adopt/etc work
4143 ds.setSession(mySession);
4144
4145 // 3. add the security data for this datastore
4146 // this saves the user and group information, so it
4147 // can
4148 // be used later when resources are created with
4149 // certain rights
4150 FeatureMap securityData = Factory.newFeatureMap();
4151 securityData.put("user", usr);
4152 securityData.put("group", grp);
4153 DataStoreRegister.addSecurityData(ds, securityData);
4154 }
4155 catch(PersistenceException pe) {
4156 JOptionPane.showMessageDialog(MainFrame.this,
4157 "Datastore open error!\n " + pe.toString(), "GATE",
4158 JOptionPane.ERROR_MESSAGE);
4159 }
4160 catch(gate.security.SecurityException se) {
4161 JOptionPane.showMessageDialog(MainFrame.this,
4162 "User identification error!\n " + se.toString(), "GATE",
4163 JOptionPane.ERROR_MESSAGE);
4164 try {
4165 if(ac != null) ac.close();
4166 if(ds != null) ds.close();
4167 }
4168 catch(gate.persist.PersistenceException ex) {
4169 JOptionPane.showMessageDialog(MainFrame.this,
4170 "Persistence error!\n " + ex.toString(), "GATE",
4171 JOptionPane.ERROR_MESSAGE);
4172 }
4173 }
4174
4175 }
4176 else {
4177 JOptionPane.showMessageDialog(MainFrame.this,
4178 "Support for this type of datastores is not implemenented!\n",
4179 "GATE", JOptionPane.ERROR_MESSAGE);
4180 }
4181 }
4182 }
4183 else {
4184 // no ds types
4185 JOptionPane.showMessageDialog(MainFrame.this,
4186 "Could not find any registered types " + "of datastores...\n"
4187 + "Check your GATE installation!", "GATE",
4188 JOptionPane.ERROR_MESSAGE);
4189
4190 }
4191 }
4192 }// class OpenDSAction extends AbstractAction
4193
4194 /**
4195 * A menu that self populates based on CREOLE register data before
4196 * being shown. Used for creating new resources of all possible types.
4197 */
4198 class LiveMenu extends XJMenu {
4199 public LiveMenu(int type) {
4200 super();
4201 this.type = type;
4202 init();
4203 }
4204
4205 protected void init() {
4206 addMenuListener(new MenuListener() {
4207 public void menuCanceled(MenuEvent e) {
4208 // do nothing
4209 }
4210 public void menuDeselected(MenuEvent e) {
4211 // clear the status
4212 statusChanged("");
4213 }
4214 public void menuSelected(MenuEvent e) {
4215 removeAll();
4216 // find out the available types of LRs and repopulate the menu
4217 CreoleRegister reg = Gate.getCreoleRegister();
4218 List<String> resTypes;
4219 switch(type){
4220 case LR:
4221 resTypes = reg.getPublicLrTypes();
4222 break;
4223 case PR:
4224 resTypes = new ArrayList<String>( reg.getPublicPrTypes() );
4225 //GATE default controllers are now also PRs, but we don't want
4226 //them here
4227 resTypes.removeAll(reg.getPublicControllerTypes());
4228 break;
4229 case APP:
4230 resTypes = reg.getPublicControllerTypes();
4231 break;
4232 default:
4233 throw new GateRuntimeException("Unknown LiveMenu type: " + type);
4234 }
4235
4236 if(resTypes != null) {
4237 if (!resTypes.isEmpty()) {
4238 HashMap<String, ResourceData> resourcesByName
4239 = new HashMap<String, ResourceData>();
4240 Iterator<String> resIter = resTypes.iterator();
4241 while(resIter.hasNext()) {
4242 ResourceData rData = reg.get(resIter.next());
4243 resourcesByName.put(rData.getName(), rData);
4244 }
4245 List<String> resNames =
4246 new ArrayList<String>(resourcesByName.keySet());
4247 Collections.sort(resNames);
4248 resIter = resNames.iterator();
4249 while(resIter.hasNext()) {
4250 ResourceData rData = resourcesByName.get(resIter.next());
4251 add(new XJMenuItem(new NewResourceAction(rData), MainFrame.this));
4252 }
4253 } else if (type == PR) {
4254 // empty PR menu -> add an action to load ANNIE plugin
4255 add(new AbstractAction("Add ANNIE Resources to this Menu") {
4256 { putValue(SHORT_DESCRIPTION, "Load the ANNIE plugin."); }
4257 public void actionPerformed(ActionEvent e) {
4258 try {
4259 URL pluginUrl = new File(Gate.getPluginsHome(),
4260 ANNIEConstants.PLUGIN_DIR).toURI().toURL();
4261 Gate.getCreoleRegister().registerDirectories(pluginUrl);
4262 Gate.addAutoloadPlugin(pluginUrl);
4263 } catch(Exception ex) {
4264 log.error("Unable to load ANNIE plugin.", ex);
4265 }
4266 }});
4267 }
4268 }
4269
4270 // fire the status listener events
4271 switch(type){
4272 case LR:
4273 statusChanged("Data used for annotating");
4274 break;
4275 case PR:
4276 statusChanged("Processes that annotate data");
4277 break;
4278 case APP:
4279 statusChanged("Run processes on data");
4280 break;
4281 default:
4282 statusChanged("Unknown resource: " + type);
4283 }
4284 }
4285 });
4286 }
4287
4288 protected int type;
4289
4290 /**
4291 * Switch for using LR data.
4292 */
4293 public static final int LR = 1;
4294
4295 /**
4296 * Switch for using PR data.
4297 */
4298 public static final int PR = 2;
4299
4300 /**
4301 * Switch for using Controller data.
4302 */
4303 public static final int APP = 3;
4304 }
4305
4306 /**
4307 * Recent applications menu that remembers previously loaded applications.
4308 */
4309 class RecentAppsMenu extends XJMenu {
4310 public RecentAppsMenu() {
4311 super();
4312 init();
4313 addMenuItems();
4314 }
4315
4316 protected void init() {
4317 addMenuListener(new MenuListener() {
4318 public void menuCanceled(MenuEvent e) {
4319 // do nothing
4320 }
4321 public void menuDeselected(MenuEvent e) {
4322 // clear the status
4323 statusChanged("");
4324 }
4325 public void menuSelected(MenuEvent e) {
4326 removeAll();
4327 addMenuItems();
4328 if (getMenuComponentCount() == 0) {
4329 add("No Recent Applications");
4330 }
4331 }
4332 });
4333 }
4334
4335 protected void addMenuItems() {
4336 final Map<String, String> locations = fileChooser.getLocations();
4337 final String list = locations.get("applications");
4338 if (list == null || list.equals("")) { return; }
4339 for (final String name : list.split(";")) {
4340 final String location = locations.get("application." + name);
4341 final XJMenuItem item = new XJMenuItem(new AbstractAction(name,
4342 MainFrame.getIcon("open-application")) {
4343 { this.putValue(Action.SHORT_DESCRIPTION, location); }
4344 public void actionPerformed(ActionEvent e) {
4345 Runnable runnable = new Runnable() { public void run() {
4346 try { File file = new File(location);
4347 PersistenceManager.loadObjectFromFile(file);
4348 } catch(Exception e) {
4349 String message = "Couldn't reload application.\n" + e.getMessage();
4350 alertButton.setAction(new AlertAction(e, message, null));
4351 if (e instanceof IOException) {
4352 // remove selected element from the applications list
4353 locations.put("applications", list.replaceFirst(name + "(;|$)", ""));
4354 fileChooser.setLocations(locations);
4355 }
4356 } finally { processFinished(); }}};
4357 Thread thread = new Thread(runnable ,"Reload application");
4358 thread.setPriority(Thread.MIN_PRIORITY);
4359 thread.start();
4360 }}, MainFrame.this);
4361 item.addMenuKeyListener(new MenuKeyListener() {
4362 public void menuKeyTyped(MenuKeyEvent e) { /* do nothing */ }
4363 public void menuKeyPressed(MenuKeyEvent e) {
4364 if (e.getKeyCode() == KeyEvent.VK_DELETE) {
4365 // remove selected element from the applications list
4366 locations.put("applications", list.replaceFirst(name + "(;|$)", ""));
4367 fileChooser.setLocations(locations);
4368 // TODO: update the menu
4369 // item.setVisible(false);
4370 // item.revalidate();
4371 }
4372 }
4373 public void menuKeyReleased(MenuKeyEvent e) {/* do nothing */ }
4374 });
4375 add(item);
4376 }
4377 add(new XJMenuItem(new AbstractAction("Clear List") {
4378 public void actionPerformed(ActionEvent e) {
4379 // clear the applications list
4380 locations.put("applications", "");
4381 fileChooser.setLocations(locations);
4382 }}, MainFrame.this));
4383 }
4384 }
4385
4386 /**
4387 * The "Tools" menu, which includes some static menu items
4388 * (added in initGuiComponents) and some dynamic items contributed
4389 * by plugins.
4390 * @author ian
4391 */
4392 class ToolsMenu extends XJMenu implements CreoleListener {
4393
4394 /**
4395 * The first position in the menu that can be used by dynamic
4396 * items.
4397 */
4398 protected int firstPluginItem = 0;
4399
4400 protected IdentityHashMap<Resource, List<JMenuItem>> itemsByResource =
4401 new IdentityHashMap<Resource, List<JMenuItem>>();
4402
4403 public ToolsMenu(String name, String description, StatusListener listener) {
4404 super(name, description, listener);
4405 Gate.getCreoleRegister().addCreoleListener(this);
4406 }
4407
4408 /**
4409 * Called when the static items have been added to inform the menu
4410 * that it can start doing its dynamic stuff.
4411 */
4412 public void staticItemsAdded() {
4413 firstPluginItem = getItemCount();
4414 processExistingTools();
4415 }
4416
4417 /**
4418 * Populate the menu with all actions coming from tools that are
4419 * already loaded.
4420 */
4421 protected void processExistingTools() {
4422 Set<String> toolTypes = Gate.getCreoleRegister().getToolTypes();
4423 for(String type : toolTypes) {
4424 List<Resource> instances = Gate.getCreoleRegister()
4425 .get(type).getInstantiations();
4426 for(Resource res : instances) {
4427 if(res instanceof ActionsPublisher) {
4428 toolLoaded(res);
4429 }
4430 }
4431 }
4432 }
4433
4434 /**
4435 * If the resource just loaded is a tool (according to the creole
4436 * register) then see if it publishes any actions and if so, add
4437 * them to the menu in the appropriate places.
4438 */
4439 public void resourceLoaded(CreoleEvent e) {
4440 Resource res = e.getResource();
4441 if(Gate.getCreoleRegister().get(res.getClass().getName()).isTool()
4442 && res instanceof ActionsPublisher) {
4443 toolLoaded(res);
4444 }
4445 }
4446
4447 /**
4448 * Add the actions published by the given tool to their appropriate
4449 * places on the Tools menu.
4450 * @param res the tool instance (which must implement ActionsPublisher)
4451 */
4452 protected void toolLoaded(Resource res) {
4453 List<Action> actions = ((ActionsPublisher)res).getActions();
4454 List<JMenuItem> items = new ArrayList<JMenuItem>();
4455 for(Action a : actions) {
4456 items.add(addMenuItem(a));
4457 }
4458 itemsByResource.put(res, items);
4459 }
4460
4461 protected JMenuItem addMenuItem(Action a) {
4462 // start by searching this menu
4463 XJMenu menuToUse = this;
4464 int firstIndex = firstPluginItem;
4465 // if the action has a menu path set, navigate the path to find the
4466 // right menu.
4467 String[] menuPath = (String[])a.getValue(GateConstants.MENU_PATH_KEY);
4468 if(menuPath != null) {
4469 PATH_ELEMENT: for(String pathElement : menuPath) {
4470 int i;
4471 for(i = firstIndex; i < menuToUse.getItemCount(); i++) {
4472 JMenuItem item = menuToUse.getItem(i);
4473 if(item instanceof XJMenu && item.getText().equals(pathElement)) {
4474 // found the menu for this path element, move on to the next one
4475 firstIndex = 0;
4476 menuToUse = (XJMenu)item;
4477 continue PATH_ELEMENT;
4478 }
4479 else if(item.getText().compareTo(pathElement) < 0) {
4480 // we've gone beyond where this menu should be in alpha
4481 // order
4482 break;
4483 }
4484 }
4485 // if we get to here, we didn't find a menu to use - add one
4486 XJMenu newMenu = new XJMenu(pathElement, pathElement, this.listener);
4487 menuToUse.add(newMenu);
4488 firstIndex = 0;
4489 menuToUse = newMenu;
4490 }
4491 }
4492
4493 // we now have the right menu, add the action at the right place
4494 int pos = firstIndex;
4495 while(pos < menuToUse.getItemCount()) {
4496 JMenuItem item = menuToUse.getItem(pos);
4497 if(item != null && item.getText().compareTo((String)a.getValue(Action.NAME)) > 0) {
4498 break;
4499 }
4500 pos++;
4501 }
4502 // finally, add the menu item and return it
4503 return menuToUse.insert(new XJMenuItem(a, this.listener), pos);
4504 }
4505
4506 /**
4507 * If the resource just unloaded is one that contributed some menu
4508 * items then remove them again.
4509 */
4510 public void resourceUnloaded(CreoleEvent e) {
4511 Resource res = e.getResource();
4512 List<JMenuItem> items = itemsByResource.remove(res);
4513 if(items != null) {
4514 for(JMenuItem item : items) {
4515 removeMenuItem(item);
4516 }
4517 }
4518 }
4519
4520 protected void removeMenuItem(JMenuItem itemToRemove) {
4521 Action a = itemToRemove.getAction();
4522 // start by searching this menu
4523 XJMenu menuToUse = this;
4524 int firstIndex = firstPluginItem;
4525 // keep track of the parent menu
4526 XJMenu parentMenu = null;
4527 // if the action has a menu path set, navigate the path to find the
4528 // right menu.
4529 String[] menuPath = (String[])a.getValue(GateConstants.MENU_PATH_KEY);
4530 if(menuPath != null) {
4531 PATH_ELEMENT: for(String pathElement : menuPath) {
4532 int i;
4533 for(i = firstIndex; i < menuToUse.getItemCount(); i++) {
4534 JMenuItem item = menuToUse.getItem(i);
4535 if(item instanceof XJMenu && item.getText().equals(pathElement)) {
4536 // found the menu for this path element, move on to the next one
4537 firstIndex = 0;
4538 parentMenu = menuToUse;
4539 menuToUse = (XJMenu)item;
4540 continue PATH_ELEMENT;
4541 }
4542 }
4543 // we've reached the end of a menu without finding the sub-menu
4544 // we were looking for. This shouldn't happen, but if it does then
4545 // we can ignore it as if there's no menu to remove the thing from
4546 // then there's nothing to remove either.
4547 return;
4548 }
4549 }
4550
4551 // we have a menu to remove the item from: remove it
4552 menuToUse.remove(itemToRemove);
4553 if(menuToUse.getItemCount() == 0 && parentMenu != null) {
4554 // sub-menu is empty, remove it from parent
4555 parentMenu.remove(menuToUse);
4556 }
4557 }
4558
4559 // remaining CreoleListener methods not used
4560 public void datastoreClosed(CreoleEvent e) { }
4561 public void datastoreCreated(CreoleEvent e) { }
4562 public void datastoreOpened(CreoleEvent e) { }
4563 public void resourceRenamed(Resource resource, String oldName,
4564 String newName) { }
4565 }
4566
4567 /**
4568 * Overrides default JTree behaviour for tooltips.
4569 */
4570 class ResourcesTree extends JTree {
4571 private static final long serialVersionUID = 1L;
4572
4573 public ResourcesTree() {
4574 myToolTip = new ResourceToolTip();
4575 }
4576
4577 /**
4578 * Overrides <code>JTree</code>'s <code>getToolTipText</code>
4579 * method in order to allow custom tips to be used.
4580 *
4581 * @param event the <code>MouseEvent</code> that initiated the
4582 * <code>ToolTip</code> display
4583 * @return a string containing the tooltip or <code>null</code> if
4584 * <code>event</code> is null
4585 */
4586 public String getToolTipText(MouseEvent event) {
4587 String res = super.getToolTipText(event);
4588 if(event != null) {
4589 Point p = event.getPoint();
4590 int selRow = getRowForLocation(p.x, p.y);
4591 if(selRow != -1) {
4592 TreePath path = getPathForRow(selRow);
4593 Object lastPath = path.getLastPathComponent();
4594 Object value = ((DefaultMutableTreeNode)lastPath).getUserObject();
4595 myToolTip.setValue(value);
4596 }
4597 }
4598 // if we always return the same text, the tooltip manager thinks
4599 // the
4600 // size and location don't need changing.
4601 return res;
4602 }
4603
4604 public JToolTip createToolTip() {
4605 return myToolTip;
4606 }
4607
4608 ResourceToolTip myToolTip;
4609 }
4610
4611 /**
4612 * Implementation of a custom tool tip to be used for showing extended
4613 * information about CREOLE resources.
4614 *
4615 */
4616 class ResourceToolTip extends JToolTip {
4617 private static final long serialVersionUID = 1L;
4618 public ResourceToolTip() {
4619 this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
4620
4621 tipComponent = new JPanel();
4622 tipComponent.setOpaque(false);
4623 tipComponent.setLayout(new BoxLayout(tipComponent, BoxLayout.X_AXIS));
4624 tipComponent.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
4625
4626 iconLabel = new JLabel(getIcon("annie-application"));
4627 iconLabel.setText(null);
4628 iconLabel.setOpaque(false);
4629 tipComponent.add(iconLabel);
4630
4631 textLabel = new JLabel();
4632 textLabel.setOpaque(false);
4633 tipComponent.add(Box.createHorizontalStrut(10));
4634 tipComponent.add(textLabel);
4635
4636 add(tipComponent);
4637 }
4638
4639 /**
4640 * Label used for the icon
4641 */
4642 JLabel iconLabel;
4643
4644 /**
4645 * Label used for the text
4646 */
4647 JLabel textLabel;
4648
4649 /**
4650 * The actual component displaying the tooltip.
4651 */
4652 JPanel tipComponent;
4653
4654 public void setTipText(String tipText) {
4655 // textLabel.setText(tipText);
4656 }
4657
4658 /**
4659 * Sets the value to be displayed
4660 *
4661 * @param value to be displayed as tooltip
4662 */
4663 public void setValue(Object value) {
4664 if(value != null) {
4665 if(value instanceof String) {
4666 String text = (String) value;
4667 if (text.equals("GATE")) {
4668 textLabel.setText("Resources tree root ");
4669 iconLabel.setIcon(getIcon("root"));
4670 } else if (text.equals("Applications")) {
4671 textLabel.setText("Applications: run processes on data ");
4672 iconLabel.setIcon(getIcon("applications"));
4673 } else if (text.equals("Language Resources")) {
4674 textLabel.setText("Language Resources: data used for annotating ");
4675 iconLabel.setIcon(getIcon("lrs"));
4676 } else if (text.equals("Processing Resources")) {
4677 textLabel.setText(
4678 "Processing Resources: processes that annotate data ");
4679 iconLabel.setIcon(getIcon("prs"));
4680 } else if (text.equals("Datastores")) {
4681 textLabel.setText("Datastores: repositories for large data ");
4682 iconLabel.setIcon(getIcon("datastores"));
4683 } else {
4684 textLabel.setText(text);
4685 iconLabel.setIcon(null);
4686 }
4687 }
4688 else if(value instanceof NameBearerHandle) {
4689 NameBearerHandle handle = (NameBearerHandle)value;
4690 textLabel.setText(handle.getTooltipText());
4691 iconLabel.setIcon(handle.getIcon());
4692 }
4693 else {
4694 textLabel.setText(null);
4695 iconLabel.setIcon(null);
4696 }
4697 }
4698 }
4699
4700 public Dimension getPreferredSize() {
4701 Dimension d = tipComponent.getPreferredSize();
4702 Insets ins = getInsets();
4703 return new Dimension(d.width + ins.left + ins.right, d.height + ins.top
4704 + ins.bottom);
4705 }
4706
4707 }
4708
4709 class HelpAboutAction extends AbstractAction {
4710 private static final long serialVersionUID = 1L;
4711 public HelpAboutAction() {
4712 super("About");
4713 putValue(SHORT_DESCRIPTION, "Show developers names and version");
4714 }
4715
4716 public void actionPerformed(ActionEvent e) {
4717 splash.showSplash();
4718 }
4719 }
4720
4721 class HelpMailingListAction extends AbstractAction {
4722 private static final long serialVersionUID = 1L;
4723 String keywords;
4724 public HelpMailingListAction() {
4725 super("Search in Mailing List");
4726 putValue(SHORT_DESCRIPTION,
4727 "Search keywords in GATE users mailing list");
4728 this.keywords = null;
4729 }
4730 public HelpMailingListAction(String keywords) {
4731 super("Search in Mailing List");
4732 this.keywords = keywords;
4733 }
4734 public void actionPerformed(ActionEvent e) {
4735 if (keywords == null) {
4736 keywords = JOptionPane.showInputDialog(instance,
4737 "Please enter your search keywords.",
4738 (String) this.getValue(NAME),
4739 JOptionPane.QUESTION_MESSAGE);
4740 if (keywords == null || keywords.trim().length() == 0) { return; }
4741 }
4742 try {
4743 showHelpFrame("http://sourceforge.net/search/index.php?" +
4744 "group_id=143829&form_submit=Search&type_of_search=mlists" +
4745 "&q=" + java.net.URLEncoder.encode(keywords, "UTF-8"),
4746 "mailing list");
4747
4748 } catch (UnsupportedEncodingException error) {
4749 String message = "The Character Encoding is not supported.";
4750 alertButton.setAction(new AlertAction(error, message, null));
4751 } finally {
4752 keywords = null;
4753 }
4754 }
4755 }
4756
4757 class HelpUserGuideAction extends AbstractAction {
4758 private static final long serialVersionUID = 1L;
4759 public HelpUserGuideAction() {
4760 super("User Guide Contents");
4761 putValue(SHORT_DESCRIPTION, "Contents of the online user guide");
4762 }
4763
4764 public void actionPerformed(ActionEvent e) {
4765 showHelpFrame("", "help contents");
4766 }
4767 }
4768
4769 public void showHelpFrame(String urlString, String resourceName) {
4770 final URL url;
4771 if (resourceName == null) { resourceName = "unknown"; }
4772 if (urlString != null
4773 && !urlString.startsWith("http://")
4774 && !urlString.startsWith("file://")) {
4775 urlString = "http://gate.ac.uk/userguide/" + urlString;
4776 }
4777 try {
4778 url = new URL(urlString);
4779 } catch (MalformedURLException e) {
4780 JOptionPane.showMessageDialog(MainFrame.this,
4781 (urlString == null) ?
4782 "There is no help page for this resource !\n\n" +
4783 "Find the developper of the resource:\n" +
4784 resourceName + "\n" + "and force him/her to put one."
4785 :
4786 "The URL of the page for " + resourceName + " is invalid.\n"
4787 + urlString,
4788 "GATE", JOptionPane.INFORMATION_MESSAGE);
4789 return;
4790 }
4791 Runnable runnable = new Runnable() {
4792 public void run() {
4793 StringBuilder actualURL = new StringBuilder(url.toString());
4794 if (url.toString().startsWith("http://gate.ac.uk/userguide/")) {
4795 // add gateVersion=... to the end of the URL
4796 int insertPoint = actualURL.length();
4797 if(url.getRef() != null) {
4798 // adjust for a #something on the end
4799 insertPoint -= url.getRef().length() + 1;
4800 }
4801 if(url.getQuery() == null) {
4802 actualURL.insert(insertPoint, '?');
4803 }
4804 else {
4805 actualURL.insert(insertPoint, "&");
4806 }
4807 actualURL.insert(insertPoint + 1, "gateVersion=" + gate.Main.version);
4808 }
4809
4810 Action[] actions = {
4811 new AbstractAction("Show configuration") {
4812 public void actionPerformed(ActionEvent e) {
4813 optionsDialog.showDialog();
4814 optionsDialog.dispose();
4815 }}};
4816
4817 String commandLine = Gate.getUserConfig().getString(
4818 MainFrame.class.getName()+".browsercommandline");
4819
4820 if(commandLine == null || commandLine.equals("")
4821 || commandLine.equals("Set dynamically when you display help.")) {
4822 // try to find the default browser
4823 Process process = null;
4824 try {
4825 // Windows
4826 commandLine = "rundll32 url.dll,FileProtocolHandler "
4827 + actualURL.toString();
4828 try { process = Runtime.getRuntime().exec(commandLine);
4829 } catch (IOException ioe2) {/* skip to next try catch */}
4830 if (process == null || process.waitFor() != 0) {
4831 // Linux
4832 commandLine = "xdg-open " + actualURL.toString();
4833 try { process = Runtime.getRuntime().exec(commandLine);
4834 } catch (IOException ioe3) {/* skip to next try catch */}
4835 if (process == null || process.waitFor() != 0) {
4836 // Linux KDE
4837 commandLine = "kfmclient exec " + actualURL.toString();
4838 try { process = Runtime.getRuntime().exec(commandLine);
4839 } catch (IOException ioe4) {/* skip to next try catch */}
4840 if (process == null || process.waitFor() != 0) {
4841 // Linux Gnome
4842 commandLine = "gnome-open " + actualURL.toString();
4843 try { process = Runtime.getRuntime().exec(commandLine);
4844 } catch (IOException ioe5) {/* skip to next try catch */}
4845 if (process == null || process.waitFor() != 0) {
4846 // Mac
4847 commandLine = "open " + actualURL.toString();
4848 try { process = Runtime.getRuntime().exec(commandLine);
4849 } catch (IOException ioe1) {/* skip to next try catch */}
4850 if (process == null || process.waitFor() != 0) {
4851 String message = "Unable to determine the default browser.\n"
4852 + "Will use a Java browser. To use a custom command line\n"
4853 + "go to the Options menu then Configuration.";
4854 alertButton.setAction(new AlertAction(null, message, actions));
4855 // Java help browser
4856 displayJavaHelpBrowser(actualURL.toString());
4857 }}}}}
4858 } catch(SecurityException se) {
4859 JOptionPane.showMessageDialog(instance,
4860 se.getMessage(), "Help Error", JOptionPane.ERROR_MESSAGE);
4861 log.error("Help browser Error", se);
4862 } catch (InterruptedException ie) {
4863 JOptionPane.showMessageDialog(instance,
4864 ie.getMessage(), "Help Error", JOptionPane.ERROR_MESSAGE);
4865 log.error("Help browser Error", ie);
4866 }
4867
4868 } else if(!commandLine.equals("Internal Java browser.")) {
4869 // external browser
4870 commandLine = commandLine.replaceFirst("%file", actualURL.toString());
4871 try {
4872 Runtime.getRuntime().exec(commandLine);
4873 }
4874 catch(Exception error) {
4875 String message = "Unable to call the custom browser command.\n" +
4876 "(" + commandLine + ")\n\n" +
4877 "Please go to the Options menu then Configuration.";
4878 alertButton.setAction(new AlertAction(error, message, actions));
4879 }
4880
4881 } else {
4882 displayJavaHelpBrowser(actualURL.toString());
4883 }
4884 }
4885 };
4886 Thread thread = new Thread(runnable, "showHelpFrame");
4887 thread.start();
4888 }
4889
4890 private void displayJavaHelpBrowser(String urlString) {
4891 if (helpFrame == null) {
4892 helpFrame = new HelpFrame();
4893 helpFrame.setSize(800, 600);
4894 helpFrame.setDefaultCloseOperation(HIDE_ON_CLOSE);
4895 // center on screen
4896 Dimension frameSize = helpFrame.getSize();
4897 Dimension ownerSize = Toolkit.getDefaultToolkit().getScreenSize();
4898 Point ownerLocation = new Point(0, 0);
4899 helpFrame.setLocation(ownerLocation.x
4900 + (ownerSize.width - frameSize.width) / 2, ownerLocation.y
4901 + (ownerSize.height - frameSize.height) / 2);
4902 }
4903 try {
4904 helpFrame.setPage(new URL(urlString));
4905 } catch (IOException error) {
4906 String message = "Error when loading help page.";
4907 alertButton.setAction(new AlertAction(error, message, null));
4908 return;
4909 }
4910 helpFrame.setVisible(false);
4911 helpFrame.setVisible(true);
4912 }
4913
4914 class HelpUserGuideInContextAction extends AbstractAction {
4915 private static final long serialVersionUID = 1L;
4916 public HelpUserGuideInContextAction() {
4917 super("Contextual User Guide");
4918 putValue(SHORT_DESCRIPTION, "Online help for the selected component");
4919 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("F1"));
4920 }
4921
4922 public void actionPerformed(ActionEvent e) {
4923 // get the handle for the selected tab pane resource view
4924 // then call HelpOnItemTreeAction with this handle
4925 JComponent largeView = (JComponent)
4926 mainTabbedPane.getSelectedComponent();
4927 if (largeView == null) { return; }
4928 Enumeration nodesEnum = resourcesTreeRoot.preorderEnumeration();
4929 boolean done = false;
4930 DefaultMutableTreeNode node = resourcesTreeRoot;
4931 while(!done && nodesEnum.hasMoreElements()) {
4932 node = (DefaultMutableTreeNode) nodesEnum.nextElement();
4933 done = node.getUserObject() instanceof Handle
4934 && ((Handle)node.getUserObject()).viewsBuilt()
4935 && ((Handle)node.getUserObject()).getLargeView() == largeView;
4936 }
4937 if(done && (Handle)node.getUserObject() instanceof NameBearerHandle) {
4938 new HelpOnItemTreeAction((NameBearerHandle)node.getUserObject())
4939 .actionPerformed(null);
4940 } else if (mainTabbedPane.getTitleAt(mainTabbedPane
4941 .getSelectedIndex()).equals("Messages")) {
4942 showHelpFrame("sec:developer:gui", "messages pane");
4943 } else {
4944 showHelpFrame(null, node.getUserObject().getClass().getName());
4945 }
4946 }
4947 }
4948
4949 class HelpOnItemTreeAction extends AbstractAction {
4950 private static final long serialVersionUID = 1L;
4951 HelpOnItemTreeAction(NameBearerHandle resource) {
4952 super("Help");
4953 putValue(SHORT_DESCRIPTION, "Help on this resource");
4954 this.resource = resource;
4955 }
4956
4957 public void actionPerformed(ActionEvent e) {
4958 String helpURL = null;
4959 String resourceClassName = resource.getTarget().getClass().getName();
4960
4961 if (resource.getTarget() instanceof Resource) {
4962 // search the help URL associated to the resource
4963 ResourceData rd = Gate.getCreoleRegister().get(resourceClassName);
4964 helpURL = rd.getHelpURL();
4965 }
4966
4967 if(helpURL == null) {
4968 // otherwise search in the associated VRs of the resource
4969 List<String> vrList = Gate.getCreoleRegister()
4970 .getLargeVRsForResource(resourceClassName);
4971 for(String vrClass : vrList) {
4972 ResourceData vrd = Gate.getCreoleRegister().get(vrClass);
4973 if(vrd != null && vrd.getHelpURL() != null) {
4974 helpURL = vrd.getHelpURL();
4975 break;
4976 }
4977 }
4978 }
4979 showHelpFrame(helpURL, resourceClassName);
4980 }
4981
4982 NameBearerHandle resource;
4983 }
4984
4985 class ToggleToolTipsAction extends AbstractAction {
4986 public ToggleToolTipsAction() {
4987 super("Show Tooltips");
4988 putValue(SHORT_DESCRIPTION,
4989 "Tooltips appear in help balloon like this one");
4990 }
4991 public void actionPerformed(ActionEvent e) {
4992 Runnable runnable = new Runnable() {
4993 public void run() {
4994 javax.swing.ToolTipManager toolTipManager =
4995 ToolTipManager.sharedInstance();
4996 if (toolTipManager.isEnabled()) {
4997 toolTipManager.setEnabled(false);
4998 Gate.getUserConfig().put(
4999 MainFrame.class.getName()+".hidetooltips", false);
5000 } else {
5001 toolTipManager.setEnabled(true);
5002 Gate.getUserConfig().put(
5003 MainFrame.class.getName()+".hidetooltips", true);
5004 }
5005 }
5006 };
5007 Thread thread = new Thread(runnable, "ToggleToolTipsAction");
5008 thread.start();
5009 }
5010 }
5011
5012
5013 protected class ResourcesTreeCellRenderer extends DefaultTreeCellRenderer {
5014 private static final long serialVersionUID = 1L;
5015 public ResourcesTreeCellRenderer() {
5016 setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
5017 }
5018
5019 public Component getTreeCellRendererComponent(JTree tree, Object value,
5020 boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
5021 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row,
5022 hasFocus);
5023 if(value == resourcesTreeRoot) {
5024 setIcon(MainFrame.getIcon("root"));
5025 setToolTipText("Resources tree root ");
5026 }
5027 else if(value == applicationsRoot) {
5028 setIcon(MainFrame.getIcon("applications"));
5029 setToolTipText("Run processes on data ");
5030 }
5031 else if(value == languageResourcesRoot) {
5032 setIcon(MainFrame.getIcon("lrs"));
5033 setToolTipText("Data used for annotating ");
5034 }
5035 else if(value == processingResourcesRoot) {
5036 setIcon(MainFrame.getIcon("prs"));
5037 setToolTipText("Processes that annotate data ");
5038 }
5039 else if(value == datastoresRoot) {
5040 setIcon(MainFrame.getIcon("datastores"));
5041 setToolTipText("Repositories for large data ");
5042 }
5043 else {
5044 // not one of the default root nodes
5045 value = ((DefaultMutableTreeNode)value).getUserObject();
5046 if(value instanceof Handle) {
5047 setIcon(((Handle)value).getIcon());
5048 setText(((Handle)value).getTitle());
5049 setToolTipText(((Handle)value).getTooltipText());
5050 }
5051 }
5052 return this;
5053 }
5054
5055 }
5056
5057 protected class ResourcesTreeCellEditor extends DefaultTreeCellEditor {
5058 ResourcesTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
5059 super(tree, renderer);
5060 }
5061
5062 /**
5063 * This is the original implementation from the super class with
5064 * some changes (i.e. shorter timer: 500 ms instead of 1200)
5065 */
5066 protected void startEditingTimer() {
5067 if(timer == null) {
5068 timer = new javax.swing.Timer(500, this);
5069 timer.setRepeats(false);
5070 }
5071 timer.start();
5072 }
5073
5074 /**
5075 * This is the original implementation from the super class with
5076 * some changes (i.e. correct discovery of icon)
5077 */
5078 public Component getTreeCellEditorComponent(JTree tree, Object value,
5079 boolean isSelected, boolean expanded, boolean leaf, int row) {
5080 Component retValue =
5081 super.getTreeCellEditorComponent(tree, value, isSelected, expanded,
5082 leaf, row);
5083 // lets find the actual icon
5084 if(renderer != null) {
5085 renderer.getTreeCellRendererComponent(tree, value, isSelected,
5086 expanded, leaf, row, false);
5087 editingIcon = renderer.getIcon();
5088 }
5089 return retValue;
5090 }
5091 }// protected class ResourcesTreeCellEditor extends
5092 // DefaultTreeCellEditor {
5093
5094 protected class ResourcesTreeModel extends DefaultTreeModel {
5095 private static final long serialVersionUID = 1L;
5096 ResourcesTreeModel(TreeNode root, boolean asksAllowChildren) {
5097 super(root, asksAllowChildren);
5098 }
5099
5100 public void valueForPathChanged(TreePath path, Object newValue) {
5101 DefaultMutableTreeNode aNode =
5102 (DefaultMutableTreeNode)path.getLastPathComponent();
5103 Object userObject = aNode.getUserObject();
5104 if(userObject instanceof Handle) {
5105 Handle handle = (Handle)userObject;
5106 Object target = handle.getTarget();
5107 if(target instanceof Resource) {
5108 Gate.getCreoleRegister().setResourceName((Resource)target,
5109 (String)newValue);
5110 } else if(target instanceof NameBearer){
5111 //not a resource, we need to do it manually
5112 ((NameBearer)target).setName((String)newValue);
5113 //next see if there is a tab for this resource and rename it
5114 for(int i = 0; i < mainTabbedPane.getTabCount(); i++) {
5115 if(mainTabbedPane.getComponentAt(i) == handle.getLargeView()) {
5116 mainTabbedPane.setTitleAt(i, (String)newValue);
5117 break;
5118 }
5119 }
5120 }
5121 }
5122 nodeChanged(aNode);
5123
5124 }
5125 }
5126
5127 class ProgressBarUpdater implements Runnable {
5128 ProgressBarUpdater(int newValue) {
5129 value = newValue;
5130 }
5131
5132 public void run() {
5133 if(value == 0)
5134 progressBar.setVisible(false);
5135 else progressBar.setVisible(true);
5136 progressBar.setValue(value);
5137 }
5138
5139 int value;
5140 }
5141
5142 class StatusBarUpdater implements Runnable {
5143 StatusBarUpdater(String text) {
5144 this.text = text;
5145 }
5146
5147 public void run() {
5148 statusBar.setText(text);
5149 }
5150
5151 String text;
5152 }
5153
5154 /**
5155 * During longer operations it is nice to keep the user entertained so
5156 * (s)he doesn't fall asleep looking at a progress bar that seems have
5157 * stopped. Also there are some operations that do not support
5158 * progress reporting so the progress bar would not work at all so we
5159 * need a way to let the user know that things are happening. We chose
5160 * for purpose to show the user a small cartoon in the form of an
5161 * animated gif. This class handles the displaying and updating of
5162 * those cartoons.
5163 */
5164 class CartoonMinder implements Runnable {
5165
5166 CartoonMinder(JPanel targetPanel) {
5167 active = false;
5168 dying = false;
5169 this.targetPanel = targetPanel;
5170 imageLabel = new JLabel(getIcon("working"));
5171 imageLabel.setOpaque(false);
5172 imageLabel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
5173 }
5174
5175 public boolean isActive() {
5176 boolean res;
5177 synchronized(lock) {
5178 res = active;
5179 }
5180 return res;
5181 }
5182
5183 public void activate() {
5184 // add the label in the panel
5185 SwingUtilities.invokeLater(new Runnable() {
5186 public void run() {
5187 targetPanel.add(imageLabel);
5188 }
5189 });
5190 // wake the dormant thread
5191 synchronized(lock) {
5192 active = true;
5193 }
5194 }
5195
5196 public void deactivate() {
5197 // send the thread to sleep
5198 synchronized(lock) {
5199 active = false;
5200 }
5201 // clear the panel
5202 SwingUtilities.invokeLater(new Runnable() {
5203 public void run() {
5204 targetPanel.removeAll();
5205 targetPanel.repaint();
5206 }
5207 });
5208 }
5209
5210 public void dispose() {
5211 synchronized(lock) {
5212 dying = true;
5213 }
5214 }
5215
5216 public void run() {
5217 boolean isDying;
5218 synchronized(lock) {
5219 isDying = dying;
5220 }
5221 while(!isDying) {
5222 boolean isActive;
5223 synchronized(lock) {
5224 isActive = active;
5225 }
5226 if(isActive && targetPanel.isVisible()) {
5227 SwingUtilities.invokeLater(new Runnable() {
5228 public void run() {
5229 // targetPanel.getParent().validate();
5230 // targetPanel.getParent().repaint();
5231 // ((JComponent)targetPanel.getParent()).paintImmediately(((JComponent)targetPanel.getParent()).getBounds());
5232 // targetPanel.doLayout();
5233
5234 // targetPanel.requestFocus();
5235 targetPanel.getParent().getParent().invalidate();
5236 targetPanel.getParent().getParent().repaint();
5237 // targetPanel.paintImmediately(targetPanel.getBounds());
5238 }
5239 });
5240 }
5241 // sleep
5242 try {
5243 Thread.sleep(300);
5244 }
5245 catch(InterruptedException ie) {
5246 log.debug("Animation interrupted", ie);
5247 }
5248
5249 synchronized(lock) {
5250 isDying = dying;
5251 }
5252 }// while(!isDying)
5253 }
5254
5255 boolean dying;
5256
5257 boolean active;
5258
5259 final String lock = "lock";
5260
5261 JPanel targetPanel;
5262
5263 JLabel imageLabel;
5264 }
5265
5266 class LocaleSelectorMenuItem extends JRadioButtonMenuItem {
5267 private static final long serialVersionUID = 1L;
5268 public LocaleSelectorMenuItem(Locale locale) {
5269 super(locale.getDisplayName());
5270 me = this;
5271 myLocale = locale;
5272 this.addActionListener(new ActionListener() {
5273 public void actionPerformed(ActionEvent e) {
5274 for(Component aRoot : MainFrame.getGuiRoots()) {
5275 if(aRoot instanceof Window) {
5276 me.setSelected(aRoot.getInputContext()
5277 .selectInputMethod(myLocale));
5278 }
5279 }
5280 }
5281 });
5282 }
5283
5284 public LocaleSelectorMenuItem() {
5285 super("System Default >>" + Locale.getDefault().getDisplayName() + "<<");
5286 me = this;
5287 myLocale = Locale.getDefault();
5288 this.addActionListener(new ActionListener() {
5289 public void actionPerformed(ActionEvent e) {
5290 for(Component aRoot : MainFrame.getGuiRoots()) {
5291 if(aRoot instanceof Window) {
5292 me.setSelected(aRoot.getInputContext()
5293 .selectInputMethod(myLocale));
5294 }
5295 }
5296 }
5297 });
5298 }
5299
5300 Locale myLocale;
5301
5302 JRadioButtonMenuItem me;
5303 }// //class LocaleSelectorMenuItem extends JRadioButtonMenuItem
5304
5305 /**
5306 * This class represent an action which brings up the Gazetteer Editor
5307 * tool
5308 */
5309 class NewGazetteerEditorAction extends AbstractAction {
5310 private static final long serialVersionUID = 1L;
5311 public NewGazetteerEditorAction() {
5312 super("Gazetteer Editor", getIcon("gazetteer"));
5313 putValue(SHORT_DESCRIPTION, "Start the Gazetteer Editor");
5314 }
5315
5316 public void actionPerformed(ActionEvent e) {
5317 com.ontotext.gate.vr.Gaze editor = new com.ontotext.gate.vr.Gaze();
5318 try {
5319 JFrame frame = new JFrame();
5320 editor.init();
5321 frame.setTitle("Gazetteer Editor");
5322 frame.getContentPane().add(editor);
5323
5324 Set<LanguageResource> gazetteers = new HashSet<LanguageResource>(
5325 Gate.getCreoleRegister().getLrInstances(
5326 "gate.creole.gazetteer.DefaultGazetteer"));
5327 if(gazetteers.isEmpty()) { return; }
5328 for(LanguageResource gazetteer : gazetteers) {
5329 Gazetteer gaz = (Gazetteer) gazetteer;
5330 if(gaz.getListsURL().toString().endsWith(
5331 System.getProperty("gate.slug.gazetteer"))) editor.setTarget(gaz);
5332 }
5333
5334 frame.setSize(Gaze.SIZE_X, Gaze.SIZE_Y);
5335 frame.setLocation(Gaze.POSITION_X, Gaze.POSITION_Y);
5336 frame.setVisible(true);
5337 editor.setVisible(true);
5338 }
5339 catch(ResourceInstantiationException error) {
5340 String message = "Failed to instanciate the gazetteer editor.";
5341 Action[] actions = {
5342 new AbstractAction("Load plugins manager") {
5343 public void actionPerformed(ActionEvent e) {
5344 (new ManagePluginsAction()).actionPerformed(null);
5345 }}};
5346 alertButton.setAction(new AlertAction(error, message, actions));
5347 }
5348 }// actionPerformed();
5349 }// class NewOntologyEditorAction
5350
5351 class AlertAction extends AbstractAction {
5352 private Timer timer =
5353 new java.util.Timer("MainFrame alert tooltip hide timer", true);
5354
5355 /**
5356 * Action for the alert button that shows a message in a popup.
5357 * A detailed dialog can be shown when the button or popup are clicked.
5358 * Log the message and error as soon as the action is created.
5359 * @param error can be null in case of info message.
5360 * @param message text to be displayed in a popup and dialogue
5361 * @param actions actions the user can choose in the dialogue
5362 */
5363 public AlertAction(Throwable error, String message, Action[] actions) {
5364 if (error == null) {
5365 log.info(message);
5366 } else {
5367 log.error(message, error);
5368 }
5369 String description = "<html>" + (error == null ?
5370 "Important information:<br>" : "There was a problem:<br>") +
5371 message.substring(0, Math.min(300, message.length()))
5372 .replaceAll("(.{40,50}(?:\\b|\\.|/))", "$1<br>") + "</html>";
5373 final int lines = description.split("<br>").length;
5374 putValue(Action.SMALL_ICON, MainFrame.getIcon("crystal-clear-app-error"));
5375 putValue(Action.SHORT_DESCRIPTION, description);
5376
5377 this.error = error;
5378 this.message = message;
5379 if (actions == null) {
5380 this.actions = new Action[1];
5381 } else {
5382 this.actions = new Action[actions.length+1];
5383 System.arraycopy(actions, 0, this.actions, 0, actions.length);
5384 }
5385 // add a 'search in mailing list' action
5386 this.actions[this.actions.length-1] = new HelpMailingListAction(message);
5387 // show for a few seconds a popup with the error message
5388 SwingUtilities.invokeLater(new Runnable() {
5389 public void run() {
5390 if (!instance.isShowing()) { return; }
5391 alertButton.setEnabled(true);
5392 JToolTip toolTip = alertButton.createToolTip();
5393 toolTip.setTipText(alertButton.getToolTipText());
5394 PopupFactory popupFactory = PopupFactory.getSharedInstance();
5395 final Popup popup = popupFactory.getPopup(alertButton, toolTip,
5396 instance.getLocationOnScreen().x+instance.getWidth()/2-100,
5397 instance.getLocationOnScreen().y+instance.getHeight()-30-(lines*10));
5398 toolTip.addMouseListener(new MouseAdapter() {
5399 public void mouseClicked(MouseEvent e) {
5400 popup.hide();
5401 alertButton.doClick();
5402 }
5403 });
5404 popup.show();
5405 Date timeToRun = new Date(System.currentTimeMillis() + 4000);
5406 timer.schedule(new TimerTask() {
5407 public void run() {
5408 SwingUtilities.invokeLater(new Runnable(){
5409 public void run() {
5410 popup.hide(); // hide the tooltip after some time
5411 }
5412 });
5413 }
5414 }, timeToRun);
5415 }
5416 });
5417 }
5418 public void actionPerformed(ActionEvent e) {
5419 ErrorDialog.show(error, message, instance, getIcon("root"), actions);
5420 }
5421 Throwable error;
5422 String message;
5423 Action[] actions;
5424 }
5425
5426 } // class MainFrame
|