1   /*
2    *  Copyright (c) 1998-2001, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  Valentin Tablan 02/10/2001
10   *
11   *  $Id: SerialControllerEditor.java,v 1.29 2002/05/13 09:59:28 valyt Exp $
12   *
13   */
14  
15  package gate.gui;
16  
17  import gate.creole.*;
18  import gate.*;
19  import gate.swing.*;
20  import gate.util.*;
21  import gate.event.*;
22  
23  
24  import javax.swing.*;
25  import javax.swing.table.*;
26  import javax.swing.event.*;
27  import javax.swing.border.*;
28  import java.awt.event.*;
29  import java.awt.Dimension;
30  import java.awt.Component;
31  import java.awt.Color;
32  import java.text.NumberFormat;
33  import java.util.*;
34  
35  public class SerialControllerEditor extends AbstractVisualResource
36                                 implements CreoleListener{
37  
38    public SerialControllerEditor() {
39    }
40  
41    public void setTarget(Object target){
42      if(!(target instanceof SerialController))
43      throw new IllegalArgumentException(
44        "gate.gui.ApplicationViewer can only be used for serial controllers\n" +
45        target.getClass().toString() +
46        " is not a gate.creole.SerialController!");
47      this.controller = (SerialController)target;
48      analyserMode = controller instanceof SerialAnalyserController ||
49                     controller instanceof ConditionalSerialAnalyserController;
50      conditionalMode = controller instanceof ConditionalController;
51      initLocalData();
52      initGuiComponents();
53      initListeners();
54    }//setController
55  
56  
57    public void setHandle(Handle handle) {
58      this.handle = handle;
59      //add the items to the popup
60      JPopupMenu popup = handle.getPopup();
61      popup.addSeparator();
62      popup.add(runAction);
63      popup.addSeparator();
64      popup.add(addMenu);
65      popup.add(removeMenu);
66  
67      popup.addPopupMenuListener(new PopupMenuListener() {
68        public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
69          buildInternalMenus();
70          addMenu.setEnabled(addMenu.getItemCount() > 0);
71          removeMenu.setEnabled(removeMenu.getItemCount() > 0);
72        }
73        public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
74        }
75        public void popupMenuCanceled(PopupMenuEvent e) {
76        }
77      });
78  
79      //register the listeners
80      if(handle instanceof StatusListener)
81        addStatusListener((StatusListener)handle);
82      if(handle instanceof ProgressListener)
83        addProgressListener((ProgressListener)handle);
84    }//setHandle
85  
86    public Resource init() throws ResourceInstantiationException{
87      super.init();
88      return this;
89    }//init
90  
91    protected void initLocalData() {
92      runAction = new RunAction();
93    }//initLocalData
94  
95    protected void initGuiComponents() {
96      setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
97  
98  
99      JPanel topBox = new JPanel();
100     topBox.setLayout(new BoxLayout(topBox, BoxLayout.X_AXIS));
101     topBox.setAlignmentX(Component.LEFT_ALIGNMENT);
102 
103     loadedPRsTableModel = new LoadedPRsTableModel();
104     loadedPRsTable = new XJTable();
105     loadedPRsTable.setModel(loadedPRsTableModel);
106 
107     loadedPRsTable.setDefaultRenderer(ProcessingResource.class,
108                                       new ResourceRenderer());
109 
110 //    loadedPRsTable.setIntercellSpacing(new Dimension(5, 5));
111     final int width1 = new JLabel("Loaded Processing resources").
112                 getPreferredSize().width + 10;
113     JScrollPane scroller = new JScrollPane(){
114       public Dimension getPreferredSize(){
115         Dimension dim = super.getPreferredSize();
116         dim.width = Math.max(dim.width, width1);
117         return dim;
118       }
119     };
120     scroller.getViewport().setView(loadedPRsTable);
121     scroller.setBorder(BorderFactory.
122                        createTitledBorder(BorderFactory.createEtchedBorder(),
123                                           " Loaded Processing resources "));
124 
125     topBox.add(scroller);
126     topBox.add(Box.createHorizontalGlue());
127 
128     addButon = new JButton(MainFrame.getIcon("right.gif"));
129     removeButton = new JButton(MainFrame.getIcon("left.gif"));
130 
131     Box buttonsBox =Box.createVerticalBox();
132     buttonsBox.add(Box.createVerticalGlue());
133     buttonsBox.add(addButon);
134     buttonsBox.add(Box.createVerticalStrut(5));
135     buttonsBox.add(removeButton);
136     buttonsBox.add(Box.createVerticalGlue());
137 
138     topBox.add(buttonsBox);
139     topBox.add(Box.createHorizontalGlue());
140 
141     memberPRsTableModel = new MemberPRsTableModel();
142     memberPRsTable = new XJTable(memberPRsTableModel);
143     memberPRsTable.setSortable(false);
144     memberPRsTable.setDefaultRenderer(ProcessingResource.class,
145                                       new ResourceRenderer());
146     memberPRsTable.setDefaultRenderer(JLabel.class, new LabelRenderer());
147 //    memberPRsTable.setIntercellSpacing(new Dimension(5, 5));
148 
149     final int width2 = new JLabel("Selected Processing resources").
150                            getPreferredSize().width + 10;
151     scroller = new JScrollPane(){
152       public Dimension getPreferredSize(){
153         Dimension dim = super.getPreferredSize();
154         dim.width = Math.max(dim.width, width2);
155         return dim;
156       }
157     };
158     scroller.getViewport().setView(memberPRsTable);
159     scroller.setBorder(BorderFactory.
160                        createTitledBorder(BorderFactory.createEtchedBorder(),
161                                           " Selected Processing resources "));
162 
163 
164     topBox.add(scroller);
165 
166     moveUpButton = new JButton(MainFrame.getIcon("moveup.gif"));
167     moveDownButton = new JButton(MainFrame.getIcon("movedown.gif"));
168 
169     buttonsBox =Box.createVerticalBox();
170     buttonsBox.add(Box.createVerticalGlue());
171     buttonsBox.add(moveUpButton);
172     buttonsBox.add(Box.createVerticalStrut(5));
173     buttonsBox.add(moveDownButton);
174     buttonsBox.add(Box.createVerticalGlue());
175 
176     topBox.add(buttonsBox);
177     topBox.add(Box.createHorizontalGlue());
178 
179     add(topBox);
180 
181     if(conditionalMode){
182       strategyPanel = new JPanel();
183       strategyPanel.setLayout(new BoxLayout(strategyPanel, BoxLayout.X_AXIS));
184       strategyPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
185       runBtnGrp = new ButtonGroup();
186       yes_RunRBtn = new JRadioButton("Yes", true);
187       yes_RunRBtn.setHorizontalTextPosition(AbstractButton.LEFT);
188       runBtnGrp.add(yes_RunRBtn);
189       no_RunRBtn = new JRadioButton("No", false);
190       no_RunRBtn.setHorizontalTextPosition(AbstractButton.LEFT);
191       runBtnGrp.add(no_RunRBtn);
192       conditional_RunRBtn = new JRadioButton("If value of feature", false);
193       conditional_RunRBtn.setHorizontalTextPosition(AbstractButton.LEFT);
194       runBtnGrp.add(conditional_RunRBtn);
195 
196       featureNameTextField = new JTextField("", 25);
197       featureNameTextField.setMaximumSize(
198                            new Dimension(Integer.MAX_VALUE,
199                                          featureNameTextField.getPreferredSize().
200                                          height));
201       featureValueTextField = new JTextField("", 25);
202       featureValueTextField.setMaximumSize(
203                            new Dimension(Integer.MAX_VALUE,
204                                          featureValueTextField.getPreferredSize().
205                                          height));
206 
207       strategyPanel.add(new JLabel(MainFrame.getIcon("greenBall.gif")));
208       strategyPanel.add(yes_RunRBtn);
209       strategyPanel.add(Box.createHorizontalStrut(5));
210 
211       strategyPanel.add(new JLabel(MainFrame.getIcon("redBall.gif")));
212       strategyPanel.add(no_RunRBtn);
213       strategyPanel.add(Box.createHorizontalStrut(5));
214 
215       strategyPanel.add(new JLabel(MainFrame.getIcon("yellowBall.gif")));
216       strategyPanel.add(conditional_RunRBtn);
217       strategyPanel.add(Box.createHorizontalStrut(5));
218 
219       strategyPanel.add(featureNameTextField);
220       strategyPanel.add(Box.createHorizontalStrut(5));
221       strategyPanel.add(new JLabel("is"));
222       strategyPanel.add(Box.createHorizontalStrut(5));
223       strategyPanel.add(featureValueTextField);
224       strategyPanel.add(Box.createHorizontalStrut(5));
225       strategyBorder = BorderFactory.createTitledBorder(
226           BorderFactory.createEtchedBorder(),
227           " No processing resource selected... ");
228       strategyPanel.setBorder(strategyBorder);
229 
230       add(strategyPanel);
231     }//if conditional mode
232     if(analyserMode){
233       //we need to add the corpus combo
234       corpusCombo = new JComboBox(corpusComboModel = new CorporaComboModel());
235       corpusCombo.setRenderer(new ResourceRenderer());
236       corpusCombo.setMaximumSize(new Dimension(Integer.MAX_VALUE,
237                                                corpusCombo.getPreferredSize().
238                                                height));
239       Corpus corpus = null;
240       if(controller instanceof SerialAnalyserController){
241         corpus = ((SerialAnalyserController)controller).getCorpus();
242       }else if(controller instanceof ConditionalSerialAnalyserController){
243         corpus = ((ConditionalSerialAnalyserController)controller).getCorpus();
244       }else{
245         throw new GateRuntimeException("Controller editor in analyser mode " +
246                                        "but the target controller is not an " +
247                                        "analyser!");
248       }
249 
250       if(corpus != null){
251         corpusCombo.setSelectedItem(corpus);
252       }else{
253         if(corpusCombo.getModel().getSize() > 1) corpusCombo.setSelectedIndex(1);
254         else corpusCombo.setSelectedIndex(0);
255       }
256       JPanel horBox = new JPanel();
257       horBox.setLayout(new BoxLayout(horBox, BoxLayout.X_AXIS));
258       horBox.setAlignmentX(Component.LEFT_ALIGNMENT);
259       horBox.add(new JLabel("Corpus:"));
260       horBox.add(Box.createHorizontalStrut(5));
261       horBox.add(corpusCombo);
262       horBox.add(Box.createHorizontalStrut(5));
263       horBox.add(Box.createHorizontalGlue());
264       add(horBox);
265       JLabel warningLbl = new JLabel(
266         "<HTML>The <b>corpus</b> and <b>document</b> parameters are not " +
267         "available as they are automatically set by the controller!</HTML>");
268       warningLbl.setAlignmentX(java.awt.Component.LEFT_ALIGNMENT);
269       add(warningLbl);
270     }
271 
272     parametersPanel = new JPanel();
273     parametersPanel.setLayout(new BoxLayout(parametersPanel, BoxLayout.Y_AXIS));
274     parametersPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
275     parametersBorder = BorderFactory.createTitledBorder(
276                                       BorderFactory.createEtchedBorder(),
277                                       " No selected processing resource ");
278     parametersPanel.setBorder(parametersBorder);
279     parametersEditor = new ResourceParametersEditor();
280     parametersEditor.init(null, null);
281     parametersPanel.add(new JScrollPane(parametersEditor));
282     add(Box.createVerticalStrut(5));
283     add(parametersPanel);
284 
285 
286     add(Box.createVerticalStrut(5));
287     add(Box.createVerticalGlue());
288     JPanel horBox = new JPanel();
289     horBox.setLayout(new BoxLayout(horBox, BoxLayout.X_AXIS));
290     horBox.setAlignmentX(Component.LEFT_ALIGNMENT);
291     horBox.add(Box.createHorizontalGlue());
292     horBox.add(new JButton(runAction));
293     horBox.add(Box.createHorizontalStrut(10));
294     add(horBox);
295     add(Box.createVerticalStrut(10));
296 
297     addMenu = new JMenu("Add");
298     removeMenu = new JMenu("Remove");
299   }// initGuiComponents()
300 
301   protected void initListeners() {
302     Gate.getCreoleRegister().addCreoleListener(this);
303 
304     this.addMouseListener(new MouseAdapter() {
305       public void mouseClicked(MouseEvent e) {
306         if(SwingUtilities.isRightMouseButton(e)){
307           if(handle != null && handle.getPopup()!= null)
308             handle.getPopup().show(SerialControllerEditor.this, e.getX(), e.getY());
309         }
310       }
311     });
312 
313     addButon.addActionListener(new ActionListener() {
314       public void actionPerformed(ActionEvent e) {
315         int rows[] = loadedPRsTable.getSelectedRows();
316         if(rows == null || rows.length == 0){
317           JOptionPane.showMessageDialog(
318               SerialControllerEditor.this,
319               "Please select some components from the list of available components!\n" ,
320               "Gate", JOptionPane.ERROR_MESSAGE);
321         } else {
322           List actions = new ArrayList();
323           for(int i = 0; i < rows.length; i++) {
324             Action act =(Action)new AddPRAction((ProcessingResource)
325                                      loadedPRsTable.getValueAt(rows[i], 0));
326             if(act != null) actions.add(act);
327           }
328           Iterator actIter = actions.iterator();
329           while(actIter.hasNext()){
330             ((Action)actIter.next()).actionPerformed(null);
331           }
332         }
333       }
334     });
335 
336     removeButton.addActionListener(new ActionListener() {
337       public void actionPerformed(ActionEvent e) {
338         int rows[] = memberPRsTable.getSelectedRows();
339         if(rows == null || rows.length == 0){
340           JOptionPane.showMessageDialog(
341               SerialControllerEditor.this,
342               "Please select some components to be removed "+
343               "from the list of used components!\n" ,
344               "Gate", JOptionPane.ERROR_MESSAGE);
345         } else {
346           List actions = new ArrayList();
347           for(int i = 0; i < rows.length; i++){
348             Action act =(Action)new RemovePRAction((ProcessingResource)
349                                      memberPRsTable.getValueAt(rows[i], 1));
350             if(act != null) actions.add(act);
351           }
352           Iterator actIter = actions.iterator();
353           while(actIter.hasNext()){
354             ((Action)actIter.next()).actionPerformed(null);
355           }
356         }// else
357       }//  public void actionPerformed(ActionEvent e)
358     });
359 
360     moveUpButton.addActionListener(new ActionListener() {
361       public void actionPerformed(ActionEvent e) {
362         int rows[] = memberPRsTable.getSelectedRows();
363         if(rows == null || rows.length == 0){
364           JOptionPane.showMessageDialog(
365               SerialControllerEditor.this,
366               "Please select some components to be moved "+
367               "from the list of used components!\n" ,
368               "Gate", JOptionPane.ERROR_MESSAGE);
369         } else {
370           //we need to make sure the rows are sorted
371           Arrays.sort(rows);
372           //get the list of PRs
373           for(int i = 0; i < rows.length; i++){
374             int row = rows[i];
375             if(row > 0){
376               //move it up
377               ProcessingResource value = controller.remove(row);
378               controller.add(row - 1, value);
379             }
380           }
381           memberPRsTableModel.fireTableDataChanged();
382           //restore selection
383           for(int i = 0; i < rows.length; i++){
384             int newRow = -1;
385             if(rows[i] > 0) newRow = rows[i] - 1;
386             else newRow = rows[i];
387             memberPRsTable.addRowSelectionInterval(newRow, newRow);
388           }
389         }
390 
391       }//public void actionPerformed(ActionEvent e)
392     });
393 
394 
395     moveDownButton.addActionListener(new ActionListener() {
396       public void actionPerformed(ActionEvent e) {
397         int rows[] = memberPRsTable.getSelectedRows();
398         if(rows == null || rows.length == 0){
399           JOptionPane.showMessageDialog(
400               SerialControllerEditor.this,
401               "Please select some components to be moved "+
402               "from the list of used components!\n" ,
403               "Gate", JOptionPane.ERROR_MESSAGE);
404         } else {
405           //we need to make sure the rows are sorted
406           Arrays.sort(rows);
407           //get the list of PRs
408           for(int i = rows.length - 1; i >= 0; i--){
409             int row = rows[i];
410             if(row < controller.getPRs().size() -1){
411               //move it down
412               ProcessingResource value = controller.remove(row);
413               controller.add(row + 1, value);
414             }
415           }
416           memberPRsTableModel.fireTableDataChanged();
417           //restore selection
418           for(int i = 0; i < rows.length; i++){
419             int newRow = -1;
420             if(rows[i] < controller.getPRs().size() - 1) newRow = rows[i] + 1;
421             else newRow = rows[i];
422             memberPRsTable.addRowSelectionInterval(newRow, newRow);
423           }
424         }
425 
426       }//public void actionPerformed(ActionEvent e)
427     });
428 
429     loadedPRsTable.addMouseListener(new MouseAdapter() {
430       public void mouseClicked(MouseEvent e) {
431         int row = loadedPRsTable.rowAtPoint(e.getPoint());
432         //load modules on double click
433         ProcessingResource pr = (ProcessingResource)
434                                 loadedPRsTableModel.getValueAt(row, 0);
435         if(SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2){
436           new AddPRAction(pr).actionPerformed(null);
437         }else if(SwingUtilities.isRightMouseButton(e)){
438             JPopupMenu popup = new JPopupMenu();
439             popup.add(new AddPRAction(pr){
440               {
441                 putValue(NAME, "Add \"" + this.pr.getName() +
442                                "\" to the \"" + controller.getName() +
443                                "\" application");
444               }
445             });
446             popup.show(loadedPRsTable, e.getPoint().x, e.getPoint().y);
447           }
448       }
449 
450       public void mousePressed(MouseEvent e) {
451       }
452 
453       public void mouseReleased(MouseEvent e) {
454       }
455 
456       public void mouseEntered(MouseEvent e) {
457       }
458 
459       public void mouseExited(MouseEvent e) {
460       }
461     });
462 
463     memberPRsTable.addMouseListener(new MouseAdapter() {
464       public void mouseClicked(MouseEvent e) {
465         final int row = memberPRsTable.rowAtPoint(e.getPoint());
466         if(row != -1){
467           //edit parameters on click
468           if(SwingUtilities.isLeftMouseButton(e) /*&& e.getClickCount() == 2*/){
469             ProcessingResource pr = (ProcessingResource)
470                                     memberPRsTableModel.getValueAt(row, 1);
471             selectPR(row);
472           }else if(SwingUtilities.isRightMouseButton(e)){
473             JPopupMenu popup = new JPopupMenu();
474             popup.add(new AbstractAction("Edit parameters"){
475               public void actionPerformed(ActionEvent e){
476                 ProcessingResource pr = (ProcessingResource)
477                                         memberPRsTableModel.getValueAt(row, 1);
478                 selectPR(row);
479               }
480             });
481             popup.show(memberPRsTable, e.getPoint().x, e.getPoint().y);
482           }
483         }
484       }
485 
486       public void mousePressed(MouseEvent e) {
487       }
488 
489       public void mouseReleased(MouseEvent e) {
490       }
491 
492       public void mouseEntered(MouseEvent e) {
493       }
494 
495       public void mouseExited(MouseEvent e) {
496       }
497     });
498 
499     addMenu.addMenuListener(new MenuListener() {
500       public void menuCanceled(MenuEvent e) {
501 
502       }
503 
504       public void menuDeselected(MenuEvent e) {
505       }
506 
507       public void menuSelected(MenuEvent e) {
508         buildInternalMenus();
509       }
510     });
511 
512     removeMenu.addMenuListener(new MenuListener() {
513       public void menuCanceled(MenuEvent e) {
514       }
515 
516       public void menuDeselected(MenuEvent e) {
517       }
518 
519       public void menuSelected(MenuEvent e) {
520         buildInternalMenus();
521       }
522     });
523 
524     if(conditionalMode){
525       final ActionListener executionModeActionListener = new ActionListener() {
526         public void actionPerformed(ActionEvent e) {
527           if(selectedPRRunStrategy != null &&
528              selectedPRRunStrategy instanceof AnalyserRunningStrategy){
529             AnalyserRunningStrategy strategy =
530               (AnalyserRunningStrategy)selectedPRRunStrategy;
531             if(yes_RunRBtn.isSelected()){
532               strategy.setRunMode(RunningStrategy.RUN_ALWAYS);
533               featureNameTextField.setEditable(false);
534               featureValueTextField.setEditable(false);
535             }else if(no_RunRBtn.isSelected()){
536               strategy.setRunMode(RunningStrategy.RUN_NEVER);
537               featureNameTextField.setEditable(false);
538               featureValueTextField.setEditable(false);
539             }else if(conditional_RunRBtn.isSelected()){
540               strategy.setRunMode(RunningStrategy.RUN_CONDITIONAL);
541               featureNameTextField.setEditable(true);
542               featureValueTextField.setEditable(true);
543 
544               String str = featureNameTextField.getText();
545               strategy.setFeatureName(str == null || str.length()==0 ?
546                                       null : str);
547               str = featureValueTextField.getText();
548               strategy.setFeatureValue(str == null || str.length()==0 ?
549                                       null : str);
550             }
551           }
552           memberPRsTable.repaint();
553         }
554       };
555 
556       yes_RunRBtn.addActionListener(executionModeActionListener);
557 
558       no_RunRBtn.addActionListener(executionModeActionListener);
559 
560       conditional_RunRBtn.addActionListener(executionModeActionListener);
561 
562       featureNameTextField.getDocument().addDocumentListener(
563       new javax.swing.event.DocumentListener() {
564         public void insertUpdate(javax.swing.event.DocumentEvent e) {
565           changeOccured(e);
566         }
567 
568         public void removeUpdate(javax.swing.event.DocumentEvent e) {
569           changeOccured(e);
570         }
571 
572         public void changedUpdate(javax.swing.event.DocumentEvent e) {
573           changeOccured(e);
574         }
575 
576         protected void changeOccured(javax.swing.event.DocumentEvent e){
577           if(selectedPRRunStrategy != null &&
578              selectedPRRunStrategy instanceof AnalyserRunningStrategy){
579             AnalyserRunningStrategy strategy =
580               (AnalyserRunningStrategy)selectedPRRunStrategy;
581             strategy.setFeatureName(featureNameTextField.getText());
582           }
583         }
584       });
585 
586       featureValueTextField.getDocument().addDocumentListener(
587       new javax.swing.event.DocumentListener() {
588         public void insertUpdate(javax.swing.event.DocumentEvent e) {
589           changeOccured(e);
590         }
591 
592         public void removeUpdate(javax.swing.event.DocumentEvent e) {
593           changeOccured(e);
594         }
595 
596         public void changedUpdate(javax.swing.event.DocumentEvent e) {
597           changeOccured(e);
598         }
599 
600         protected void changeOccured(javax.swing.event.DocumentEvent e){
601           if(selectedPRRunStrategy != null &&
602              selectedPRRunStrategy instanceof AnalyserRunningStrategy){
603             AnalyserRunningStrategy strategy =
604               (AnalyserRunningStrategy)selectedPRRunStrategy;
605             strategy.setFeatureValue(featureValueTextField.getText());
606           }
607         }
608       });
609     }//if conditional
610   }//protected void initListeners()
611 
612   /**
613    * Cleans the internal data and prepares this object to be collected
614    */
615   public void cleanup(){
616     Gate.getCreoleRegister().removeCreoleListener(this);
617     controller = null;
618     progressListeners.clear();
619     statusListeners.clear();
620     parametersEditor.cleanup();
621     addMenu.removeAll();
622     removeMenu.removeAll();
623     handle = null;
624   }
625 
626   protected void buildInternalMenus(){
627     addMenu.removeAll();
628     Iterator prIter = Gate.getCreoleRegister().getPrInstances().iterator();
629     while(prIter.hasNext()){
630       ProcessingResource pr = (ProcessingResource)prIter.next();
631       if(Gate.getHiddenAttribute(pr.getFeatures())){
632         //ignore this resource
633       }else{
634         Action act = new AddPRAction(pr);
635         if(act.isEnabled()) addMenu.add(act);
636       }
637     }// while
638 
639     removeMenu.removeAll();
640     prIter = Gate.getCreoleRegister().getPrInstances().iterator();
641     while(prIter.hasNext()){
642       ProcessingResource pr = (ProcessingResource)prIter.next();
643       if(Gate.getHiddenAttribute(pr.getFeatures())){
644         //ignore this resource
645       }else{
646         Action act = new RemovePRAction(pr);
647         if(act.isEnabled()) removeMenu.add(act);
648       }
649     }// while
650   }
651 
652   /**
653    * Called when a PR has been selected in the memeber PRs table;
654    * @param pr
655    */
656   protected void selectPR(int index){
657     ProcessingResource pr = (ProcessingResource)
658                             ((java.util.List)controller.getPRs()).get(index);
659     showParamsEditor(pr);
660     selectedPR = pr;
661     if(conditionalMode){
662       strategyBorder.setTitle(" Run \"" + pr.getName() + "\"? ");
663       //update the state of the run strategy buttons
664       selectedPRRunStrategy = (RunningStrategy)
665                                  ((List)((ConditionalController)controller).
666                                           getRunningStrategies()).get(index);
667       int runMode = selectedPRRunStrategy.getRunMode();
668 
669       if(selectedPRRunStrategy instanceof AnalyserRunningStrategy){
670         yes_RunRBtn.setEnabled(true);
671         no_RunRBtn.setEnabled(true);
672         conditional_RunRBtn.setEnabled(true);
673 
674         featureNameTextField.setText(
675               ((AnalyserRunningStrategy)selectedPRRunStrategy).
676               getFeatureName());
677         featureValueTextField.setText(
678               ((AnalyserRunningStrategy)selectedPRRunStrategy).
679               getFeatureValue());
680       }else{
681         yes_RunRBtn.setEnabled(false);
682         no_RunRBtn.setEnabled(false);
683         conditional_RunRBtn.setEnabled(false);
684 
685         featureNameTextField.setText("");
686         featureValueTextField.setText("");
687       }
688 
689       featureNameTextField.setEditable(false);
690       featureValueTextField.setEditable(false);
691 
692       switch(selectedPRRunStrategy.getRunMode()){
693         case RunningStrategy.RUN_ALWAYS:{
694           yes_RunRBtn.setSelected(true);
695           break;
696         }
697 
698         case RunningStrategy.RUN_NEVER:{
699           no_RunRBtn.setSelected(true);
700           break;
701         }
702 
703         case RunningStrategy.RUN_CONDITIONAL:{
704           conditional_RunRBtn.setSelected(true);
705           if(selectedPRRunStrategy instanceof AnalyserRunningStrategy){
706             featureNameTextField.setEditable(true);
707             featureValueTextField.setEditable(true);
708           }
709           break;
710         }
711       }//switch
712     }
713   }
714 
715   /**
716    * Stops the current edits for parameters; sets the paarmeters for the
717    * resource currently being edited and diplays the editor for the new
718    * resource
719    * @param pr the new resource
720    */
721   protected void showParamsEditor(ProcessingResource pr){
722     try{
723       if(parametersEditor.getResource() != null) parametersEditor.setParameters();
724     }catch(ResourceInstantiationException rie){
725       JOptionPane.showMessageDialog(
726           SerialControllerEditor.this,
727           "Failed to set parameters for \"" + pr.getName() +"\"!\n" ,
728           "Gate", JOptionPane.ERROR_MESSAGE);
729       rie.printStackTrace(Err.getPrintWriter());
730     }
731 
732     if(pr != null){
733       ResourceData rData = (ResourceData)Gate.getCreoleRegister().
734                                          get(pr.getClass().getName());
735 
736       parametersBorder.setTitle(" Parameters for the \"" + pr.getName() +
737                                 "\" " + rData.getName() + " ");
738 
739       //this is a list of lists
740       List parameters = rData.getParameterList().getRuntimeParameters();
741 
742       if(analyserMode){
743         //remove corpus and document
744         //create a new list so we don't change the one from CreoleReg.
745         List newParameters = new ArrayList();
746         Iterator pDisjIter = parameters.iterator();
747         while(pDisjIter.hasNext()){
748           List aDisjunction = (List)pDisjIter.next();
749           List newDisjunction = new ArrayList(aDisjunction);
750           Iterator internalParIter = newDisjunction.iterator();
751           while(internalParIter.hasNext()){
752             Parameter parameter = (Parameter)internalParIter.next();
753             if(parameter.getName().equals("corpus") ||
754                parameter.getName().equals("document")) internalParIter.remove();
755           }
756           if(!newDisjunction.isEmpty()) newParameters.add(newDisjunction);
757         }
758         parametersEditor.init(pr, newParameters);
759       }else{
760         parametersEditor.init(pr, parameters);
761       }
762     }else{
763       parametersBorder.setTitle("No selected processing resource");
764       parametersEditor.init(null, null);
765     }
766     SerialControllerEditor.this.validate();
767     SerialControllerEditor.this.repaint(100);
768   }
769 
770   //CreoleListener implementation
771   public void resourceLoaded(CreoleEvent e) {
772     if(Gate.getHiddenAttribute(e.getResource().getFeatures())) return;
773     if(e.getResource() instanceof ProcessingResource){
774       loadedPRsTableModel.fireTableDataChanged();
775       memberPRsTableModel.fireTableDataChanged();
776       repaint(100);
777     }else if(e.getResource() instanceof LanguageResource){
778       if(e.getResource() instanceof Corpus && analyserMode){
779         corpusComboModel.fireDataChanged();
780       }
781     }
782   }// public void resourceLoaded
783 
784   public void resourceUnloaded(CreoleEvent e) {
785     if(Gate.getHiddenAttribute(e.getResource().getFeatures())) return;
786     if(e.getResource() instanceof ProcessingResource){
787       ProcessingResource pr = (ProcessingResource)e.getResource();
788       if(controller.getPRs().contains(pr)){
789         new RemovePRAction(pr).actionPerformed(null);
790       }
791       loadedPRsTableModel.fireTableDataChanged();
792       memberPRsTableModel.fireTableDataChanged();
793       repaint(100);
794     }
795   }//public void resourceUnloaded(CreoleEvent e)
796 
797   public void resourceRenamed(Resource resource, String oldName,
798                               String newName){
799     if(Gate.getHiddenAttribute(resource.getFeatures())) return;
800     if(resource instanceof ProcessingResource){
801       repaint(100);
802     }
803   }
804 
805   public void datastoreOpened(CreoleEvent e) {
806   }
807   public void datastoreCreated(CreoleEvent e) {
808   }
809   public void datastoreClosed(CreoleEvent e) {
810   }
811   public synchronized void removeStatusListener(StatusListener l) {
812     if (statusListeners != null && statusListeners.contains(l)) {
813       Vector v = (Vector) statusListeners.clone();
814       v.removeElement(l);
815       statusListeners = v;
816     }
817   }
818   public synchronized void addStatusListener(StatusListener l) {
819     Vector v = statusListeners == null ? new Vector(2) :
820                                   (Vector) statusListeners.clone();
821     if (!v.contains(l)) {
822       v.addElement(l);
823       statusListeners = v;
824     }
825   }
826 
827 
828 
829   /**
830    * Table model for all the loaded processing resources that are not part of
831    * the controller.
832    */
833   class LoadedPRsTableModel extends AbstractTableModel{
834     public int getRowCount(){
835       List loadedPRs = new ArrayList(Gate.getCreoleRegister().getPrInstances());
836       loadedPRs.removeAll(controller.getPRs());
837       Iterator prsIter = loadedPRs.iterator();
838       while(prsIter.hasNext()){
839         ProcessingResource aPR = (ProcessingResource)prsIter.next();
840         if(Gate.getHiddenAttribute(aPR.getFeatures())) prsIter.remove();
841       }
842 
843       return loadedPRs.size();
844     }
845 
846     public Object getValueAt(int row, int column){
847       List loadedPRs = new ArrayList(Gate.getCreoleRegister().getPrInstances());
848       loadedPRs.removeAll(controller.getPRs());
849       Iterator prsIter = loadedPRs.iterator();
850       while(prsIter.hasNext()){
851         ProcessingResource aPR = (ProcessingResource)prsIter.next();
852         if(Gate.getHiddenAttribute(aPR.getFeatures())) prsIter.remove();
853       }
854 
855       Collections.sort(loadedPRs, nameComparator);
856       ProcessingResource pr = (ProcessingResource)loadedPRs.get(row);
857       switch(column){
858         case 0 : return pr;
859         case 1 : {
860           ResourceData rData = (ResourceData)Gate.getCreoleRegister().
861                                     get(pr.getClass().getName());
862           if(rData == null) return pr.getClass();
863           else return rData.getName();
864         }
865         default: return null;
866       }
867     }
868 
869     public int getColumnCount(){
870       return 2;
871     }
872 
873     public String getColumnName(int columnIndex){
874       switch(columnIndex){
875         case 0 : return "Name";
876         case 1 : return "Type";
877         default: return "?";
878       }
879     }
880 
881     public Class getColumnClass(int columnIndex){
882       switch(columnIndex){
883         case 0 : return ProcessingResource.class;
884         case 1 : return String.class;
885         default: return Object.class;
886       }
887     }
888 
889     public boolean isCellEditable(int rowIndex, int columnIndex){
890       return false;
891     }
892 
893     public void setValueAt(Object aValue, int rowIndex, int columnIndex){
894     }
895     NameComparator nameComparator = new NameComparator();
896   }//protected class LoadedPRsTableModel extends AbstractTableModel
897 
898   /**
899    * A model for a combobox containing the loaded corpora in the system
900    */
901   protected class CorporaComboModel extends AbstractListModel
902                                   implements ComboBoxModel{
903     public int getSize(){
904       //get all corpora regardless of their actual type
905       java.util.List loadedCorpora = null;
906       try{
907         loadedCorpora = Gate.getCreoleRegister().
908                                getAllInstances("gate.Corpus");
909       }catch(GateException ge){
910         ge.printStackTrace(Err.getPrintWriter());
911       }
912 
913       return loadedCorpora == null ? 1 : loadedCorpora.size() + 1;
914     }
915 
916     public Object getElementAt(int index){
917       if(index == 0) return "<none>";
918       else{
919         //get all corpora regardless of their actual type
920         java.util.List loadedCorpora = null;
921         try{
922           loadedCorpora = Gate.getCreoleRegister().
923                                  getAllInstances("gate.Corpus");
924         }catch(GateException ge){
925           ge.printStackTrace(Err.getPrintWriter());
926         }
927         return loadedCorpora == null? "" : loadedCorpora.get(index - 1);
928       }
929     }
930 
931     //use the controller for data caching
932     public void setSelectedItem(Object anItem){
933       if(controller instanceof SerialAnalyserController)
934       ((SerialAnalyserController)controller).
935         setCorpus((Corpus)(anItem.equals("<none>") ? null : anItem));
936       else if(controller instanceof ConditionalSerialAnalyserController)
937       ((ConditionalSerialAnalyserController)controller).
938         setCorpus((Corpus)(anItem.equals("<none>") ? null : anItem));
939     }
940 
941     public Object getSelectedItem(){
942       Corpus corpus = null;
943       if(controller instanceof SerialAnalyserController){
944         corpus = ((SerialAnalyserController)controller).getCorpus();
945       }else if(controller instanceof ConditionalSerialAnalyserController){
946         corpus = ((ConditionalSerialAnalyserController)controller).getCorpus();
947       }else{
948         throw new GateRuntimeException("Controller editor in analyser mode " +
949                                        "but the target controller is not an " +
950                                        "analyser!");
951       }
952       return (corpus == null ? (Object)"<none>" : (Object)corpus);
953     }
954 
955     void fireDataChanged(){
956       fireContentsChanged(this, 0, getSize());
957     }
958 
959     Object selectedItem = null;
960   }
961 
962   /**
963    *  Renders JLabel by simply displaying them
964    */
965   class LabelRenderer implements TableCellRenderer{
966     public Component getTableCellRendererComponent(JTable table,
967                                                    Object value,
968                                                    boolean isSelected,
969                                                    boolean hasFocus,
970                                                    int row,
971                                                    int column){
972       return (JLabel) value;
973     }
974   }
975 
976   /**
977    * Table model for all the processing resources in the controller.
978    */
979   class MemberPRsTableModel extends AbstractTableModel{
980     MemberPRsTableModel(){
981       green = new JLabel(MainFrame.getIcon("greenBall.gif"));
982       red = new JLabel(MainFrame.getIcon("redBall.gif"));
983       yellow = new JLabel(MainFrame.getIcon("yellowBall.gif"));
984     }
985     public int getRowCount(){
986       return controller.getPRs().size();
987     }
988 
989     public Object getValueAt(int row, int column){
990       ProcessingResource pr = (ProcessingResource)
991                               ((List)controller.getPRs()).get(row);
992       switch(column){
993         case 0 : {
994           if(conditionalMode){
995             RunningStrategy strategy = (RunningStrategy)
996                                  ((List)((ConditionalController)controller).
997                                           getRunningStrategies()).get(row);
998             switch(strategy.getRunMode()){
999               case RunningStrategy.RUN_ALWAYS : return green;
1000              case RunningStrategy.RUN_NEVER : return red;
1001              case RunningStrategy.RUN_CONDITIONAL : return yellow;
1002            }
1003          }
1004          return green;
1005        }
1006        case 1 : return pr;
1007        case 2 : {
1008          ResourceData rData = (ResourceData)Gate.getCreoleRegister().
1009                                    get(pr.getClass().getName());
1010          if(rData == null) return pr.getClass();
1011          else return rData.getName();
1012        }
1013        default: return null;
1014      }
1015    }
1016
1017    public int getColumnCount(){
1018      return 3;
1019    }
1020
1021    public String getColumnName(int columnIndex){
1022      switch(columnIndex){
1023        case 0 : return "!";
1024        case 1 : return "Name";
1025//        case 1 : return "!";
1026        case 2 : return "Type";
1027        default: return "?";
1028      }
1029    }
1030
1031    public Class getColumnClass(int columnIndex){
1032      switch(columnIndex){
1033        case 0 : return JLabel.class;
1034        case 1 : return ProcessingResource.class;
1035//        case 1 : return Boolean.class;
1036        case 2 : return String.class;
1037        default: return Object.class;
1038      }
1039    }
1040
1041    public boolean isCellEditable(int rowIndex, int columnIndex){
1042      return false;
1043    }
1044
1045    public void setValueAt(Object aValue, int rowIndex, int columnIndex){
1046    }
1047
1048    protected JLabel green, red, yellow;
1049  }//protected class MemeberPRsTableModel extends AbstractTableModel
1050
1051  /** Adds a PR to the controller*/
1052  class AddPRAction extends AbstractAction {
1053    AddPRAction(ProcessingResource aPR){
1054      super(aPR.getName());
1055      this.pr = aPR;
1056      setEnabled(!controller.getPRs().contains(aPR));
1057    }
1058
1059    public void actionPerformed(ActionEvent e){
1060      controller.add(pr);
1061      loadedPRsTableModel.fireTableDataChanged();
1062      memberPRsTableModel.fireTableDataChanged();
1063      SerialControllerEditor.this.validate();
1064      SerialControllerEditor.this.repaint(100);
1065    }
1066
1067    ProcessingResource pr;
1068  }
1069
1070  /** Removes a PR from the controller*/
1071  class RemovePRAction extends AbstractAction {
1072    RemovePRAction(ProcessingResource pr){
1073      super(pr.getName());
1074      this.pr = pr;
1075      setEnabled(controller.getPRs().contains(pr));
1076    }
1077
1078    public void actionPerformed(ActionEvent e){
1079      if(controller.remove(pr)){
1080        loadedPRsTableModel.fireTableDataChanged();
1081        memberPRsTableModel.fireTableDataChanged();
1082        if(parametersEditor.getResource() == pr){
1083          parametersEditor.init(null, null);
1084          parametersBorder.setTitle("No selected processing resource");
1085        }
1086        SerialControllerEditor.this.validate();
1087        SerialControllerEditor.this.repaint(100);
1088      }
1089    }
1090
1091    ProcessingResource pr;
1092  }
1093
1094
1095  /** Runs the Application*/
1096  class RunAction extends AbstractAction {
1097    RunAction(){
1098      super("Run");
1099    }
1100
1101    public void actionPerformed(ActionEvent e){
1102      Runnable runnable = new Runnable(){
1103        public void run(){
1104          //stop editing the parameters
1105          try{
1106            parametersEditor.setParameters();
1107          }catch(ResourceInstantiationException rie){
1108            JOptionPane.showMessageDialog(
1109              SerialControllerEditor.this,
1110              "Could not set parameters for the \"" +
1111              parametersEditor.getResource().getName() +
1112              "\" processing resource:\nSee \"Messages\" tab for details!",
1113              "Gate", JOptionPane.ERROR_MESSAGE);
1114              rie.printStackTrace(Err.getPrintWriter());
1115              return;
1116          }
1117
1118          if(analyserMode){
1119            //set the corpus
1120            Object value = corpusCombo.getSelectedItem();
1121            Corpus corpus = value.equals("<none>") ? null : (Corpus)value;
1122            if(corpus == null){
1123              JOptionPane.showMessageDialog(
1124                SerialControllerEditor.this,
1125                "No corpus provided!\n" +
1126                "Please select a corpus and try again!",
1127                "Gate", JOptionPane.ERROR_MESSAGE);
1128              return;
1129            }
1130            if(controller instanceof SerialAnalyserController)
1131              ((SerialAnalyserController)controller).setCorpus(corpus);
1132            else if(controller instanceof ConditionalSerialAnalyserController)
1133              ((ConditionalSerialAnalyserController)controller).setCorpus(corpus);
1134          }
1135          //check the runtime parameters
1136          List badPRs;
1137          try{
1138            badPRs = controller.getOffendingPocessingResources();
1139          }catch(ResourceInstantiationException rie){
1140            JOptionPane.showMessageDialog(
1141              SerialControllerEditor.this,
1142              "Could not check runtime parameters for " +
1143              "the processing resources:\n" + rie.toString(),
1144              "Gate", JOptionPane.ERROR_MESSAGE);
1145            return;
1146          }
1147          if(badPRs != null && !badPRs.isEmpty()){
1148            //we know what PRs have problems so it would be nice to show
1149            //them in red or something
1150            JOptionPane.showMessageDialog(
1151              SerialControllerEditor.this,
1152              "Some required runtime parameters are not set!",
1153              "Gate", JOptionPane.ERROR_MESSAGE);
1154            return;
1155          }
1156
1157          //set the listeners
1158          StatusListener sListener = new InternalStatusListener();
1159          ProgressListener pListener = new InternalProgressListener();
1160
1161          controller.addStatusListener(sListener);
1162          controller.addProgressListener(pListener);
1163
1164          Gate.setExecutable(controller);
1165
1166          MainFrame.lockGUI("Running " + controller.getName() + "...");
1167          //execute the thing
1168          long startTime = System.currentTimeMillis();
1169          fireStatusChanged("Running " +
1170                            controller.getName());
1171          fireProgressChanged(0);
1172
1173          try {
1174            controller.execute();
1175          }catch(ExecutionInterruptedException eie){
1176            MainFrame.unlockGUI();
1177            JOptionPane.showMessageDialog(
1178              SerialControllerEditor.this,
1179              "Interrupted!\n" + eie.toString(),
1180              "Gate", JOptionPane.ERROR_MESSAGE);
1181          }catch(ExecutionException ee) {
1182            ee.printStackTrace(Err.getPrintWriter());
1183            MainFrame.unlockGUI();
1184            JOptionPane.showMessageDialog(
1185              SerialControllerEditor.this,
1186              "Execution error while running \"" + controller.getName() +
1187              "\" :\nSee \"Messages\" tab for details!",
1188              "Gate", JOptionPane.ERROR_MESSAGE);
1189          }catch(Exception e){
1190            MainFrame.unlockGUI();
1191            JOptionPane.showMessageDialog(SerialControllerEditor.this,
1192                                          "Unhandled execution error!\n " +
1193                                          "See \"Messages\" tab for details!",
1194                                          "Gate", JOptionPane.ERROR_MESSAGE);
1195            e.printStackTrace(Err.getPrintWriter());
1196          }finally{
1197            MainFrame.unlockGUI();
1198            Gate.setExecutable(null);
1199          }//catch
1200
1201          //remove the listeners
1202          controller.removeStatusListener(sListener);
1203          controller.removeProgressListener(pListener);
1204
1205          long endTime = System.currentTimeMillis();
1206          fireProcessFinished();
1207          fireStatusChanged(controller.getName() +
1208                            " run in " +
1209                            NumberFormat.getInstance().format(
1210                            (double)(endTime - startTime) / 1000) + " seconds");
1211        }
1212      };
1213      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1214                                 runnable,
1215                                 "ApplicationViewer1");
1216      thread.setPriority(Thread.MIN_PRIORITY);
1217      thread.start();
1218    }//public void actionPerformed(ActionEvent e)
1219  }//class RunAction
1220
1221  /**
1222   * A simple progress listener used to forward the events upstream.
1223   */
1224  protected class InternalProgressListener implements ProgressListener{
1225    public void progressChanged(int i){
1226      fireProgressChanged(i);
1227    }
1228
1229    public void processFinished(){
1230      fireProcessFinished();
1231    }
1232  }//InternalProgressListener
1233
1234  /**
1235   * A simple status listener used to forward the events upstream.
1236   */
1237  protected class InternalStatusListener implements StatusListener{
1238    public void statusChanged(String message){
1239      fireStatusChanged(message);
1240    }
1241  }//InternalStatusListener
1242
1243  /** The controller this editor edits */
1244  SerialController controller;
1245
1246  /** The {@link Handle} that created this view */
1247  Handle handle;
1248
1249  /**
1250   * Contains all the PRs loaded in the sytem that are not already part of the
1251   * serial controller
1252   */
1253  XJTable loadedPRsTable;
1254
1255  /**
1256   * model for the {@link loadedPRsTable} JTable.
1257   */
1258  LoadedPRsTableModel loadedPRsTableModel;
1259
1260  /**
1261   * Displays the PRs in the controller
1262   */
1263  XJTable memberPRsTable;
1264
1265  /** model for {@link memberPRsTable}*/
1266  MemberPRsTableModel memberPRsTableModel;
1267
1268  /** Adds one or more PR(s) to the controller*/
1269  JButton addButon;
1270
1271  /** Removes one or more PR(s) from the controller*/
1272  JButton removeButton;
1273
1274  /** Moves the module up in the controller list*/
1275  JButton moveUpButton;
1276
1277  /** Moves the module down in the controller list*/
1278  JButton moveDownButton;
1279
1280  /** A component for editing the parameters of the currently selected PR*/
1281  ResourceParametersEditor parametersEditor;
1282
1283  /** A JPanel containing the {@link parametersEditor}*/
1284  JPanel parametersPanel;
1285
1286  /** A border for the {@link parametersPanel} */
1287  TitledBorder parametersBorder;
1288
1289
1290  /** A JPanel containing the running strategy options*/
1291  JPanel strategyPanel;
1292
1293  /** A border for the running strategy options box */
1294  TitledBorder strategyBorder;
1295
1296  /**
1297   * Button for run always.
1298   */
1299  JRadioButton yes_RunRBtn;
1300
1301  /**
1302   * Button for never run.
1303   */
1304  JRadioButton no_RunRBtn;
1305
1306  /**
1307   * Button for conditional run.
1308   */
1309  JRadioButton conditional_RunRBtn;
1310
1311  /**
1312   * The group for run strategy buttons;
1313   */
1314  ButtonGroup runBtnGrp;
1315
1316  /**
1317   * Text field for the feature name for conditional run.
1318   */
1319  JTextField featureNameTextField;
1320
1321  /**
1322   * Text field for the feature value for conditional run.
1323   */
1324  JTextField featureValueTextField;
1325
1326  /**
1327   * A combobox that allows selection of a corpus from the list of loaded
1328   * corpora.
1329   */
1330  JComboBox corpusCombo;
1331
1332  CorporaComboModel corpusComboModel;
1333
1334  /**The "Add PR" menu; part of the popup menu*/
1335  JMenu addMenu;
1336
1337  /**The "Remove PR" menu; part of the popup menu*/
1338  JMenu removeMenu;
1339
1340  /** Action that runs the application*/
1341  RunAction runAction;
1342
1343  /**
1344   * Is the controller displayed an analyser controller?
1345   */
1346  boolean analyserMode = false;
1347
1348  /**
1349   * Is the controller displayed conditional?
1350   */
1351  boolean conditionalMode = false;
1352
1353  /**
1354   * The PR currently selected (having its parameters set)
1355   */
1356  ProcessingResource selectedPR = null;
1357
1358  /**
1359   * The running strategy for the selected PR.
1360   */
1361  RunningStrategy selectedPRRunStrategy = null;
1362
1363  private transient Vector statusListeners;
1364  private transient Vector progressListeners;
1365
1366
1367
1368  protected void fireStatusChanged(String e) {
1369    if (statusListeners != null) {
1370      Vector listeners = statusListeners;
1371      int count = listeners.size();
1372      for (int i = 0; i < count; i++) {
1373        ((StatusListener) listeners.elementAt(i)).statusChanged(e);
1374      }
1375    }
1376  }
1377  public synchronized void removeProgressListener(ProgressListener l) {
1378    if (progressListeners != null && progressListeners.contains(l)) {
1379      Vector v = (Vector) progressListeners.clone();
1380      v.removeElement(l);
1381      progressListeners = v;
1382    }
1383  }
1384  public synchronized void addProgressListener(ProgressListener l) {
1385    Vector v = progressListeners == null ? new Vector(2) : (Vector) progressListeners.clone();
1386    if (!v.contains(l)) {
1387      v.addElement(l);
1388      progressListeners = v;
1389    }
1390  }
1391  protected void fireProgressChanged(int e) {
1392    if (progressListeners != null) {
1393      Vector listeners = progressListeners;
1394      int count = listeners.size();
1395      for (int i = 0; i < count; i++) {
1396        ((ProgressListener) listeners.elementAt(i)).progressChanged(e);
1397      }
1398    }
1399  }
1400  protected void fireProcessFinished() {
1401    if (progressListeners != null) {
1402      Vector listeners = progressListeners;
1403      int count = listeners.size();
1404      for (int i = 0; i < count; i++) {
1405        ((ProgressListener) listeners.elementAt(i)).processFinished();
1406      }
1407    }
1408  }
1409  }//SerialControllerEditor
1410