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 02/10/2001
0011 *
0012 * $Id: SerialControllerEditor.java 13389 2011-02-01 19:19:59Z markagreenwood $
0013 *
0014 */
0015
0016 package gate.gui;
0017
0018 import java.awt.BorderLayout;
0019 import java.awt.Color;
0020 import java.awt.Component;
0021 import java.awt.Dimension;
0022 import java.awt.GridBagConstraints;
0023 import java.awt.GridBagLayout;
0024 import java.awt.Insets;
0025 import java.awt.datatransfer.Transferable;
0026 import java.awt.datatransfer.StringSelection;
0027 import java.awt.datatransfer.DataFlavor;
0028 import java.awt.datatransfer.UnsupportedFlavorException;
0029 import java.awt.event.*;
0030 import java.text.NumberFormat;
0031 import java.util.*;
0032 import java.io.IOException;
0033
0034 import javax.swing.*;
0035 import javax.swing.border.TitledBorder;
0036 import javax.swing.event.*;
0037 import javax.swing.table.AbstractTableModel;
0038 import javax.swing.table.DefaultTableCellRenderer;
0039 import javax.swing.table.TableCellRenderer;
0040
0041 import gate.*;
0042 import gate.creole.*;
0043 import gate.creole.RunningStrategy.UnconditionalRunningStrategy;
0044 import gate.creole.metadata.CreoleResource;
0045 import gate.creole.metadata.GuiType;
0046 import gate.event.*;
0047 import gate.swing.*;
0048 import gate.util.*;
0049
0050 @CreoleResource(name = "Serial Application Editor", guiType = GuiType.LARGE,
0051 resourceDisplayed = "gate.creole.SerialController", mainViewer = true)
0052 public class SerialControllerEditor extends AbstractVisualResource
0053 implements CreoleListener, ControllerListener,
0054 ActionsPublisher{
0055
0056 public SerialControllerEditor() {
0057
0058 }
0059
0060 public void setTarget(Object target){
0061 if(!(target instanceof SerialController))
0062 throw new IllegalArgumentException(
0063 "gate.gui.ApplicationViewer can only be used for serial controllers\n" +
0064 target.getClass().toString() +
0065 " is not a gate.creole.SerialController!");
0066 if(controller != null) controller.removeControllerListener(this);
0067 this.controller = (SerialController)target;
0068 controller.addControllerListener(this);
0069 corpusControllerMode = controller instanceof CorpusController;
0070 analyserMode = controller instanceof SerialAnalyserController ||
0071 controller instanceof ConditionalSerialAnalyserController;
0072 conditionalMode = controller instanceof ConditionalController;
0073
0074 initLocalData();
0075 initGuiComponents();
0076 initListeners();
0077
0078 loadedPRsTableModel.fireTableDataChanged();
0079 memberPRsTableModel.fireTableDataChanged();
0080
0081 }//setController
0082
0083
0084 public void setHandle(Handle handle) {
0085 this.handle = handle;
0086
0087 //register the listeners
0088 if(handle instanceof StatusListener)
0089 addStatusListener((StatusListener)handle);
0090 if(handle instanceof ProgressListener)
0091 addProgressListener((ProgressListener)handle);
0092 }
0093
0094 public Resource init() throws ResourceInstantiationException{
0095 super.init();
0096 return this;
0097 }
0098
0099 protected void initLocalData() {
0100 actionList = new ArrayList<Action>();
0101 runAction = new RunAction();
0102 //add the items to the popup
0103 actionList.add(null);
0104 actionList.add(runAction);
0105 addPRAction = new AddPRAction();
0106 removePRAction = new RemovePRAction();
0107 }
0108
0109 protected void initGuiComponents() {
0110 //we use a JSplitPane for most of the content, and add the Run button to
0111 //the South area
0112 setLayout(new BorderLayout());
0113
0114 JPanel topSplit = new JPanel();
0115 topSplit.setLayout(new GridBagLayout());
0116 GridBagConstraints constraints = new GridBagConstraints();
0117 constraints.fill = GridBagConstraints.BOTH;
0118 constraints.gridy = 0;
0119
0120
0121 loadedPRsTableModel = new LoadedPRsTableModel();
0122 loadedPRsTable = new XJTable();
0123 loadedPRsTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
0124 loadedPRsTable.setSortable(false);
0125 loadedPRsTable.setModel(loadedPRsTableModel);
0126 loadedPRsTable.setDragEnabled(true);
0127 loadedPRsTable.setDefaultRenderer(ProcessingResource.class,
0128 new ResourceRenderer());
0129 //create a renderer that doesn't mind being extended horizontally.
0130 loadedPRsTable.setDefaultRenderer(String.class,
0131 new DefaultTableCellRenderer(){
0132 @Override
0133 public Dimension getMaximumSize() {
0134 //we don't mind being extended horizontally
0135 Dimension dim = super.getMaximumSize();
0136 if(dim != null){
0137 dim.width = Integer.MAX_VALUE;
0138 setMaximumSize(dim);
0139 }
0140 return dim;
0141 }
0142 @Override
0143 public Dimension getMinimumSize() {
0144 //we don't like being squashed!
0145 return getPreferredSize();
0146 }
0147 });
0148
0149 final int width1 = new JLabel("Loaded Processing resources").
0150 getPreferredSize().width + 30;
0151 JScrollPane scroller = new JScrollPane(){
0152 public Dimension getPreferredSize(){
0153 Dimension dim = super.getPreferredSize();
0154 dim.width = Math.max(dim.width, width1);
0155 return dim;
0156 }
0157 public Dimension getMinimumSize(){
0158 Dimension dim = super.getMinimumSize();
0159 dim.width = Math.max(dim.width, width1);
0160 return dim;
0161 }
0162 };
0163 scroller.getViewport().setView(loadedPRsTable);
0164 scroller.setBorder(BorderFactory.
0165 createTitledBorder(BorderFactory.createEtchedBorder(),
0166 " Loaded Processing resources "));
0167
0168 //adding a scrollable table
0169 constraints.weightx = 1;
0170 constraints.weighty = 1;
0171 constraints.insets = new Insets(0,0,0,5);
0172 topSplit.add(scroller, constraints);
0173
0174
0175 addButton = new JButton(addPRAction);
0176 addButton.setText("");
0177 addButton.setEnabled(false);
0178 removeButton = new JButton(removePRAction);
0179 removeButton.setText("");
0180 removeButton.setEnabled(false);
0181
0182 Box buttonsBox =Box.createVerticalBox();
0183 buttonsBox.add(Box.createVerticalGlue());
0184 buttonsBox.add(addButton);
0185 buttonsBox.add(Box.createVerticalStrut(5));
0186 buttonsBox.add(removeButton);
0187 buttonsBox.add(Box.createVerticalGlue());
0188
0189 constraints.weightx = 0;
0190 constraints.weighty = 0;
0191 constraints.insets = new Insets(0,0,0,5);
0192 topSplit.add(buttonsBox, constraints);
0193
0194 memberPRsTableModel = new MemberPRsTableModel();
0195 memberPRsTable = new XJTable();
0196 memberPRsTable.setSortable(false);
0197 memberPRsTable.setModel(memberPRsTableModel);
0198 memberPRsTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
0199 memberPRsTable.setDefaultRenderer(ProcessingResource.class,
0200 new ResourceRenderer());
0201 memberPRsTable.setDefaultRenderer(String.class,
0202 new DefaultTableCellRenderer(){
0203 @Override
0204 public Dimension getMaximumSize() {
0205 //we don't mind being extended horizontally
0206 Dimension dim = super.getMaximumSize();
0207 if(dim != null){
0208 dim.width = Integer.MAX_VALUE;
0209 setMaximumSize(dim);
0210 }
0211 return dim;
0212 }
0213 @Override
0214 public Dimension getMinimumSize() {
0215 //we don't like being squashed!
0216 return getPreferredSize();
0217 }
0218 });
0219 memberPRsTable.setDefaultRenderer(Icon.class, new IconRenderer());
0220 memberPRsTable.setDragEnabled(true);
0221
0222 final int width2 = new JLabel("Selected Processing resources").
0223 getPreferredSize().width + 30;
0224 scroller = new JScrollPane(){
0225 public Dimension getPreferredSize(){
0226 Dimension dim = super.getPreferredSize();
0227 dim.width = Math.max(dim.width, width2);
0228 return dim;
0229 }
0230 public Dimension getMinimumSize(){
0231 Dimension dim = super.getMinimumSize();
0232 dim.width = Math.max(dim.width, width2);
0233 return dim;
0234 }
0235 };
0236 scroller.getViewport().setView(memberPRsTable);
0237 scroller.setBorder(BorderFactory.
0238 createTitledBorder(BorderFactory.createEtchedBorder(),
0239 " Selected Processing resources "));
0240
0241 //adding a scrollable table
0242 constraints.weightx = 1;
0243 constraints.weighty = 1;
0244 constraints.insets = new Insets(0,0,0,5);
0245 topSplit.add(scroller, constraints);
0246
0247
0248 moveUpButton = new JButton(MainFrame.getIcon("up"));
0249 moveUpButton.setMnemonic(KeyEvent.VK_UP);
0250 moveUpButton.setToolTipText("Move the selected resources up.");
0251 moveUpButton.setEnabled(false);
0252 moveDownButton = new JButton(MainFrame.getIcon("down"));
0253 moveDownButton.setMnemonic(KeyEvent.VK_DOWN);
0254 moveDownButton.setToolTipText("Move the selected resources down.");
0255 moveDownButton.setEnabled(false);
0256
0257 buttonsBox =Box.createVerticalBox();
0258 buttonsBox.add(Box.createVerticalGlue());
0259 buttonsBox.add(moveUpButton);
0260 buttonsBox.add(Box.createVerticalStrut(5));
0261 buttonsBox.add(moveDownButton);
0262 buttonsBox.add(Box.createVerticalGlue());
0263
0264 //adding a scrollable table
0265 constraints.weightx = 0;
0266 constraints.weighty = 0;
0267 constraints.insets = new Insets(0,0,0,0);
0268 topSplit.add(buttonsBox, constraints);
0269
0270 // =========== BOTTOM Half ===========
0271 JPanel bottomSplit = new JPanel();
0272 bottomSplit.setLayout(new GridBagLayout());
0273
0274 //first row
0275 constraints.gridy = 0;
0276
0277 if(conditionalMode){
0278 strategyPanel = new JPanel();
0279 strategyPanel.setLayout(new BoxLayout(strategyPanel, BoxLayout.X_AXIS));
0280 strategyPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
0281 runBtnGrp = new ButtonGroup();
0282 yes_RunRBtn = new JRadioButton("Yes", true);
0283 yes_RunRBtn.setHorizontalTextPosition(AbstractButton.LEFT);
0284 runBtnGrp.add(yes_RunRBtn);
0285 no_RunRBtn = new JRadioButton("No", false);
0286 no_RunRBtn.setHorizontalTextPosition(AbstractButton.LEFT);
0287 runBtnGrp.add(no_RunRBtn);
0288 conditional_RunRBtn = new JRadioButton("If value of feature", false);
0289 conditional_RunRBtn.setHorizontalTextPosition(AbstractButton.LEFT);
0290 runBtnGrp.add(conditional_RunRBtn);
0291
0292 featureNameTextField = new JTextField("", 25);
0293 featureNameTextField.setMaximumSize(
0294 new Dimension(Integer.MAX_VALUE,
0295 featureNameTextField.getPreferredSize().
0296 height));
0297
0298 featureValueTextField = new JTextField("", 25);
0299 featureValueTextField.setMaximumSize(
0300 new Dimension(Integer.MAX_VALUE,
0301 featureValueTextField.getPreferredSize().
0302 height));
0303
0304 strategyPanel.add(new JLabel(MainFrame.getIcon("greenBall")));
0305 strategyPanel.add(yes_RunRBtn);
0306 strategyPanel.add(Box.createHorizontalStrut(5));
0307
0308 strategyPanel.add(new JLabel(MainFrame.getIcon("redBall")));
0309 strategyPanel.add(no_RunRBtn);
0310 strategyPanel.add(Box.createHorizontalStrut(5));
0311
0312 strategyPanel.add(new JLabel(MainFrame.getIcon("yellowBall")));
0313 strategyPanel.add(conditional_RunRBtn);
0314 strategyPanel.add(Box.createHorizontalStrut(5));
0315
0316 strategyPanel.add(featureNameTextField);
0317 strategyPanel.add(Box.createHorizontalStrut(5));
0318 strategyPanel.add(new JLabel("is"));
0319 strategyPanel.add(Box.createHorizontalStrut(5));
0320 strategyPanel.add(featureValueTextField);
0321 strategyPanel.add(Box.createHorizontalStrut(5));
0322 strategyBorder = BorderFactory.createTitledBorder(
0323 BorderFactory.createEtchedBorder(),
0324 " No processing resource selected... ");
0325 strategyPanel.setBorder(strategyBorder);
0326
0327
0328 constraints.weightx = 1;
0329 constraints.weighty = 0;
0330 constraints.insets = new Insets(0,0,0,0);
0331 bottomSplit.add(strategyPanel, constraints);
0332 constraints.gridy++;
0333 }//if conditional mode
0334
0335 if(corpusControllerMode){
0336 //we need to add the corpus combo
0337 corpusCombo = new JComboBox(corpusComboModel = new CorporaComboModel());
0338 corpusCombo.setRenderer(new ResourceRenderer());
0339 corpusCombo.setMaximumSize(new Dimension(Integer.MAX_VALUE,
0340 corpusCombo.getPreferredSize().
0341 height));
0342 Corpus corpus = null;
0343 if(controller instanceof CorpusController){
0344 corpus = ((CorpusController)controller).getCorpus();
0345 }else{
0346 throw new GateRuntimeException("Controller editor in corpus " +
0347 "controller mode " +
0348 "but the target controller is not an " +
0349 "CorpusController!");
0350 }
0351
0352 if(corpus != null){
0353 corpusCombo.setSelectedItem(corpus);
0354 }else{
0355 if(corpusCombo.getModel().getSize() > 1) corpusCombo.setSelectedIndex(1);
0356 else corpusCombo.setSelectedIndex(0);
0357 }
0358 JPanel horBox = new JPanel();
0359 horBox.setLayout(new BoxLayout(horBox, BoxLayout.X_AXIS));
0360 horBox.setAlignmentX(Component.LEFT_ALIGNMENT);
0361 horBox.add(new JLabel("Corpus:"));
0362 horBox.add(Box.createHorizontalStrut(5));
0363 horBox.add(corpusCombo);
0364 horBox.add(Box.createHorizontalStrut(5));
0365
0366 constraints.weightx = 1;
0367 constraints.anchor = GridBagConstraints.WEST;
0368 constraints.fill = GridBagConstraints.BOTH;
0369 constraints.weighty = 0;
0370 constraints.insets = new Insets(0,0,0,0);
0371 bottomSplit.add(horBox, constraints);
0372
0373 //all the following rows have one element only
0374 constraints.gridwidth = 1;
0375 constraints.gridy++;
0376 }//if(corpusControllerMode)
0377
0378 parametersPanel = new JPanel();
0379 parametersPanel.setLayout(new BoxLayout(parametersPanel, BoxLayout.Y_AXIS));
0380 parametersPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
0381 parametersBorder = BorderFactory.createTitledBorder(
0382 BorderFactory.createEtchedBorder(),
0383 " No selected processing resource ");
0384 parametersPanel.setBorder(parametersBorder);
0385 parametersEditor = new ResourceParametersEditor();
0386 parametersEditor.init(null, null);
0387 parametersPanel.add(new JScrollPane(parametersEditor));
0388 // parametersPanel.add(parametersEditor, constraints);
0389
0390 constraints.weighty = 1;
0391 constraints.weightx = 1;
0392 constraints.anchor = GridBagConstraints.CENTER;
0393 constraints.fill = GridBagConstraints.BOTH;
0394 constraints.insets = new Insets(0,0,0,0);
0395 bottomSplit.add(parametersPanel, constraints);
0396 constraints.gridy++;
0397
0398 constraints.weightx = 0;
0399 constraints.weighty = 0;
0400 constraints.fill = GridBagConstraints.NONE;
0401 constraints.anchor = GridBagConstraints.CENTER;
0402 bottomSplit.add(new JButton(runAction), constraints);
0403
0404 final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
0405 topSplit, bottomSplit);
0406 splitPane.addAncestorListener(new AncestorListener() {
0407 public void ancestorRemoved(AncestorEvent event) {}
0408 public void ancestorMoved(AncestorEvent event) {}
0409 /**
0410 * One-shot ancestor listener that places the divider location on first
0411 * show, and then de-registers self.
0412 */
0413 public void ancestorAdded(AncestorEvent event) {
0414 // This seems to work more reliably if queued rather than executed
0415 // directly.
0416 SwingUtilities.invokeLater(new Runnable(){
0417 public void run(){
0418 splitPane.setDividerLocation(0.5);
0419 }
0420 });
0421 splitPane.removeAncestorListener(this);
0422 }
0423 });
0424
0425 add(splitPane, BorderLayout.CENTER);
0426 }// initGuiComponents()
0427
0428 protected void initListeners() {
0429 Gate.getCreoleRegister().addCreoleListener(this);
0430
0431 this.addMouseListener(new MouseAdapter() {
0432 public void mousePressed(MouseEvent e) {
0433 processMouseEvent(e);
0434 }
0435 public void mouseReleased(MouseEvent e) {
0436 processMouseEvent(e);
0437 }
0438 protected void processMouseEvent(MouseEvent e) {
0439 if(e.isPopupTrigger()) {
0440 // context menu
0441 if(handle != null
0442 && handle.getPopup() != null) {
0443 handle.getPopup().show(SerialControllerEditor.this,
0444 e.getX(), e.getY());
0445 }
0446 }
0447 }
0448 });
0449
0450 moveUpButton.addActionListener(new ActionListener() {
0451 public void actionPerformed(ActionEvent e) {
0452 int rows[] = memberPRsTable.getSelectedRows();
0453 if(rows == null || rows.length == 0){
0454 JOptionPane.showMessageDialog(
0455 SerialControllerEditor.this,
0456 "Please select some components to be moved "+
0457 "from the list of used components!\n" ,
0458 "GATE", JOptionPane.ERROR_MESSAGE);
0459 } else {
0460 //we need to make sure the rows are sorted
0461 Arrays.sort(rows);
0462 //get the list of PRs
0463 for(int row : rows) {
0464 if(row > 0) {
0465 //move it up
0466 ProcessingResource value = controller.remove(row);
0467 controller.add(row - 1, value);
0468 }
0469 }
0470 // memberPRsTableModel.fireTableDataChanged();
0471 //restore selection
0472 for(int row : rows) {
0473 int newRow;
0474 if(row > 0) newRow = row - 1;
0475 else newRow = row;
0476 memberPRsTable.addRowSelectionInterval(newRow, newRow);
0477 }
0478 memberPRsTable.requestFocusInWindow();
0479 }
0480
0481 }
0482 });
0483
0484 moveDownButton.addActionListener(new ActionListener() {
0485 public void actionPerformed(ActionEvent e) {
0486 int rows[] = memberPRsTable.getSelectedRows();
0487 if(rows == null || rows.length == 0){
0488 JOptionPane.showMessageDialog(
0489 SerialControllerEditor.this,
0490 "Please select some components to be moved "+
0491 "from the list of used components!\n" ,
0492 "GATE", JOptionPane.ERROR_MESSAGE);
0493 } else {
0494 //we need to make sure the rows are sorted
0495 Arrays.sort(rows);
0496 //get the list of PRs
0497 for(int i = rows.length - 1; i >= 0; i--){
0498 int row = rows[i];
0499 if(row < controller.getPRs().size() -1){
0500 //move it down
0501 ProcessingResource value = controller.remove(row);
0502 controller.add(row + 1, value);
0503 }
0504 }
0505 // memberPRsTableModel.fireTableDataChanged();
0506 //restore selection
0507 for(int row : rows) {
0508 int newRow;
0509 if(row < controller.getPRs().size() - 1) newRow = row + 1;
0510 else newRow = row;
0511 memberPRsTable.addRowSelectionInterval(newRow, newRow);
0512 }
0513 memberPRsTable.requestFocusInWindow();
0514 }
0515
0516 }
0517 });
0518
0519 // mouse click edit the resource
0520 // mouse double click or context menu add the resource to the application
0521 loadedPRsTable.addMouseListener(new MouseAdapter() {
0522 public void mousePressed(MouseEvent e) {
0523 if(e.isPopupTrigger()) { processMouseEvent(e); }
0524 }
0525 public void mouseReleased(MouseEvent e) {
0526 if(e.isPopupTrigger()) { processMouseEvent(e); }
0527 }
0528 public void mouseClicked(MouseEvent e) {
0529 processMouseEvent(e);
0530 }
0531 protected void processMouseEvent(MouseEvent e) {
0532 int row = loadedPRsTable.rowAtPoint(e.getPoint());
0533 if(row == -1) { return; }
0534 ProcessingResource pr = (ProcessingResource) loadedPRsTable
0535 .getValueAt(row, loadedPRsTable.convertColumnIndexToView(0));
0536
0537 if(e.isPopupTrigger()) {
0538 // context menu
0539 if(!loadedPRsTable.isRowSelected(row)) {
0540 // if right click outside the selection then reset selection
0541 loadedPRsTable.getSelectionModel().setSelectionInterval(row, row);
0542 }
0543 JPopupMenu popup = new XJPopupMenu();
0544 popup.add(addPRAction);
0545 popup.show(loadedPRsTable, e.getPoint().x, e.getPoint().y);
0546
0547 } else if(e.getID() == MouseEvent.MOUSE_CLICKED) {
0548 if (e.getClickCount() == 2) {
0549 //add selected modules on double click
0550 addPRAction.actionPerformed(null);
0551 }
0552 }
0553 }
0554 });
0555
0556 // drag and drop support
0557 loadedPRsTable.setTransferHandler(new TransferHandler() {
0558 // minimal drag and drop that only call the removePRAction when importing
0559 String source = "";
0560 public int getSourceActions(JComponent c) {
0561 return MOVE;
0562 }
0563 protected Transferable createTransferable(JComponent c) {
0564 return new StringSelection("loadedPRsTable");
0565 }
0566 protected void exportDone(JComponent c, Transferable data, int action) {
0567 }
0568 public boolean canImport(JComponent c, DataFlavor[] flavors) {
0569 for(DataFlavor flavor : flavors) {
0570 if(DataFlavor.stringFlavor.equals(flavor)) {
0571 return true;
0572 }
0573 }
0574 return false;
0575 }
0576 public boolean importData(JComponent c, Transferable t) {
0577 if (canImport(c, t.getTransferDataFlavors())) {
0578 try {
0579 source = (String)t.getTransferData(DataFlavor.stringFlavor);
0580 if (source.startsWith("memberPRsTable")) {
0581 removePRAction.actionPerformed(null);
0582 return true;
0583 } else {
0584 return false;
0585 }
0586 } catch (UnsupportedFlavorException ufe) { // just return false later
0587 } catch (IOException ioe) { // just return false later
0588 }
0589 }
0590 return false;
0591 }
0592 });
0593
0594 // mouse click edit the resource
0595 // mouse double click or context menu remove the resource from the
0596 // application
0597 memberPRsTable.addMouseListener(new MouseAdapter() {
0598 public void mousePressed(MouseEvent e) {
0599 if(e.isPopupTrigger()) { processMouseEvent(e); }
0600 }
0601 public void mouseReleased(MouseEvent e) {
0602 if(e.isPopupTrigger()) { processMouseEvent(e); }
0603 }
0604 public void mouseClicked(MouseEvent e) {
0605 processMouseEvent(e);
0606 }
0607 protected void processMouseEvent(MouseEvent e) {
0608 int row = memberPRsTable.rowAtPoint(e.getPoint());
0609 if(row == -1) { return; }
0610
0611 if(e.isPopupTrigger()) {
0612 // context menu
0613 if(!memberPRsTable.isRowSelected(row)) {
0614 // if right click outside the selection then reset selection
0615 memberPRsTable.getSelectionModel().setSelectionInterval(row, row);
0616 }
0617 JPopupMenu popup = new XJPopupMenu();
0618 popup.add(removePRAction);
0619 popup.show(memberPRsTable, e.getPoint().x, e.getPoint().y);
0620
0621 } else if(e.getID() == MouseEvent.MOUSE_CLICKED) {
0622 if (e.getClickCount() == 2) {
0623 //remove selected modules on double click
0624 removePRAction.actionPerformed(null);
0625 }
0626 }
0627 }
0628 });
0629
0630 // Drag and drop support
0631 memberPRsTable.setTransferHandler(new TransferHandler() {
0632 // minimal drag and drop that only call the addPRAction when importing
0633 String source = "";
0634 public int getSourceActions(JComponent c) {
0635 return MOVE;
0636 }
0637 protected Transferable createTransferable(JComponent c) {
0638 int selectedRows[] = memberPRsTable.getSelectedRows();
0639 Arrays.sort(selectedRows);
0640 return new StringSelection("memberPRsTable"
0641 + Arrays.toString(selectedRows));
0642 }
0643 protected void exportDone(JComponent c, Transferable data, int action) {
0644 }
0645 public boolean canImport(JComponent c, DataFlavor[] flavors) {
0646 for(DataFlavor flavor : flavors) {
0647 if(DataFlavor.stringFlavor.equals(flavor)) {
0648 return true;
0649 }
0650 }
0651 return false;
0652 }
0653 public boolean importData(JComponent c, Transferable t) {
0654 if (!canImport(c, t.getTransferDataFlavors())) {
0655 return false;
0656 }
0657 try {
0658 source = (String)t.getTransferData(DataFlavor.stringFlavor);
0659 if (source.startsWith("memberPRsTable")) {
0660 int insertion = memberPRsTable.getSelectedRow();
0661 int initialInsertion = insertion;
0662 List<ProcessingResource> prs = new ArrayList<ProcessingResource>();
0663 source = source.replaceFirst("^memberPRsTable\\[", "");
0664 source = source.replaceFirst("\\]$", "");
0665 String selectedRows[] = source.split(", ");
0666 if (Integer.valueOf(selectedRows[0]) < insertion) { insertion++; }
0667 // get the list of PRs selected when dragging started
0668 for(String row : selectedRows) {
0669 if (Integer.valueOf(row) == initialInsertion) {
0670 // the user draged the selected rows on themselves, do nothing
0671 return false;
0672 }
0673 prs.add((ProcessingResource) memberPRsTable.getValueAt(
0674 Integer.valueOf(row),
0675 memberPRsTable.convertColumnIndexToView(1)));
0676 if (Integer.valueOf(row) < initialInsertion) { insertion--; }
0677 }
0678 // remove the PRs selected when dragging started
0679 for (ProcessingResource pr : prs) {
0680 controller.remove(pr);
0681 }
0682 // add the PRs at the insertion point
0683 for (ProcessingResource pr : prs) {
0684 controller.add(insertion, pr);
0685 insertion++;
0686 }
0687 // select the moved PRs
0688 memberPRsTable.addRowSelectionInterval(
0689 insertion - selectedRows.length, insertion - 1);
0690 return true;
0691 } else if (source.equals("loadedPRsTable")) {
0692 addPRAction.actionPerformed(null);
0693 return true;
0694 } else {
0695 return false;
0696 }
0697 } catch (UnsupportedFlavorException ufe) {
0698 return false;
0699 } catch (IOException ioe) {
0700 return false;
0701 }
0702 }
0703 });
0704
0705 loadedPRsTable.getSelectionModel().addListSelectionListener(
0706 new ListSelectionListener() {
0707 public void valueChanged(ListSelectionEvent e) {
0708 // disable Add button if no selection
0709 addButton.setEnabled(loadedPRsTable.getSelectedRowCount() > 0);
0710 }
0711 });
0712
0713 memberPRsTable.getSelectionModel().addListSelectionListener(
0714 new ListSelectionListener() {
0715 public void valueChanged(ListSelectionEvent e) {
0716 // disable Remove and Move buttons if no selection
0717 removeButton.setEnabled(memberPRsTable.getSelectedRowCount() > 0);
0718 moveUpButton.setEnabled(memberPRsTable.getSelectedRowCount() > 0
0719 && !memberPRsTable.isRowSelected(0));
0720 moveDownButton.setEnabled(memberPRsTable.getSelectedRowCount() > 0
0721 && !memberPRsTable.isRowSelected(memberPRsTable.getRowCount() - 1));
0722 //update the parameters & strategy editors
0723 if(memberPRsTable.getSelectedRowCount() == 1){
0724 //only one selection
0725 selectPR(memberPRsTable.getSelectedRow());
0726 }else{
0727 //clean up UI
0728 selectPR(-1);
0729 }
0730 }
0731 });
0732
0733 if(conditionalMode){
0734 /**
0735 * A listener called when the selection state changes for any of the
0736 * execution mode radio buttons. We use selection changes rather than
0737 * action listeners, as the change of state may not be as results of an
0738 * action (e.g. editing one of the text fields, changes the selection).
0739 */
0740 ItemListener strategyModeListener = new ItemListener() {
0741 public void itemStateChanged(ItemEvent e) {
0742 if(selectedPRRunStrategy != null) {
0743 if(selectedPRRunStrategy instanceof AnalyserRunningStrategy){
0744 AnalyserRunningStrategy strategy =
0745 (AnalyserRunningStrategy)selectedPRRunStrategy;
0746 if(yes_RunRBtn.isSelected()){
0747 strategy.setRunMode(RunningStrategy.RUN_ALWAYS);
0748 }else if(no_RunRBtn.isSelected()){
0749 strategy.setRunMode(RunningStrategy.RUN_NEVER);
0750 }else if(conditional_RunRBtn.isSelected()){
0751 strategy.setRunMode(RunningStrategy.RUN_CONDITIONAL);
0752 }
0753 } else if(selectedPRRunStrategy instanceof UnconditionalRunningStrategy) {
0754 UnconditionalRunningStrategy strategy =
0755 (UnconditionalRunningStrategy)selectedPRRunStrategy;
0756 if(yes_RunRBtn.isSelected()){
0757 strategy.shouldRun(true);
0758 }else if(no_RunRBtn.isSelected()){
0759 strategy.shouldRun(false);
0760 }
0761 }
0762 }
0763 //some icons may have changed!
0764 memberPRsTable.repaint();
0765 }
0766 };
0767
0768 yes_RunRBtn.addItemListener(strategyModeListener);
0769 no_RunRBtn.addItemListener(strategyModeListener);
0770 conditional_RunRBtn.addItemListener(strategyModeListener);
0771
0772
0773 featureNameTextField.getDocument().addDocumentListener(
0774 new javax.swing.event.DocumentListener() {
0775 public void insertUpdate(javax.swing.event.DocumentEvent e) {
0776 changeOccured(e);
0777 }
0778
0779 public void removeUpdate(javax.swing.event.DocumentEvent e) {
0780 changeOccured(e);
0781 }
0782
0783 public void changedUpdate(javax.swing.event.DocumentEvent e) {
0784 changeOccured(e);
0785 }
0786
0787 protected void changeOccured(javax.swing.event.DocumentEvent e){
0788 if(selectedPRRunStrategy != null &&
0789 selectedPRRunStrategy instanceof AnalyserRunningStrategy){
0790 AnalyserRunningStrategy strategy =
0791 (AnalyserRunningStrategy)selectedPRRunStrategy;
0792 strategy.setFeatureName(featureNameTextField.getText());
0793 }
0794 //editing the textfield changes the running strategy to conditional
0795 conditional_RunRBtn.setSelected(true);
0796 }
0797 });
0798
0799 featureValueTextField.getDocument().addDocumentListener(
0800 new javax.swing.event.DocumentListener() {
0801 public void insertUpdate(javax.swing.event.DocumentEvent e) {
0802 changeOccured(e);
0803 }
0804
0805 public void removeUpdate(javax.swing.event.DocumentEvent e) {
0806 changeOccured(e);
0807 }
0808
0809 public void changedUpdate(javax.swing.event.DocumentEvent e) {
0810 changeOccured(e);
0811 }
0812
0813 protected void changeOccured(javax.swing.event.DocumentEvent e){
0814 if(selectedPRRunStrategy != null &&
0815 selectedPRRunStrategy instanceof AnalyserRunningStrategy){
0816 AnalyserRunningStrategy strategy =
0817 (AnalyserRunningStrategy)selectedPRRunStrategy;
0818 strategy.setFeatureValue(featureValueTextField.getText());
0819 }
0820 //editing the textfield changes the running strategy to conditional
0821 conditional_RunRBtn.setSelected(true);
0822 }
0823 });
0824 }//if conditional
0825
0826 if(corpusControllerMode){
0827 corpusCombo.addPopupMenuListener(new PopupMenuListener() {
0828 public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
0829 corpusComboModel.fireDataChanged();
0830 }
0831
0832 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
0833 }
0834
0835 public void popupMenuCanceled(PopupMenuEvent e) {
0836 }
0837 });
0838 }
0839
0840 addAncestorListener(new AncestorListener() {
0841 public void ancestorAdded(AncestorEvent event) {
0842 // every time the user switches back to this view, we check
0843 // whether another controller has just included this one
0844 loadedPRsTableModel.fireTableDataChanged();
0845 memberPRsTableModel.fireTableDataChanged();
0846 }
0847 public void ancestorRemoved(AncestorEvent event) { /* do nothing */ }
0848 public void ancestorMoved(AncestorEvent event) { /* do nothing */
0849 }
0850 }
0851 );
0852
0853 // binds F3 key to the run action
0854 getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
0855 .put(KeyStroke.getKeyStroke("F3"), "Run");
0856 getActionMap().put("Run", runAction);
0857
0858 }//protected void initListeners()
0859
0860
0861 public List getActions(){
0862 return actionList;
0863 }
0864
0865 /**
0866 * Cleans the internal data and prepares this object to be collected
0867 */
0868 public void cleanup(){
0869 Gate.getCreoleRegister().removeCreoleListener(this);
0870 controller.removeControllerListener(this);
0871 controller = null;
0872 progressListeners.clear();
0873 statusListeners.clear();
0874 parametersEditor.cleanup();
0875 handle = null;
0876 }
0877
0878 /**
0879 * Called when a PR has been selected in the member PRs table;
0880 * @param index row index in {@link #memberPRsTable} (or -1 if no PR is
0881 * currently selected)
0882 */
0883 protected void selectPR(int index){
0884 //stop current editing of parameters
0885 if(parametersEditor.getResource() != null){
0886 try{
0887 parametersEditor.setParameters();
0888 }catch(ResourceInstantiationException rie){
0889 JOptionPane.showMessageDialog(
0890 SerialControllerEditor.this,
0891 "Failed to set parameters for \"" +
0892 parametersEditor.getResource().getName() +"\"!\n" ,
0893 "GATE", JOptionPane.ERROR_MESSAGE);
0894 rie.printStackTrace(Err.getPrintWriter());
0895 }
0896
0897 if(conditionalMode){
0898 if(selectedPRRunStrategy != null &&
0899 selectedPRRunStrategy instanceof AnalyserRunningStrategy){
0900 AnalyserRunningStrategy strategy =
0901 (AnalyserRunningStrategy)selectedPRRunStrategy;
0902 strategy.setFeatureName(featureNameTextField.getText());
0903 strategy.setFeatureValue(featureValueTextField.getText());
0904 }
0905 selectedPRRunStrategy = null;
0906 }
0907 }
0908 //find the new PR
0909 ProcessingResource pr = null;
0910 if(index >= 0 && index < controller.getPRs().size()){
0911 pr = (ProcessingResource)((java.util.List)controller.getPRs()).get(index);
0912 }
0913 if(pr != null){
0914 //update the GUI for the new PR
0915 ResourceData rData = (ResourceData)Gate.getCreoleRegister().
0916 get(pr.getClass().getName());
0917 //update the border name
0918 parametersBorder.setTitle(" Runtime Parameters for the \"" + pr.getName() +
0919 "\" " + rData.getName() + ": ");
0920 //update the params editor
0921 //this is a list of lists
0922 List<List<Parameter>> parameters =
0923 rData.getParameterList().getRuntimeParameters();
0924 if(corpusControllerMode){
0925 //remove corpus and document
0926 //create a new list so we don't change the one from CreoleReg.
0927 List<List<Parameter>> oldParameters = parameters;
0928 parameters = new ArrayList<List<Parameter>>();
0929 for(List<Parameter> aDisjunction : oldParameters) {
0930 List<Parameter> newDisjunction = new ArrayList<Parameter>();
0931 for(Parameter parameter : aDisjunction) {
0932 if(!parameter.getName().equals("corpus")
0933 && !parameter.getName().equals("document")) {
0934 newDisjunction.add(parameter);
0935 }
0936 }
0937 if(!newDisjunction.isEmpty()) parameters.add(newDisjunction);
0938 }
0939 }
0940 parametersEditor.init(pr, parameters);
0941
0942 if(conditionalMode){
0943 strategyBorder.setTitle(" Run \"" + pr.getName() + "\"? ");
0944 //update the state of the run strategy buttons
0945 yes_RunRBtn.setEnabled(true);
0946 no_RunRBtn.setEnabled(true);
0947 conditional_RunRBtn.setEnabled(true);
0948
0949 //editing the strategy panel causes the edits to be sent to the current
0950 //strategy object, which can lead to a race condition.
0951 //So we used a cached value instead.
0952 selectedPRRunStrategy = null;
0953 RunningStrategy newStrategy = (RunningStrategy)
0954 ((List)((ConditionalController)controller).
0955 getRunningStrategies()).get(index);
0956 if(newStrategy instanceof AnalyserRunningStrategy){
0957 featureNameTextField.setEnabled(true);
0958 featureValueTextField.setEnabled(true);
0959 conditional_RunRBtn.setEnabled(true);
0960 featureNameTextField.setText(
0961 ((AnalyserRunningStrategy)newStrategy).
0962 getFeatureName());
0963 featureValueTextField.setText(
0964 ((AnalyserRunningStrategy)newStrategy).
0965 getFeatureValue());
0966 }
0967 else {
0968 featureNameTextField.setEnabled(false);
0969 featureValueTextField.setEnabled(false);
0970 conditional_RunRBtn.setEnabled(false);
0971 }
0972 switch(newStrategy.getRunMode()){
0973 case RunningStrategy.RUN_ALWAYS:{
0974 yes_RunRBtn.setSelected(true);
0975 break;
0976 }
0977 case RunningStrategy.RUN_NEVER:{
0978 no_RunRBtn.setSelected(true);
0979 break;
0980 }
0981 case RunningStrategy.RUN_CONDITIONAL:{
0982 conditional_RunRBtn.setSelected(true);
0983 break;
0984 }
0985 }//switch
0986 //now that the UI is updated, we can safely link to the new strategy
0987 selectedPRRunStrategy = newStrategy;
0988 }
0989 }else{
0990 //selected PR == null -> clean all mentions of the old PR from the GUI
0991 parametersBorder.setTitle(" No processing resource selected... ");
0992 parametersEditor.init(null, null);
0993 if(conditionalMode){
0994 strategyBorder.setTitle(" No processing resource selected... ");
0995 yes_RunRBtn.setEnabled(false);
0996 no_RunRBtn.setEnabled(false);
0997 conditional_RunRBtn.setEnabled(false);
0998 featureNameTextField.setText("");
0999 featureNameTextField.setEnabled(false);
1000 featureValueTextField.setText("");
1001 featureValueTextField.setEnabled(false);
1002 }
1003 }
1004 //this seems to be needed to show the changes
1005 SerialControllerEditor.this.repaint(100);
1006 }
1007
1008
1009 //CreoleListener implementation
1010 public void resourceLoaded(CreoleEvent e) {
1011 if(Gate.getHiddenAttribute(e.getResource().getFeatures())) return;
1012 if(e.getResource() instanceof ProcessingResource){
1013 loadedPRsTableModel.fireTableDataChanged();
1014 memberPRsTableModel.fireTableDataChanged();
1015 // repaint(100);
1016 }else if(e.getResource() instanceof LanguageResource){
1017 if(e.getResource() instanceof Corpus && corpusControllerMode){
1018 corpusComboModel.fireDataChanged();
1019 }
1020 }
1021 }
1022
1023 public void resourceUnloaded(CreoleEvent e) {
1024 if(Gate.getHiddenAttribute(e.getResource().getFeatures())) return;
1025 if(e.getResource() instanceof ProcessingResource){
1026 ProcessingResource pr = (ProcessingResource)e.getResource();
1027 if(controller != null && controller.getPRs().contains(pr)){
1028 controller.remove(pr);
1029 }
1030 loadedPRsTableModel.fireTableDataChanged();
1031 memberPRsTableModel.fireTableDataChanged();
1032 // repaint(100);
1033 }
1034 else if(e.getResource() instanceof LanguageResource) {
1035 if(e.getResource() instanceof Corpus && corpusControllerMode) {
1036 Corpus c = (Corpus)e.getResource();
1037 if(controller instanceof CorpusController) {
1038 if(c == ((CorpusController)controller).getCorpus()) {
1039 // setCorpus(null) is also called in the controller's
1040 // resourceUnloaded(), but we can't be sure which handler is
1041 // called first...
1042 ((CorpusController)controller).setCorpus(null);
1043 }
1044 }
1045 else {
1046 throw new GateRuntimeException("Controller editor in analyser mode " +
1047 "but the target controller is not an " +
1048 "analyser!");
1049 }
1050 corpusComboModel.fireDataChanged();
1051 }
1052 }
1053 }
1054
1055 public void resourceRenamed(Resource resource, String oldName,
1056 String newName){
1057 if(Gate.getHiddenAttribute(resource.getFeatures())) return;
1058 if(resource instanceof ProcessingResource){
1059 repaint(100);
1060 }
1061 }
1062
1063 public void datastoreOpened(CreoleEvent e) {
1064 }
1065 public void datastoreCreated(CreoleEvent e) {
1066 }
1067 public void datastoreClosed(CreoleEvent e) {
1068 }
1069 public synchronized void removeStatusListener(StatusListener l) {
1070 if (statusListeners != null && statusListeners.contains(l)) {
1071 Vector<StatusListener> v = (Vector) statusListeners.clone();
1072 v.removeElement(l);
1073 statusListeners = v;
1074 }
1075 }
1076
1077 /* (non-Javadoc)
1078 * @see gate.event.ControllerListener#resourceAdded(gate.event.ControllerEvent)
1079 */
1080 public void resourceAdded(ControllerEvent evt){
1081 loadedPRsTableModel.fireTableDataChanged();
1082 memberPRsTableModel.fireTableDataChanged();
1083 }
1084
1085 /* (non-Javadoc)
1086 * @see gate.event.ControllerListener#resourceRemoved(gate.event.ControllerEvent)
1087 */
1088 public void resourceRemoved(ControllerEvent evt){
1089 loadedPRsTableModel.fireTableDataChanged();
1090 memberPRsTableModel.fireTableDataChanged();
1091 }
1092
1093 public synchronized void addStatusListener(StatusListener l) {
1094 Vector<StatusListener> v = statusListeners == null ?
1095 new Vector(2) : (Vector) statusListeners.clone();
1096 if (!v.contains(l)) {
1097 v.addElement(l);
1098 statusListeners = v;
1099 }
1100 }
1101
1102 private boolean firstIncludesOrEqualsSecond(Controller first,
1103 Controller second) {
1104 if (first.equals(second)) {
1105 return true;
1106 } else {
1107 for (Object object : first.getPRs()) {
1108 if (object instanceof Controller) {
1109 if (firstIncludesOrEqualsSecond((Controller)object, second)) {
1110 return true;
1111 }
1112 }
1113 }
1114 }
1115 return false;
1116 }
1117
1118 /**
1119 * Table model for all the loaded processing resources that are not part of
1120 * the controller.
1121 */
1122 class LoadedPRsTableModel extends AbstractTableModel{
1123 public int getRowCount(){
1124 List<ProcessingResource> loadedPRs = new ArrayList<ProcessingResource>(
1125 Gate.getCreoleRegister().getPrInstances());
1126 if(controller != null) {
1127 loadedPRs.removeAll(controller.getPRs());
1128 }
1129 Iterator prsIter = loadedPRs.iterator();
1130 while(prsIter.hasNext()){
1131 ProcessingResource aPR = (ProcessingResource)prsIter.next();
1132 if(Gate.getHiddenAttribute(aPR.getFeatures())
1133 || ( aPR instanceof Controller
1134 && firstIncludesOrEqualsSecond((Controller)aPR, controller)) ) {
1135 prsIter.remove();
1136 }
1137 }
1138
1139 return loadedPRs.size();
1140 }
1141
1142 public Object getValueAt(int row, int column){
1143 List<ProcessingResource> loadedPRs = new ArrayList<ProcessingResource>(
1144 Gate.getCreoleRegister().getPrInstances());
1145 if(controller != null) {
1146 loadedPRs.removeAll(controller.getPRs());
1147 }
1148 Iterator prsIter = loadedPRs.iterator();
1149 while(prsIter.hasNext()){
1150 ProcessingResource aPR = (ProcessingResource)prsIter.next();
1151 if(Gate.getHiddenAttribute(aPR.getFeatures())
1152 || ( aPR instanceof Controller
1153 && firstIncludesOrEqualsSecond((Controller)aPR, controller)) ) {
1154 prsIter.remove();
1155 }
1156 }
1157
1158 Collections.sort(loadedPRs, nameComparator);
1159 ProcessingResource pr = loadedPRs.get(row);
1160 switch(column){
1161 case 0 : return pr;
1162 case 1 : {
1163 ResourceData rData = Gate.getCreoleRegister()
1164 .get(pr.getClass().getName());
1165 if(rData == null) return pr.getClass();
1166 else return rData.getName();
1167 }
1168 default: return null;
1169 }
1170 }
1171
1172 public int getColumnCount(){
1173 return 2;
1174 }
1175
1176 public String getColumnName(int columnIndex){
1177 switch(columnIndex){
1178 case 0 : return "Name";
1179 case 1 : return "Type";
1180 default: return "?";
1181 }
1182 }
1183
1184 public Class getColumnClass(int columnIndex){
1185 switch(columnIndex){
1186 case 0 : return ProcessingResource.class;
1187 case 1 : return String.class;
1188 default: return Object.class;
1189 }
1190 }
1191
1192 public boolean isCellEditable(int rowIndex, int columnIndex){
1193 return false;
1194 }
1195
1196 public void setValueAt(Object aValue, int rowIndex, int columnIndex){
1197 }
1198 NameComparator nameComparator = new NameComparator();
1199 }//protected class LoadedPRsTableModel extends AbstractTableModel
1200
1201 /**
1202 * A model for a combobox containing the loaded corpora in the system
1203 */
1204 protected class CorporaComboModel extends AbstractListModel
1205 implements ComboBoxModel{
1206 public int getSize(){
1207 //get all corpora regardless of their actual type
1208 java.util.List loadedCorpora = null;
1209 try{
1210 loadedCorpora = Gate.getCreoleRegister().
1211 getAllInstances("gate.Corpus");
1212 }catch(GateException ge){
1213 ge.printStackTrace(Err.getPrintWriter());
1214 }
1215
1216 return loadedCorpora == null ? 1 : loadedCorpora.size() + 1;
1217 }
1218
1219 public Object getElementAt(int index){
1220 if(index == 0) return "<none>";
1221 else{
1222 //get all corpora regardless of their actual type
1223 java.util.List loadedCorpora = null;
1224 try{
1225 loadedCorpora = Gate.getCreoleRegister().
1226 getAllInstances("gate.Corpus");
1227 }catch(GateException ge){
1228 ge.printStackTrace(Err.getPrintWriter());
1229 }
1230 return loadedCorpora == null? "" : loadedCorpora.get(index - 1);
1231 }
1232 }
1233
1234 //use the controller for data caching
1235 public void setSelectedItem(Object anItem){
1236 if(controller instanceof CorpusController)
1237 ((CorpusController)controller).
1238 setCorpus((Corpus)(anItem.equals("<none>") ? null : anItem));
1239 }
1240
1241 public Object getSelectedItem(){
1242 Corpus corpus = null;
1243 if(controller instanceof CorpusController) {
1244 corpus = ((CorpusController)controller).getCorpus();
1245 }else{
1246 throw new GateRuntimeException("Controller editor in corpus " +
1247 "controller mode " +
1248 "but the target controller is not a " +
1249 "CorpusController!");
1250 }
1251 return (corpus == null ? (Object)"<none>" : (Object)corpus);
1252 }
1253
1254 void fireDataChanged(){
1255 fireContentsChanged(this, 0, getSize());
1256 }
1257 }
1258
1259 /**
1260 * Renders JLabel by simply displaying them
1261 */
1262 class IconRenderer extends DefaultTableCellRenderer{
1263
1264 public Component getTableCellRendererComponent(JTable table,
1265 Object value,
1266 boolean isSelected,
1267 boolean hasFocus,
1268 int row,
1269 int column){
1270 super.getTableCellRendererComponent(table, "", isSelected, hasFocus,
1271 row, column);
1272 setIcon((Icon)value);
1273 return this;
1274 }
1275
1276 @Override
1277 public Dimension getMaximumSize() {
1278 return getPreferredSize();
1279 }
1280
1281 @Override
1282 public Dimension getMinimumSize() {
1283 return getPreferredSize();
1284 }
1285
1286 }
1287
1288 /**
1289 * Table model for all the processing resources in the controller.
1290 */
1291 class MemberPRsTableModel extends AbstractTableModel{
1292 public MemberPRsTableModel(){
1293 green = MainFrame.getIcon("greenBall");
1294 red = MainFrame.getIcon("redBall");
1295 yellow = MainFrame.getIcon("yellowBall");
1296 }
1297
1298 public int getRowCount(){
1299 return controller == null ? 0 : controller.getPRs().size();
1300 }
1301
1302 public Object getValueAt(int row, int column){
1303 ProcessingResource pr = (ProcessingResource)
1304 ((List)controller.getPRs()).get(row);
1305 switch(column){
1306 case 0 : {
1307 if(conditionalMode){
1308 RunningStrategy strategy = (RunningStrategy)
1309 ((List)((ConditionalController)controller).
1310 getRunningStrategies()).get(row);
1311 switch(strategy.getRunMode()){
1312 case RunningStrategy.RUN_ALWAYS : return green;
1313 case RunningStrategy.RUN_NEVER : return red;
1314 case RunningStrategy.RUN_CONDITIONAL : return yellow;
1315 }
1316 }
1317 return green;
1318 }
1319 case 1 : return pr;
1320 case 2 : {
1321 ResourceData rData = (ResourceData)Gate.getCreoleRegister().
1322 get(pr.getClass().getName());
1323 if(rData == null) return pr.getClass();
1324 else return rData.getName();
1325 }
1326 default: return null;
1327 }
1328 }
1329
1330 public int getColumnCount(){
1331 return 3;
1332 }
1333
1334 public String getColumnName(int columnIndex){
1335 switch(columnIndex){
1336 case 0 : return "!";
1337 case 1 : return "Name";
1338 // case 1 : return "!";
1339 case 2 : return "Type";
1340 default: return "?";
1341 }
1342 }
1343
1344 public Class getColumnClass(int columnIndex){
1345 switch(columnIndex){
1346 case 0 : return Icon.class;
1347 case 1 : return ProcessingResource.class;
1348 // case 1 : return Boolean.class;
1349 case 2 : return String.class;
1350 default: return Object.class;
1351 }
1352 }
1353
1354 public boolean isCellEditable(int rowIndex, int columnIndex){
1355 return false;
1356 }
1357
1358 public void setValueAt(Object aValue, int rowIndex, int columnIndex){
1359 }
1360
1361 protected Icon green, red, yellow;
1362 }//protected class MemberPRsTableModel extends AbstractTableModel
1363
1364 /** Adds a PR to the controller*/
1365 class AddPRAction extends AbstractAction {
1366 AddPRAction(){
1367 putValue(NAME, "Add selected resources to the application");
1368 putValue(SHORT_DESCRIPTION, "Add selected resources to the application");
1369 putValue(SMALL_ICON, MainFrame.getIcon("right-arrow"));
1370 putValue(MNEMONIC_KEY, KeyEvent.VK_RIGHT);
1371 }
1372
1373 public void actionPerformed(ActionEvent e){
1374 try {
1375 List<ProcessingResource> prs = new ArrayList<ProcessingResource>();
1376 int selectedRows[] = loadedPRsTable.getSelectedRows();
1377 Arrays.sort(selectedRows);
1378 for (int row : selectedRows) {
1379 prs.add((ProcessingResource) loadedPRsTable
1380 .getValueAt(row, loadedPRsTable.convertColumnIndexToView(0)));
1381 }
1382 //insert the new PRs after the last currently selected row.
1383 selectedRows = memberPRsTable.getSelectedRows();
1384 Arrays.sort(selectedRows);
1385 int insertion = selectedRows.length == 0 ?
1386 memberPRsTable.getRowCount() :
1387 selectedRows[selectedRows.length -1] +1;
1388 for (ProcessingResource pr : prs) {
1389 controller.add(insertion, pr);
1390 insertion++;
1391 }
1392 //select the newly added PRs
1393 for (ProcessingResource pr : prs) {
1394 for (int row = 0; row < memberPRsTable.getRowCount(); row++) {
1395 if (memberPRsTable.getValueAt(row,
1396 memberPRsTable.convertColumnIndexToView(1)) == pr) {
1397 memberPRsTable.addRowSelectionInterval(row, row);
1398 }
1399 }
1400 }
1401 memberPRsTable.requestFocusInWindow();
1402 }
1403 catch(GateRuntimeException ex) {
1404 JOptionPane.showMessageDialog(SerialControllerEditor.this,
1405 "Could not add PR to pipeline:\n"
1406 +ex.getMessage(),
1407 "GATE", JOptionPane.ERROR_MESSAGE);
1408 return;
1409 }
1410 }
1411 }
1412
1413 /** Removes a PR from the controller*/
1414 class RemovePRAction extends AbstractAction {
1415 RemovePRAction(){
1416 putValue(NAME, "Remove selected resouces from the application");
1417 putValue(SHORT_DESCRIPTION,
1418 "Remove selected resouces from the application");
1419 putValue(SMALL_ICON, MainFrame.getIcon("left-arrow"));
1420 putValue(MNEMONIC_KEY, KeyEvent.VK_LEFT);
1421 }
1422
1423 public void actionPerformed(ActionEvent e){
1424 List<ProcessingResource> prs = new ArrayList<ProcessingResource>();
1425 for (int row : memberPRsTable.getSelectedRows()) {
1426 prs.add((ProcessingResource) memberPRsTable
1427 .getValueAt(row, memberPRsTable.convertColumnIndexToView(1)));
1428 }
1429 for (ProcessingResource pr : prs) {
1430 controller.remove(pr);
1431 }
1432 // transfer the selection
1433 for (ProcessingResource pr : prs) {
1434 for (int row = 0; row < loadedPRsTable.getRowCount(); row++) {
1435 if (loadedPRsTable.getValueAt(row,
1436 loadedPRsTable.convertColumnIndexToView(0)) == pr) {
1437 loadedPRsTable.addRowSelectionInterval(row, row);
1438 }
1439 }
1440 }
1441 loadedPRsTable.requestFocusInWindow();
1442 if (memberPRsTable.getSelectedRowCount() == 0) {
1443 parametersEditor.init(null, null);
1444 parametersBorder.setTitle("No selected processing resource");
1445 }
1446 }
1447 }
1448
1449
1450 /** Runs the Application*/
1451 class RunAction extends AbstractAction {
1452 RunAction(){
1453 super("Run this Application");
1454 super.putValue(SHORT_DESCRIPTION, "<html>Run this application"
1455 +" <font color=#667799><small>F3"
1456 +" </small></font></html>");
1457 }
1458
1459 public void actionPerformed(ActionEvent e){
1460 Runnable runnable = new Runnable(){
1461 public void run(){
1462
1463 if (memberPRsTable.getRowCount() == 0) {
1464 JOptionPane.showMessageDialog(SerialControllerEditor.this,
1465 "Add at least one processing resource in the right table\n"
1466 +"that contains the resources of the application to be run.",
1467 "GATE", JOptionPane.ERROR_MESSAGE);
1468 return;
1469 }
1470
1471 //stop editing the parameters
1472 try{
1473 parametersEditor.setParameters();
1474 }catch(ResourceInstantiationException rie){
1475 JOptionPane.showMessageDialog(
1476 SerialControllerEditor.this,
1477 "Could not set parameters for the \"" +
1478 parametersEditor.getResource().getName() +
1479 "\" processing resource:\nSee \"Messages\" tab for details!",
1480 "GATE", JOptionPane.ERROR_MESSAGE);
1481 rie.printStackTrace(Err.getPrintWriter());
1482 return;
1483 }
1484
1485 if(corpusControllerMode){
1486 //set the corpus
1487 Object value = corpusCombo.getSelectedItem();
1488 Corpus corpus = value.equals("<none>") ? null : (Corpus)value;
1489 if(analyserMode && corpus == null){
1490 JOptionPane.showMessageDialog(
1491 SerialControllerEditor.this,
1492 "No corpus provided!\n" +
1493 "Please select a corpus and try again!",
1494 "GATE", JOptionPane.ERROR_MESSAGE);
1495 corpusCombo.requestFocusInWindow();
1496 return;
1497 }
1498 if(controller instanceof CorpusController)
1499 ((CorpusController)controller).setCorpus(corpus);
1500 }
1501 //check the runtime parameters
1502 List badPRs;
1503 try{
1504 badPRs = controller.getOffendingPocessingResources();
1505 }catch(ResourceInstantiationException rie){
1506 JOptionPane.showMessageDialog(
1507 SerialControllerEditor.this,
1508 "Could not check runtime parameters for " +
1509 "the processing resources:\n" + rie.toString(),
1510 "GATE", JOptionPane.ERROR_MESSAGE);
1511 return;
1512 }
1513 if(badPRs != null && !badPRs.isEmpty()){
1514 String badPRsString = "";
1515 for (Object badPR : badPRs) {
1516 badPRsString += "- "
1517 + ((ProcessingResource) badPR).getName() + "\n";
1518 }
1519 //we know what PRs have problems so it would be nice to show
1520 //them in red or something
1521 JOptionPane.showMessageDialog(
1522 SerialControllerEditor.this,
1523 "Some required runtime parameters are not set\n"+
1524 "in the following resources:\n"+
1525 badPRsString,
1526 "GATE", JOptionPane.ERROR_MESSAGE);
1527 return;
1528 }
1529
1530 //set the listeners
1531 StatusListener sListener = new InternalStatusListener();
1532 ProgressListener pListener = new InternalProgressListener();
1533
1534 controller.addStatusListener(sListener);
1535 controller.addProgressListener(pListener);
1536
1537 Gate.setExecutable(controller);
1538
1539 int corpusSize = 1;
1540 if (controller instanceof CorpusController) {
1541 corpusSize = ((CorpusController) controller).getCorpus().size();
1542 }
1543 MainFrame.lockGUI("Running " + controller.getName() + " on "
1544 + corpusSize + (corpusSize == 1 ? " document" : " documents"));
1545 //execute the thing
1546 long startTime = System.currentTimeMillis();
1547 fireStatusChanged("Start running " + controller.getName() + " on "
1548 + corpusSize + (corpusSize == 1 ? " document" : " documents"));
1549 fireProgressChanged(0);
1550
1551 try {
1552 Benchmark.executeWithBenchmarking(controller,
1553 Benchmark.createBenchmarkId(controller.getName(), null),
1554 RunAction.this, null);
1555 }catch(ExecutionInterruptedException eie){
1556 MainFrame.unlockGUI();
1557 JOptionPane.showMessageDialog(
1558 SerialControllerEditor.this,
1559 "Interrupted!\n" + eie.toString(),
1560 "GATE", JOptionPane.ERROR_MESSAGE);
1561 }catch(ExecutionException ee) {
1562 ee.printStackTrace(Err.getPrintWriter());
1563 MainFrame.unlockGUI();
1564 JOptionPane.showMessageDialog(
1565 SerialControllerEditor.this,
1566 "Execution error while running \"" + controller.getName() +
1567 "\" :\nSee \"Messages\" tab for details!",
1568 "GATE", JOptionPane.ERROR_MESSAGE);
1569 }catch(Exception e){
1570 MainFrame.unlockGUI();
1571 JOptionPane.showMessageDialog(SerialControllerEditor.this,
1572 "Unhandled execution error!\n " +
1573 "See \"Messages\" tab for details!",
1574 "GATE", JOptionPane.ERROR_MESSAGE);
1575 e.printStackTrace(Err.getPrintWriter());
1576 }finally{
1577 MainFrame.unlockGUI();
1578 Gate.setExecutable(null);
1579 }//catch
1580
1581 //remove the listeners
1582 controller.removeStatusListener(sListener);
1583 controller.removeProgressListener(pListener);
1584
1585 long endTime = System.currentTimeMillis();
1586 fireProcessFinished();
1587 fireStatusChanged(controller.getName() +
1588 " run in " +
1589 NumberFormat.getInstance().format(
1590 (double)(endTime - startTime) / 1000) + " seconds");
1591 }
1592 };
1593 Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1594 runnable,
1595 "ApplicationViewer1");
1596 thread.setPriority(Thread.MIN_PRIORITY);
1597 thread.start();
1598 }//public void actionPerformed(ActionEvent e)
1599 }//class RunAction
1600
1601 /**
1602 * A simple progress listener used to forward the events upstream.
1603 */
1604 protected class InternalProgressListener implements ProgressListener{
1605 public void progressChanged(int i){
1606 fireProgressChanged(i);
1607 }
1608
1609 public void processFinished(){
1610 fireProcessFinished();
1611 }
1612 }//InternalProgressListener
1613
1614 /**
1615 * A simple status listener used to forward the events upstream.
1616 */
1617 protected class InternalStatusListener implements StatusListener{
1618 public void statusChanged(String message){
1619 fireStatusChanged(message);
1620 }
1621 }//InternalStatusListener
1622
1623
1624
1625 /** The controller this editor edits */
1626 protected SerialController controller;
1627
1628 /** The {@link Handle} that created this view */
1629 protected Handle handle;
1630
1631 /**
1632 * The list of actions provided by this editor
1633 */
1634 protected List<Action> actionList;
1635 /**
1636 * Contains all the PRs loaded in the sytem that are not already part of the
1637 * serial controller
1638 */
1639 protected XJTable loadedPRsTable;
1640
1641 /**
1642 * model for the {@link #loadedPRsTable} JTable.
1643 */
1644 protected LoadedPRsTableModel loadedPRsTableModel;
1645
1646 /**
1647 * Displays the PRs in the controller
1648 */
1649 protected XJTable memberPRsTable;
1650
1651 /** model for {@link #memberPRsTable}*/
1652 protected MemberPRsTableModel memberPRsTableModel;
1653
1654 /** Adds one or more PR(s) to the controller*/
1655 protected JButton addButton;
1656
1657 /** Removes one or more PR(s) from the controller*/
1658 protected JButton removeButton;
1659
1660 /** Moves the module up in the controller list*/
1661 protected JButton moveUpButton;
1662
1663 /** Moves the module down in the controller list*/
1664 protected JButton moveDownButton;
1665
1666 /** A component for editing the parameters of the currently selected PR*/
1667 protected ResourceParametersEditor parametersEditor;
1668
1669 /** A JPanel containing the {@link #parametersEditor}*/
1670 protected JPanel parametersPanel;
1671
1672 /** A border for the {@link #parametersPanel} */
1673 protected TitledBorder parametersBorder;
1674
1675
1676 /** A JPanel containing the running strategy options*/
1677 protected JPanel strategyPanel;
1678
1679 /** A border for the running strategy options box */
1680 protected TitledBorder strategyBorder;
1681
1682 /**
1683 * Button for run always.
1684 */
1685 protected JRadioButton yes_RunRBtn;
1686
1687 /**
1688 * Button for never run.
1689 */
1690 protected JRadioButton no_RunRBtn;
1691
1692 /**
1693 * Button for conditional run.
1694 */
1695 protected JRadioButton conditional_RunRBtn;
1696
1697 /**
1698 * The group for run strategy buttons;
1699 */
1700 protected ButtonGroup runBtnGrp;
1701
1702 /**
1703 * Text field for the feature name for conditional run.
1704 */
1705 protected JTextField featureNameTextField;
1706
1707 /**
1708 * Text field for the feature value for conditional run.
1709 */
1710 protected JTextField featureValueTextField;
1711
1712 /**
1713 * A combobox that allows selection of a corpus from the list of loaded
1714 * corpora.
1715 */
1716 protected JComboBox corpusCombo;
1717
1718 protected CorporaComboModel corpusComboModel;
1719
1720 /** Action that runs the application*/
1721 protected RunAction runAction;
1722
1723 /**
1724 * Is the controller displayed a CorpusController?
1725 */
1726 protected boolean corpusControllerMode = false;
1727
1728 /**
1729 * Is the controller displayed an analyser controller?
1730 */
1731 protected boolean analyserMode = false;
1732
1733 /**
1734 * Is the controller displayed conditional?
1735 */
1736 protected boolean conditionalMode = false;
1737
1738 /**
1739 * The PR currently selected (having its parameters set)
1740 */
1741 protected ProcessingResource selectedPR = null;
1742
1743 /**
1744 * The running strategy for the selected PR.
1745 */
1746 protected RunningStrategy selectedPRRunStrategy = null;
1747
1748 private transient Vector<StatusListener> statusListeners;
1749 private transient Vector<ProgressListener> progressListeners;
1750
1751 private AddPRAction addPRAction;
1752 private RemovePRAction removePRAction;
1753
1754
1755 protected void fireStatusChanged(String e) {
1756 if (statusListeners != null) {
1757 Vector<StatusListener> listeners = statusListeners;
1758 int count = listeners.size();
1759 for (int i = 0; i < count; i++) {
1760 listeners.elementAt(i).statusChanged(e);
1761 }
1762 }
1763 }
1764 public synchronized void removeProgressListener(ProgressListener l) {
1765 if (progressListeners != null && progressListeners.contains(l)) {
1766 Vector<ProgressListener> v = (Vector) progressListeners.clone();
1767 v.removeElement(l);
1768 progressListeners = v;
1769 }
1770 }
1771 public synchronized void addProgressListener(ProgressListener l) {
1772 Vector<ProgressListener> v = progressListeners == null ?
1773 new Vector(2) : (Vector) progressListeners.clone();
1774 if (!v.contains(l)) {
1775 v.addElement(l);
1776 progressListeners = v;
1777 }
1778 }
1779 protected void fireProgressChanged(int e) {
1780 if (progressListeners != null) {
1781 Vector<ProgressListener> listeners = progressListeners;
1782 int count = listeners.size();
1783 for (int i = 0; i < count; i++) {
1784 listeners.elementAt(i).progressChanged(e);
1785 }
1786 }
1787 }
1788 protected void fireProcessFinished() {
1789 if (progressListeners != null) {
1790 Vector<ProgressListener> listeners = progressListeners;
1791 int count = listeners.size();
1792 for (int i = 0; i < count; i++) {
1793 listeners.elementAt(i).processFinished();
1794 }
1795 }
1796 }
1797
1798 }
|