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