1   /*  ApplicationViewer.java
2    *
3    *  Copyright (c) 1998-2001, The University of Sheffield.
4    *
5    *  This file is part of GATE (see http://gate.ac.uk/), and is free
6    *  software, licenced under the GNU Library General Public License,
7    *  Version 2, June 1991 (in the distribution as file licence.html,
8    *  and also available at http://gate.ac.uk/gate/licence.html).
9    *
10   *  Valentin Tablan 25/01/2001
11   *
12   *  $Id: ApplicationEditor.java,v 1.6 2001/11/15 14:21:14 valyt Exp $
13   *
14   */
15  
16  package gate.gui;
17  
18  import gate.creole.*;
19  import gate.*;
20  import gate.swing.*;
21  import gate.util.*;
22  import gate.event.*;
23  
24  
25  import javax.swing.*;
26  import java.beans.*;
27  import javax.swing.event.*;
28  import javax.swing.table.*;
29  import javax.swing.tree.*;
30  import java.text.*;
31  import java.awt.Component;
32  import java.awt.Window;
33  import java.awt.Color;
34  import java.awt.Dimension;
35  import java.awt.BorderLayout;
36  import java.awt.event.*;
37  import java.lang.reflect.*;
38  import java.util.*;
39  import java.io.IOException;
40  import java.net.URL;
41  
42  public class ApplicationEditor extends AbstractVisualResource
43                                 implements CreoleListener{
44  
45    public ApplicationEditor() {
46    }
47  
48    public void setTarget(Object target){
49      if(!(target instanceof SerialController))
50      throw new IllegalArgumentException(
51        "gate.gui.ApplicationViewer can only be used for serial controllers\n" +
52        target.getClass().toString() +
53        " is not a gate.creole.SerialController!");
54      this.controller = (SerialController)target;
55      initLocalData();
56      initGuiComponents();
57      initListeners();
58    }//setController
59  
60  
61    public void setHandle(Handle handle) {
62      this.handle = handle;
63      //add the items to the popup
64      JPopupMenu popup = handle.getPopup();
65      popup.addSeparator();
66      popup.add(runAction);
67      popup.addSeparator();
68      popup.add(addMenu);
69      popup.add(removeMenu);
70  
71      //register the listeners
72      if(handle instanceof StatusListener)
73        addStatusListener((StatusListener)handle);
74      if(handle instanceof ProgressListener)
75        addProgressListener((ProgressListener)handle);
76    }//setHandle
77  
78    public Resource init() throws ResourceInstantiationException{
79      super.init();
80      return this;
81    }//init
82  
83    protected void initLocalData() {
84      prList = (List)controller.getPRs();
85      paramsForPR = new HashMap();
86      runAction = new RunAction();
87    }//initLocalData
88  
89    protected void initGuiComponents() {
90      this.setLayout(new BorderLayout());
91      Box mainBox = Box.createHorizontalBox();
92  
93      mainTTModel = new PRsAndParamsTTModel(controller);
94      mainTreeTable = new JTreeTable(mainTTModel);
95      mainTreeTable.getTree().setRootVisible(false);
96      mainTreeTable.getTree().setShowsRootHandles(true);
97  
98      mainTreeTable.getTree().setCellRenderer(new CustomTreeCellRenderer());
99      mainTreeTable.getTree().setCellEditor(new ParameterDisjunctionEditor());
100 
101 
102     mainTreeTable.setIntercellSpacing(new Dimension(5,0));
103 
104     mainTreeTable.getColumnModel().
105                   getColumn(3).setCellRenderer(new ParameterValueRenderer());
106     mainTreeTable.getColumnModel().
107                   getColumn(3).setCellEditor(new ParameterValueEditor());
108     mainTreeTable.getColumnModel().
109                   getColumn(2).setCellRenderer(new BooleanRenderer());
110     mainTreeTable.getColumnModel().
111                   getColumn(1).setCellRenderer(new DefaultTableCellRenderer());
112 
113 
114 //    mainTreeTable.setDefaultRenderer(Object.class, new ParameterValueRenderer());
115 //    mainTreeTable.setDefaultEditor(Object.class, new ParameterValueEditor());
116 //    mainTreeTable.setDefaultRenderer(Boolean.class, new BooleanRenderer());
117 
118     ToolTipManager.sharedInstance().registerComponent(mainTreeTable.getTree());
119     ToolTipManager.sharedInstance().registerComponent(mainTreeTable);
120     JScrollPane scroller = new JScrollPane(mainTreeTable);
121     JPanel leftPane = new JPanel();
122     leftPane.setLayout(new BoxLayout(leftPane, BoxLayout.Y_AXIS));
123     leftPane.add(scroller);
124     upBtn = new JButton("Move up", MainFrame.getIcon("up.gif"));
125     downBtn = new JButton("Move down", MainFrame.getIcon("down.gif"));
126     Dimension dim = upBtn.getPreferredSize();
127     int x = dim.width;
128     int y = dim.height;
129     dim = downBtn.getPreferredSize();
130     x = Math.max(x, dim.width);
131     y = Math.max(y, dim.height);
132     dim = new Dimension(x, y);
133     upBtn.setPreferredSize(dim);
134     downBtn.setPreferredSize(dim);
135     upBtn.setMinimumSize(dim);
136     downBtn.setMinimumSize(dim);
137     upBtn.setMaximumSize(dim);
138     downBtn.setMaximumSize(dim);
139 
140 
141     Box horBox = Box.createHorizontalBox();
142     Box verBox = Box.createVerticalBox();
143     verBox.add(upBtn);
144     verBox.add(downBtn);
145     horBox.add(verBox);
146     horBox.add(Box.createHorizontalGlue());
147     leftPane.add(Box.createVerticalStrut(5));
148     leftPane.add(horBox);
149 
150     leftPane.setBorder(BorderFactory.createTitledBorder("Used components"));
151 
152     mainBox.add(leftPane);
153 
154     Box buttonsBox = Box.createVerticalBox();
155     addModuleBtn = new JButton("Add component", MainFrame.getIcon("left2.gif"));
156     addModuleBtn.setAlignmentX(JComponent.CENTER_ALIGNMENT);
157     removeModuleBtn = new JButton("Remove component",
158                                   MainFrame.getIcon("right2.gif"));
159     removeModuleBtn.setAlignmentX(JComponent.CENTER_ALIGNMENT);
160     dim = addModuleBtn.getPreferredSize();
161     x = dim.width;
162     y = dim.height;
163     dim = removeModuleBtn.getPreferredSize();
164     x = Math.max(x, dim.width);
165     y = Math.max(y, dim.height);
166     dim = new Dimension(x, y);
167     addModuleBtn.setPreferredSize(dim);
168     removeModuleBtn.setPreferredSize(dim);
169     addModuleBtn.setMinimumSize(dim);
170     removeModuleBtn.setMinimumSize(dim);
171     addModuleBtn.setMaximumSize(dim);
172     removeModuleBtn.setMaximumSize(dim);
173 
174     buttonsBox.add(Box.createVerticalStrut(30));
175     buttonsBox.add(addModuleBtn);
176     buttonsBox.add(Box.createVerticalStrut(5));
177     buttonsBox.add(removeModuleBtn);
178     buttonsBox.add(Box.createVerticalStrut(30));
179     runBtn = new JButton(runAction);
180     runBtn.setAlignmentX(JComponent.CENTER_ALIGNMENT);
181     buttonsBox.add(runBtn);
182     buttonsBox.add(Box.createVerticalGlue());
183 
184     mainBox.add(buttonsBox);
185 
186     modulesTableModel = new ModulesTableModel();
187     modulesTable = new XJTable(modulesTableModel);
188     modulesTable.setSortable(true);
189     modulesTable.setSortedColumn(0);
190     modulesTable.setSelectionMode(
191                                 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
192     scroller = new JScrollPane(modulesTable);
193     scroller.setBorder(BorderFactory.createTitledBorder("Available components"));
194 
195     mainBox.add(scroller);
196 
197     this.add(mainBox, BorderLayout.CENTER);
198 
199 //    popup = new JPopupMenu();
200 //    popup.add(new RunAction());
201     addMenu = new JMenu("Add");
202     removeMenu = new JMenu("Remove");
203 //    popup.add(addMenu);
204 //    popup.add(removeMenu);
205   }// initGuiComponents()
206 
207   protected void initListeners() {
208     Gate.getCreoleRegister().addCreoleListener(this);
209     this.addMouseListener(new MouseAdapter() {
210       public void mouseClicked(MouseEvent e) {
211         if(SwingUtilities.isRightMouseButton(e)){
212           if(handle != null && handle.getPopup()!= null)
213             handle.getPopup().show(ApplicationEditor.this, e.getX(), e.getY());
214         }
215       }
216     });
217 
218     addModuleBtn.addActionListener(new ActionListener() {
219       public void actionPerformed(ActionEvent e) {
220         int rows[] = modulesTable.getSelectedRows();
221         if(rows == null || rows.length == 0){
222           JOptionPane.showMessageDialog(
223               ApplicationEditor.this,
224               "Please select some components from the list of available components!\n" ,
225               "Gate", JOptionPane.ERROR_MESSAGE);
226         } else {
227           List actions = new ArrayList();
228           for(int i = 0; i < rows.length; i++) {
229 //            Action act =(Action)
230 //                       addActionForPR.get(modulesTable.getValueAt(rows[i], -1));
231             Action act =(Action)new AddPRAction((ProcessingResource)
232                                      modulesTable.getValueAt(rows[i], -1));
233             if(act != null) actions.add(act);
234           }
235           Iterator actIter = actions.iterator();
236           while(actIter.hasNext()){
237             ((Action)actIter.next()).actionPerformed(null);
238           }
239         }
240       }
241     });
242 
243     removeModuleBtn.addActionListener(new ActionListener() {
244       public void actionPerformed(ActionEvent e) {
245         int rows[] = mainTreeTable.getSelectedRows();
246         if(rows == null || rows.length == 0){
247           JOptionPane.showMessageDialog(
248               ApplicationEditor.this,
249               "Please select some components to be removed "+
250               "from the list of used components!\n" ,
251               "Gate", JOptionPane.ERROR_MESSAGE);
252         } else {
253           List actions = new ArrayList();
254 //          List nodes = new ArrayList();
255           for(int i = 0; i < rows.length; i++){
256             DefaultMutableTreeNode node = (DefaultMutableTreeNode)
257                                           mainTreeTable.getTree().
258                                           getPathForRow(rows[i]).
259                                           getLastPathComponent();
260             Object value = ((DefaultMutableTreeNode)node).getUserObject();
261             if(value instanceof ProcessingResource &&
262                prList.contains(value)){
263               Action act = new RemovePRAction((ProcessingResource)value);
264               if(act != null){
265                 actions.add(act);
266               }
267             } else {
268               JOptionPane.showMessageDialog(
269                   ApplicationEditor.this,
270                   "Only processing resources can be removed!\n" +
271                   "(Processing resources are the nodes from the first level " +
272                   "of the tree)" ,
273                   "Gate", JOptionPane.ERROR_MESSAGE);
274             }
275           }
276           Iterator actIter = actions.iterator();
277           while(actIter.hasNext()){
278             ((Action)actIter.next()).actionPerformed(null);
279           }
280         }// else
281       }//  public void actionPerformed(ActionEvent e)
282     });
283 
284     upBtn.addActionListener(new ActionListener() {
285       public void actionPerformed(ActionEvent e) {
286         TreePath[] paths = mainTreeTable.getTree().getSelectionPaths();
287         if(paths == null || paths.length == 0){
288           JOptionPane.showMessageDialog(
289               ApplicationEditor.this,
290               "Please select some components to be moved from the " +
291               "list of used components!\n" ,
292               "Gate", JOptionPane.ERROR_MESSAGE);
293         } else {
294           for(int i = 0; i < paths.length; i++) {
295             DefaultMutableTreeNode node = (DefaultMutableTreeNode)
296                                           paths[i].getLastPathComponent();
297             Object value = node.getUserObject();
298             if(value instanceof ProcessingResource &&
299                prList.contains(value)){
300               int index = prList.indexOf(value);
301               //move the module up
302               if(index > 0){
303                 prList.remove(index);
304                 index--;
305                 prList.add(index, value);
306                 DefaultMutableTreeNode parent =
307                       (DefaultMutableTreeNode)node.getParent();
308                 boolean expanded = mainTreeTable.getTree().isExpanded(paths[i]);
309                 mainTTModel.removeNodeFromParent(node);
310                 mainTTModel.insertNodeInto(node, parent, index);
311                 if(expanded){
312                   mainTreeTable.expandPath(paths[i]);
313                 }
314               }
315             } else {
316               JOptionPane.showMessageDialog(
317                   ApplicationEditor.this,
318                   "Only processing resources can be moved!\n" +
319                   "(Processing resources are the nodes from the first level of the tree)" ,
320                   "Gate", JOptionPane.ERROR_MESSAGE);
321             }
322           }
323           final TreePath[] finalPaths = paths;
324           SwingUtilities.invokeLater(new Runnable(){
325             public void run(){
326               mainTreeTable.getTree().setSelectionPaths(finalPaths);
327             }
328           });
329         }// else
330       }//public void actionPerformed(ActionEvent e)
331     });
332 
333     downBtn.addActionListener(new ActionListener() {
334       public void actionPerformed(ActionEvent e) {
335         TreePath[] paths = mainTreeTable.getTree().getSelectionPaths();
336         if(paths == null || paths.length == 0){
337           JOptionPane.showMessageDialog(
338               ApplicationEditor.this,
339               "Please select some components to be moved from the list of used components!\n" ,
340               "Gate", JOptionPane.ERROR_MESSAGE);
341         } else {
342           for(int i = paths.length -1; i >= 0; i--){
343             DefaultMutableTreeNode node = (DefaultMutableTreeNode)
344                                           paths[i].getLastPathComponent();
345             Object value = node.getUserObject();
346             if(value instanceof ProcessingResource && prList.contains(value)){
347               int index = prList.indexOf(value);
348               //move the module down
349               if(index < prList.size() - 1){
350                 prList.remove(index);
351                 index++;
352                 prList.add(index, value);
353                 DefaultMutableTreeNode parent =
354                       (DefaultMutableTreeNode)node.getParent();
355                 boolean expanded = mainTreeTable.getTree().isExpanded(paths[i]);
356                 mainTTModel.removeNodeFromParent(node);
357                 mainTTModel.insertNodeInto(node, parent, index);
358                 if(expanded){
359                   mainTreeTable.expandPath(paths[i]);
360                 }
361               }
362             }else{
363               JOptionPane.showMessageDialog(
364                   ApplicationEditor.this,
365                   "Only processing resources can be moved!\n" +
366                   "(Processing resources are the nodes from the first level of the tree)" ,
367                   "Gate", JOptionPane.ERROR_MESSAGE);
368             }
369           }//for(int i = 0; i < rows.length; i++)
370           final TreePath[] finalPaths = paths;
371           SwingUtilities.invokeLater(new Runnable(){
372             public void run(){
373               mainTreeTable.getTree().setSelectionPaths(finalPaths);
374             }
375           });
376         }// else
377       }//public void actionPerformed(ActionEvent e)
378     });
379 
380     mainTreeTable.addComponentListener(new ComponentAdapter() {
381       public void componentResized(ComponentEvent e) {
382         ApplicationEditor.this.validate();
383       }// public void componentResized(ComponentEvent e)
384 
385       public void componentShown(ComponentEvent e) {
386         ApplicationEditor.this.validate();
387       }// public void componentShown(ComponentEvent e)
388     });
389 
390     modulesTable.addComponentListener(new ComponentAdapter() {
391       public void componentResized(ComponentEvent e) {
392         ApplicationEditor.this.validate();
393       }// public void componentResized(ComponentEvent e)
394 
395       public void componentShown(ComponentEvent e) {
396         ApplicationEditor.this.validate();
397       }// public void componentShown(ComponentEvent e)
398     });
399 
400     addMenu.addMenuListener(new MenuListener() {
401       public void menuCanceled(MenuEvent e) {
402 
403       }
404 
405       public void menuDeselected(MenuEvent e) {
406       }
407 
408       public void menuSelected(MenuEvent e) {
409         addMenu.removeAll();
410         Iterator prIter = Gate.getCreoleRegister().getPrInstances().iterator();
411         while(prIter.hasNext()){
412           ProcessingResource pr = (ProcessingResource)prIter.next();
413           if(Gate.getHiddenAttribute(pr.getFeatures())){
414             //ignore this resource
415           }else{
416             addMenu.add(new AddPRAction(pr));
417           }
418         }// while
419       }
420     });
421 
422     removeMenu.addMenuListener(new MenuListener() {
423       public void menuCanceled(MenuEvent e) {
424       }
425 
426       public void menuDeselected(MenuEvent e) {
427       }
428 
429       public void menuSelected(MenuEvent e) {
430         removeMenu.removeAll();
431         Iterator prIter = Gate.getCreoleRegister().getPrInstances().iterator();
432         while(prIter.hasNext()){
433           ProcessingResource pr = (ProcessingResource)prIter.next();
434           if(Gate.getHiddenAttribute(pr.getFeatures())){
435             //ignore this resource
436           }else{
437             removeMenu.add(new RemovePRAction(pr));
438           }
439         }// while
440       }
441     });
442   }//protected void initListeners()
443 
444 //  protected void updateActions(){
445 //    Iterator prIter = Gate.getCreoleRegister().getPrInstances().iterator();
446 //    while(prIter.hasNext()){
447 //      ProcessingResource pr = (ProcessingResource)prIter.next();
448 //      if(Gate.getApplicationAttribute(pr.getFeatures()) ||
449 //         Gate.getHiddenAttribute(pr.getFeatures())){
450 //        //ignore this resource
451 //      }else{
452 //        if(!addActionForPR.containsKey(pr)){
453 //          AddPRAction addAction = new AddPRAction(pr);
454 //          RemovePRAction remAction = new RemovePRAction(pr);
455 //          remAction.setEnabled(false);
456 //          addActionForPR.put(pr, addAction);
457 //          removeActionForPR.put(pr, remAction);
458 //        }
459 //      }
460 //    }// while
461 //  }//protected void updateActions()
462 //
463 //  public MenuElement[] getPopupElements(){
464 //    updateActions();
465 //    popup.removeAll();
466 //    popup.add(runAction);
467 //    addMenu = new JMenu("Add");
468 //    removeMenu = new JMenu("Remove");
469 //    popup.add(addMenu);
470 //    popup.add(removeMenu);
471 //    Iterator addActionsIter = addActionForPR.values().iterator();
472 //    while(addActionsIter.hasNext()){
473 //      addMenu.add((Action)addActionsIter.next());
474 //    }
475 //
476 //    Iterator remActionsIter = removeActionForPR.values().iterator();
477 //    while(remActionsIter.hasNext()){
478 //      removeMenu.add((Action)remActionsIter.next());
479 //    }
480 //    return popup.getSubElements();
481 //  }//public MenuElement[] getPopupElements()
482 
483   protected String getResourceName(Resource res){
484     ResourceData rData = (ResourceData)Gate.getCreoleRegister().
485                          get(res.getClass().getName());
486     if(rData != null) return rData.getName();
487     else return res.getClass().getName();
488   }//getResourceName
489 
490   class PRsAndParamsTTModel extends DefaultTreeModel implements TreeTableModel{
491     PRsAndParamsTTModel(SerialController aController){
492       super(new DefaultMutableTreeNode(aController, true), true);
493     }
494 
495     public int getColumnCount(){
496       return 4;
497     }//getColumnCount
498 
499     public String getColumnName(int column){
500       switch(column){
501         case 0: return "Name";
502         case 1: return "Type";
503         case 2: return "Required";
504         case 3: return "Parameter Value";
505         default: return "?";
506       }
507     }//public String getColumnName(int column)
508 
509     public Class getColumnClass(int column){
510       switch(column){
511         case 1: return String.class;
512         case 2: return Boolean.class;
513         case 3: return Object.class;
514         default: return Object.class;
515       }
516     }//public Class getColumnClass(int column)
517 
518     public Object getValueAt(Object node, int column){
519       if(node == root){
520           switch(column){
521             case 0: return null;
522             case 1: return null;
523             case 2: return new Boolean(false);
524             case 3: return null;
525           }
526       }else{
527         node = ((DefaultMutableTreeNode)node).getUserObject();
528         if (node instanceof ProcessingResource){
529           ProcessingResource pr = (ProcessingResource)node;
530           switch(column){
531             case 0: return null;
532             case 1: return getResourceName(pr);
533             case 2: return new Boolean(false);
534             case 3: return null;
535           }
536         }else if (node instanceof ParameterDisjunction){
537           ParameterDisjunction pd = (ParameterDisjunction)node;
538           switch(column){
539             case 0: return pd;
540             case 1: {
541               String paramType = pd.getType();
542               if(Gate.getCreoleRegister().containsKey(paramType)){
543                 ResourceData rData = (ResourceData)
544                                      Gate.getCreoleRegister().get(paramType);
545                 if(rData != null) paramType = rData.getName();
546               }
547               return paramType;
548             }
549             case 2: return pd.getRequired();
550             case 3: return pd.getValue();
551             default: return null;
552           }
553         }
554       }
555       return null;
556     }//public Object getValueAt(Object node, int column)
557 
558     public boolean isCellEditable(Object node, int column){
559       node = ((DefaultMutableTreeNode)node).getUserObject();
560       if(column == 3) return node instanceof ParameterDisjunction;
561       if(column == 0){
562         return node instanceof ParameterDisjunction &&
563                ((ParameterDisjunction)node).size() > 1 ;
564       }
565       return false;
566     }//public boolean isCellEditable(Object node, int column)
567 
568     public void setValueAt(Object aValue, Object node, int column){
569       Object nodeObject = ((DefaultMutableTreeNode)node).getUserObject();
570       switch(column){
571         case 0:{
572           if(nodeObject instanceof ParameterDisjunction && aValue instanceof Integer){
573             ((ParameterDisjunction)nodeObject).
574               setSelectedIndex(((Integer)aValue).intValue());
575           }
576           nodeChanged((DefaultMutableTreeNode)node);
577           break;
578         }case 3:{
579           if(nodeObject instanceof ParameterDisjunction){
580             ((ParameterDisjunction)nodeObject).setValue(aValue);
581           }
582           break;
583         }
584       }//switch(column)
585     }//setValueAt
586 /*
587     public Object getChild(Object parent, int index){
588       if(parent == root){
589         SerialController sc = (SerialController)parent;
590         return sc.get(index);
591       }else{
592         parent = ((DefaultMutableTreeNode)parent).getUserObject();
593         if (parent instanceof ProcessingResource){
594           ProcessingResource pr = (ProcessingResource)parent;
595           List paramsList = (List)paramsForPR.get(pr);
596           return (ParameterDisjunction)paramsList.get(index);
597         }else return null;
598       }
599     }
600 
601     public int getChildCount(Object parent){
602       if(parent == root){
603         SerialController sc = (SerialController)parent;
604         return sc.size();
605       }else{
606         parent = ((DefaultMutableTreeNode)parent).getUserObject();
607         if (parent instanceof ProcessingResource){
608           ProcessingResource pr = (ProcessingResource)parent;
609           List paramsList = (List)paramsForPR.get(pr);
610           return paramsList==null ? 0 : paramsList.size();
611         }else  return 0;
612       }
613     }
614 
615 */
616     public void dataChanged(){
617       fireTreeStructureChanged(this, new Object[]{getRoot()}, null, null);
618     }//dataChanged
619 
620   }//class PRsAndParamsTTModel extends AbstractTreeTableModel
621 
622   class CustomTreeCellRenderer extends DefaultTreeCellRenderer {
623     public CustomTreeCellRenderer(){
624       combo = new JComboBox();
625       comboRenderer = new CustomRenderer();
626       combo.setRenderer(comboRenderer);
627     }
628 
629     class CustomRenderer extends JLabel implements ListCellRenderer {
630       public Component getListCellRendererComponent(JList list,
631                                                     Object value,
632                                                     int index,
633                                                     boolean isSelected,
634                                                     boolean cellHasFocus){
635 
636         setText(value.toString());
637         setToolTipText(tipText);
638         setIcon(MainFrame.getIcon(iconName));
639         setMinimumSize(getPreferredSize());
640         return this;
641       }
642     };
643 
644     public Component getTreeCellRendererComponent(JTree tree,
645                                                   Object value,
646                                                   boolean sel,
647                                                   boolean expanded,
648                                                   boolean leaf,
649                                                   int row,
650                                                   boolean hasFocus){
651 
652       String text = "";
653       tipText = null;
654       iconName = null;
655       value = ((DefaultMutableTreeNode)value).getUserObject();
656       if (value instanceof ProcessingResource){
657         ProcessingResource pr = (ProcessingResource)value;
658         text = pr.getName();
659         ResourceData rData = (ResourceData)
660                    Gate.getCreoleRegister().get(pr.getClass().getName());
661         tipText = rData.getComment();
662         iconName = rData.getIcon();
663         if(iconName == null) iconName = "pr.gif";
664       } else if (value instanceof ParameterDisjunction) {
665         ParameterDisjunction pd = (ParameterDisjunction)value;
666 
667         iconName = "param.gif";
668         if(Gate.getCreoleRegister().containsKey(pd.getType())){
669           ResourceData rData = (ResourceData)
670                                Gate.getCreoleRegister().get(pd.getType());
671           if(rData != null){
672             tipText = rData.getComment();
673             iconName = rData.getIcon();
674           }
675         }
676 
677         text =  pd.getName();
678         if(pd.size() > 1){
679           combo.setModel(new DefaultComboBoxModel(new Object[]{text}));
680           return combo;
681         };
682       }
683 
684       //prepare the renderer
685       Component comp = super.getTreeCellRendererComponent(tree, text, sel,
686                                                           expanded, leaf,
687                                                           row, hasFocus);
688       setToolTipText(tipText);
689       setIcon(MainFrame.getIcon(iconName));
690       return this;
691     }//public Component getTreeCellRendererComponent
692 
693     /**
694      * Used for Parameter Disjunctions
695      */
696     JComboBox combo;
697     String iconName;
698     String tipText;
699     CustomRenderer comboRenderer;
700   }//class CustomTreeCellRenderer extends DefaultTreeCellRenderer
701 
702   class ModulesTableModel extends AbstractTableModel{
703     public int getRowCount(){
704       List prsList = Gate.getCreoleRegister().getPrInstances();
705       int size = prsList.size();
706       Iterator prsIter = prsList.iterator();
707       while(prsIter.hasNext()){
708         Resource res = (Resource)prsIter.next();
709         if(prList.contains(res)||
710            Gate.getHiddenAttribute(res.getFeatures())) size--;
711       }
712       return size;
713     }//public int getRowCount()
714 
715     public int getColumnCount(){
716       return 2;
717     }//public int getColumnCount()
718 
719     public String getColumnName(int columnIndex){
720       switch(columnIndex){
721         case 0: return "Name";
722         case 1: return "Type";
723         default: return "?";
724       }
725     }//public String getColumnName(int columnIndex)
726 
727     public Class getColumnClass(int columnIndex){
728       return String.class;
729     }//public Class getColumnClass(int columnIndex)
730 
731     public boolean isCellEditable(int rowIndex,  int columnIndex){
732       return false;
733     }//public boolean isCellEditable(int rowIndex,  int columnIndex)
734 
735     public Object getValueAt(int rowIndex, int columnIndex){
736       //find the right PR
737       List allPrs = new ArrayList(Gate.getCreoleRegister().getPrInstances());
738       Iterator allPRsIter = allPrs.iterator();
739       int index = -1;
740       ProcessingResource pr =null;
741       while(allPRsIter.hasNext() && index < rowIndex){
742         pr = (ProcessingResource)allPRsIter.next();
743         if (!(prList.contains(pr)||
744               Gate.getHiddenAttribute(pr.getFeatures()))
745             )  index ++;
746       }
747       if(index == rowIndex && pr != null){
748         switch(columnIndex){
749           case -1: return pr;
750           case 0: return pr.getName();
751           case 1: return getResourceName(pr);
752         }
753       }
754       return null;
755     }// public Object getValueAt(int rowIndex, int columnIndex)
756 
757     public void setValueAt(Object aValue, int rowIndex, int columnIndex){
758     }
759 
760   }//class ModulesTableModel extends AbstractTableModel
761 
762   class AddPRAction extends AbstractAction {
763     AddPRAction(ProcessingResource aPR){
764       super(aPR.getName());
765       this.pr = aPR;
766       setEnabled(!prList.contains(aPR));
767     }
768 
769     public void actionPerformed(ActionEvent e){
770       prList.add(pr);
771       DefaultMutableTreeNode root = (DefaultMutableTreeNode)mainTTModel.
772                                      getRoot();
773       DefaultMutableTreeNode node = new DefaultMutableTreeNode(pr, true);
774       mainTTModel.insertNodeInto(node, root, root.getChildCount());
775       mainTreeTable.expandPath(
776             new TreePath(new Object[]{mainTTModel.getRoot(), node}));
777 
778       ResourceData rData = (ResourceData)
779                           Gate.getCreoleRegister().get(pr.getClass().getName());
780       List params = rData.getParameterList().getRuntimeParameters();
781 //System.out.println("parameters: " + params);
782       Iterator paramsIter = params.iterator();
783       List parameterDisjunctions = new ArrayList();
784       while(paramsIter.hasNext()){
785         ParameterDisjunction pDisj = new ParameterDisjunction(pr,
786                                           (List)paramsIter.next());
787         parameterDisjunctions.add(pDisj);
788         DefaultMutableTreeNode paramNode = new DefaultMutableTreeNode(pDisj,
789                                                                       false);
790         mainTTModel.insertNodeInto(paramNode, node, node.getChildCount());
791         mainTreeTable.expandPath(new TreePath(new Object[]{
792                                      mainTTModel.getRoot(), node, paramNode}));
793       }
794       paramsForPR.put(pr, parameterDisjunctions);
795       modulesTableModel.fireTableDataChanged();
796       this.setEnabled(false);
797 //      ((Action)removeActionForPR.get(pr)).setEnabled(true);
798     }//public void actionPerformed(ActionEvent e)
799     ProcessingResource pr;
800   }//class AddPRAction extends AbstractAction
801 
802 
803   class RemovePRAction extends AbstractAction {
804     RemovePRAction(ProcessingResource pr){
805       super(pr.getName());
806       this.pr = pr;
807       setEnabled(prList.contains(pr));
808     }
809 
810     public void actionPerformed(ActionEvent e){
811       prList.remove(pr);
812       paramsForPR.remove(pr);
813       modulesTableModel.fireTableDataChanged();
814       //remove the PR from the PRs-and-Params tree
815       Enumeration prNodesEnum = ((DefaultMutableTreeNode)
816                                   mainTTModel.getRoot()).children();
817       children: while(prNodesEnum.hasMoreElements()){
818         DefaultMutableTreeNode node = (DefaultMutableTreeNode)
819                                       prNodesEnum.nextElement();
820         Object value = ((DefaultMutableTreeNode)node).getUserObject();
821         if(value == pr){
822           mainTTModel.removeNodeFromParent(node);
823           break children;
824         }
825       }
826 
827       this.setEnabled(false);
828     }//public void actionPerformed(ActionEvent e)
829     ProcessingResource pr;
830   }//class RemovePRAction extends AbstractAction
831 
832   class RunAction extends AbstractAction {
833     RunAction(){
834       super("Run");
835     }
836 
837     public void actionPerformed(ActionEvent e){
838       Runnable runnable = new Runnable(){
839         public void run(){
840           //stop edits
841           if(mainTreeTable.getEditingColumn() != -1 &&
842             mainTreeTable.getEditingRow() != -1){
843             mainTreeTable.editingStopped(
844                 new ChangeEvent(mainTreeTable.getCellEditor(
845                                 mainTreeTable.getEditingRow(),
846                                 mainTreeTable.getEditingColumn())));
847           }
848 
849           //read all the parameters: this will set all null parameters to their
850           //default values (e.g.the most recently used document)
851           Enumeration nodes = ((DefaultMutableTreeNode)mainTTModel.getRoot()).
852                               depthFirstEnumeration();
853           while(nodes.hasMoreElements())
854             mainTTModel.getValueAt(nodes.nextElement(), 3);
855 
856           //set the listeners
857           StatusListener sListener = new InternalStatusListener();
858           ProgressListener pListener = new InternalProgressListener();
859 
860           controller.addStatusListener(sListener);
861           controller.addProgressListener(pListener);
862 
863           Gate.setExecutable(controller);
864 
865           //execute the thing
866           long startTime = System.currentTimeMillis();
867           fireStatusChanged("Running " +
868                             controller.getName());
869           fireProgressChanged(0);
870 
871           try {
872             controller.execute();
873           }catch(ExecutionInterruptedException eie){
874             JOptionPane.showMessageDialog(
875               ApplicationEditor.this,
876               "Interrupted!\n" + eie.toString(),
877               "Gate", JOptionPane.ERROR_MESSAGE);
878             Gate.setExecutable(null);
879           }catch(ExecutionException ee) {
880             Gate.setExecutable(null);
881             ee.printStackTrace(Err.getPrintWriter());
882             JOptionPane.showMessageDialog(
883               ApplicationEditor.this,
884               "Execution error while running \"" + controller.getName() +
885               "\" :\nSee \"Messages\" tab for details!",
886               "Gate", JOptionPane.ERROR_MESSAGE);
887           }catch(Exception e){
888             Gate.setExecutable(null);
889             JOptionPane.showMessageDialog(ApplicationEditor.this,
890                                           "Unhandled execution error!\n " +
891                                           "See \"Messages\" tab for details!",
892                                           "Gate", JOptionPane.ERROR_MESSAGE);
893             e.printStackTrace(Err.getPrintWriter());
894           }//catch
895           Gate.setExecutable(null);
896 
897 
898           //remove the listeners
899           controller.removeStatusListener(sListener);
900           controller.removeProgressListener(pListener);
901 //
902 //
903 //
904 //
905 //          Iterator prsIter = prList.iterator();
906 //          while(prsIter.hasNext()){
907 //            ProcessingResource pr = (ProcessingResource)prsIter.next();
908 //            FeatureMap params = Factory.newFeatureMap();
909 //            List someParams = (List)paramsForPR.get(pr);
910 //            Iterator paramsIter = someParams.iterator();
911 //            while(paramsIter.hasNext()){
912 //              ParameterDisjunction pDisj =
913 //                                        (ParameterDisjunction)paramsIter.next();
914 //              if(pDisj.getValue() != null){
915 //                params.put(pDisj.getName(), pDisj.getValue());
916 //              }
917 //            }
918 //            try{
919 //              pr.setParameterValues(params);
920 //            }catch(ResourceInstantiationException ie){
921 //              ie.printStackTrace(Err.getPrintWriter());
922 //              JOptionPane.showMessageDialog(
923 //                ApplicationEditor.this,
924 //                "Could not set parameters for " + pr.getName() + ":\n" +
925 //                "See the \"Messages\" tab for details",
926 //                "Gate", JOptionPane.ERROR_MESSAGE);
927 //              fireProcessFinished();
928 //              return;
929 //            }
930 //          }
931 //          //run the thing
932 //          prsIter = prList.iterator();
933 //          int i = 0;
934 //          Map listeners = new HashMap();
935 //          listeners.put("gate.event.StatusListener", new StatusListener(){
936 //            public void statusChanged(String text){
937 //              fireStatusChanged(text);
938 //            }
939 //          });
940 //
941 //
942 //          while(prsIter.hasNext()){
943 //            ProcessingResource pr = (ProcessingResource)prsIter.next();
944 //            fireStatusChanged("Running " + pr.getName());
945 //            listeners.put("gate.event.ProgressListener",
946 //                          new CustomProgressListener(
947 //                                i * 100 / prList.size(),
948 //                                (i + 1) * 100 / prList.size()));
949 //
950 //            //try to set this listener if the resource can fire progress events
951 //            try{
952 //
953 //              // get the beaninfo for the resource bean, excluding data about Object
954 //              BeanInfo resBeanInfo = Introspector.getBeanInfo(pr.getClass(),
955 //                                                              Object.class);
956 //              // get all the events the bean can fire
957 //              EventSetDescriptor[] events = resBeanInfo.getEventSetDescriptors();
958 //
959 //              // add the listeners
960 //              if(events != null) {
961 //                EventSetDescriptor event;
962 //                for(int j = 0; j < events.length; j++) {
963 //                  event = events[j];
964 //
965 //                  // did we get such a listener?
966 //                  Object listener =
967 //                    listeners.get(event.getListenerType().getName());
968 //                  if(listener != null){
969 //                    Method addListener = event.getAddListenerMethod();
970 //
971 //                    // call the set method with the parameter value
972 //                    Object[] args = new Object[1];
973 //                    args[0] = listener;
974 //                    addListener.invoke(pr, args);
975 //                  }
976 //                } // for each event
977 //              }   // if events != null
978 //            }catch(IntrospectionException ie){
979 //              //not really important; just ignore
980 //            }catch(java.lang.reflect.InvocationTargetException ite){
981 //              //not really important; just ignore
982 //            }catch(IllegalAccessException iae){
983 //              //not really important; just ignore
984 //            }
985 //
986 //            try {
987 //              pr.execute();
988 //            } catch(ExecutionException ee) {
989 //              ee.printStackTrace(Err.getPrintWriter());
990 //              Exception exc = ee.getException();
991 //              if(exc != null){
992 //                Err.prln("===> from:");
993 //                exc.printStackTrace(Err.getPrintWriter());
994 //              }
995 //              JOptionPane.showMessageDialog(
996 //                ApplicationEditor.this,
997 //                "Execution error while running \"" + pr.getName() + "\" :\n " +
998 //                "See \"Messages\" tab for details!",
999 //                "Gate", JOptionPane.ERROR_MESSAGE);
1000//            }catch(Exception e){
1001//              JOptionPane.showMessageDialog(ApplicationEditor.this,
1002//                                            "Unhandled execution error!\n " +
1003//                                            "See \"Messages\" tab for details!",
1004//                                            "Gate", JOptionPane.ERROR_MESSAGE);
1005//              e.printStackTrace(Err.getPrintWriter());
1006//            }//catch
1007//            i++;
1008//          }
1009          long endTime = System.currentTimeMillis();
1010          fireProcessFinished();
1011          fireStatusChanged(controller.getName() +
1012                            " run in " +
1013                            NumberFormat.getInstance().format(
1014                            (double)(endTime - startTime) / 1000) + " seconds");
1015        }
1016      };
1017      Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1018                                 runnable,
1019                                 "ApplicationViewer1");
1020      thread.setPriority(Thread.MIN_PRIORITY);
1021      thread.start();
1022    }//public void actionPerformed(ActionEvent e)
1023  }//class RunAction
1024
1025  class ParameterDisjunction {
1026    /**
1027     * @param options a list of {@link gate.creole.Parameter}
1028     * @param pr the {@link ProcessingResource}
1029     */
1030    public ParameterDisjunction(ProcessingResource pr, List options) {
1031      this.options = options;
1032      this.pr = pr;
1033      Iterator paramsIter = options.iterator();
1034      names = new String[options.size()];
1035      int i = 0;
1036      while(paramsIter.hasNext()){
1037        names[i++] = ((Parameter)paramsIter.next()).getName();
1038      }
1039//      values = new Object[options.size()];
1040      setSelectedIndex(0);
1041    }// public ParameterDisjunction(List options)
1042
1043    public void setSelectedIndex(int index){
1044      selectedIndex = index;
1045      currentParameter = (Parameter)options.get(selectedIndex);
1046      typeName = currentParameter.getTypeName();
1047//      if(values[selectedIndex] == null){
1048//        try {
1049//          values[selectedIndex] = currentParameter.getDefaultValue();
1050//        } catch(Exception e) {
1051//          values[selectedIndex] = "";
1052//        }
1053//      }
1054
1055//      tableModel.fireTableDataChanged();
1056    }// public void setSelectedIndex(int index)
1057
1058    public int size() {
1059      return options.size();
1060    }
1061
1062    public Boolean getRequired() {
1063      return new Boolean(!currentParameter.isOptional());
1064    }
1065
1066    public String getName() {
1067      return currentParameter.getName();
1068    }
1069
1070    public String getComment(){
1071      return currentParameter.getComment();
1072    }
1073
1074    public String getType(){
1075      return currentParameter.getTypeName();
1076    }
1077
1078    public String[] getNames(){
1079      return names;
1080    }
1081
1082    public Object[] getParameters(){
1083      return options.toArray();
1084    }
1085    /**
1086     * Called when the value used for this parameter has been unloaded.
1087     * Will set the value for this param to the default
1088     */
1089    public void clearValue(){
1090      try{
1091        setValue(currentParameter.getDefaultValue());
1092      }catch(ParameterException pe){
1093        setValue(null);
1094      }
1095    }
1096
1097    public void setValue(Object value){
1098      try{
1099        pr.setParameterValue(currentParameter.getName(), value);
1100      }catch(Exception e){
1101        JOptionPane.showMessageDialog(ApplicationEditor.this,
1102                                      "Invalid value!\n" +
1103                                      "Is it the right type?",
1104                                      "Gate", JOptionPane.ERROR_MESSAGE);
1105      }
1106//      Object oldValue = values[selectedIndex];
1107//      if(value instanceof String){
1108//        if(typeName.equals("java.lang.String")){
1109//          values[selectedIndex] = value;
1110//        }else{
1111//          try{
1112//            values[selectedIndex] = currentParameter.
1113//                                    calculateValueFromString((String)value);
1114//          }catch(Exception e){
1115//            values[selectedIndex] = oldValue;
1116//            JOptionPane.showMessageDialog(ApplicationEditor.this,
1117//                                          "Invalid value!\n" +
1118//                                          "Is it the right type?",
1119//                                          "Gate", JOptionPane.ERROR_MESSAGE);
1120//          }
1121//        }
1122//      }else{
1123//        values[selectedIndex] = value;
1124//      }
1125    }// public void setValue(Object value)
1126
1127    public Object getValue(){
1128      Object value = null;
1129      try{
1130        value = pr.getParameterValue(currentParameter.getName());
1131      }catch(Exception e){
1132        value = null;
1133      }
1134      if(value == null){
1135        //no value set; use the most currently used one of the given type
1136        if(Gate.getCreoleRegister().containsKey(getType())){
1137          WeakBumpyStack instances = ((ResourceData)
1138                              Gate.getCreoleRegister().get(getType())).
1139                                  getInstantiations();
1140          if(instances != null && !instances.isEmpty()){
1141            value = instances.peek();
1142            setValue(value);
1143          }
1144        }
1145      }
1146      return value;
1147
1148//      if(values[selectedIndex] != null) {
1149//        return values[selectedIndex];
1150//      } else {
1151//        //no value set; use the most currently used one of the given type
1152//        if(Gate.getCreoleRegister().containsKey(getType())){
1153//          Stack instances = ((ResourceData)
1154//                              Gate.getCreoleRegister().get(getType())).
1155//                                  getInstantiations();
1156//          if(instances != null && !instances.isEmpty()){
1157//            return instances.peek();
1158//          }
1159//          else return null;
1160//        } else {
1161//          return null;
1162//        }
1163//      }// else
1164    }// public Object getValue()
1165
1166
1167    int selectedIndex;
1168    List options;
1169    ProcessingResource pr;
1170    String typeName;
1171    String name;
1172    String[] names;
1173    Parameter currentParameter;
1174//    Object[] values;
1175  }//class ParameterDisjunction
1176
1177  class ParameterDisjunctionEditor extends DefaultCellEditor {
1178    public ParameterDisjunctionEditor(){
1179      super(new JComboBox());
1180      combo = (JComboBox)super.getComponent();
1181      setClickCountToStart(1);
1182      combo.setRenderer(new CustomRenderer());
1183    }//public ParameterDisjunctionEditor()
1184      class CustomRenderer extends JLabel implements ListCellRenderer {
1185        public CustomRenderer(){
1186          setOpaque(true);
1187        }
1188
1189        public Component getListCellRendererComponent(JList list,
1190                                                      Object value,
1191                                                      int index,
1192                                                      boolean isSelected,
1193                                                      boolean cellHasFocus){
1194          if (isSelected) {
1195              setBackground(list.getSelectionBackground());
1196              setForeground(list.getSelectionForeground());
1197          }
1198          else {
1199              setBackground(list.getBackground());
1200              setForeground(list.getForeground());
1201          }
1202
1203          setFont(list.getFont());
1204
1205          setText((String)value);
1206
1207          String iconName = "param.gif";
1208          Object[] params = pDisj.getParameters();
1209          for(int i = 0; i < params.length; i++){
1210            Parameter param = (Parameter)params[i];
1211            if(param.getName().equals(value)){
1212              String type = param.getTypeName();
1213              if(Gate.getCreoleRegister().containsKey(type)){
1214                ResourceData rData = (ResourceData)
1215                                     Gate.getCreoleRegister().get(type);
1216                if(rData != null) iconName = rData.getIcon();
1217              }
1218              break;
1219            }//if(params[i].getName().equals(value))
1220          }//for(int i = 0; params.length; i++)
1221
1222          setIcon(MainFrame.getIcon(iconName));
1223          return this;
1224        }
1225      };//class CustomRenderer extends JLabel implements ListCellRenderer
1226
1227    public Component getTreeCellEditorComponent(JTree tree,
1228                                                Object value,
1229                                                boolean isSelected,
1230                                                boolean expanded,
1231                                                boolean leaf,
1232                                                int row){
1233     pDisj = (ParameterDisjunction)((DefaultMutableTreeNode)value).
1234                                    getUserObject();
1235     combo.setModel(new DefaultComboBoxModel(pDisj.getNames()));
1236     combo.setSelectedItem(pDisj.getName());
1237     return combo;
1238    }//public Component getTreeCellEditorComponent
1239
1240    public Object getCellEditorValue(){
1241      return new Integer(combo.getSelectedIndex());
1242    }
1243
1244    JComboBox combo;
1245    ParameterDisjunction pDisj;
1246  }//class ParameterDisjunctionEditor
1247
1248  class ParameterValueRenderer extends ObjectRenderer {
1249    public Component getTableCellRendererComponent(JTable table,
1250                                               Object value,
1251                                               boolean isSelected,
1252                                               boolean hasFocus,
1253                                               int row,
1254                                               int column){
1255      //value = ((DefaultMutableTreeNode)value).getUserObject();
1256      if(value instanceof NameBearer){
1257        String name = (String)
1258                        ((NameBearer)value).getName();
1259        if(name != null){
1260          return super.getTableCellRendererComponent(table, name, isSelected,
1261                                                     hasFocus, row, column);
1262        }
1263      }
1264      return super.getTableCellRendererComponent(table, value, isSelected,
1265                                                 hasFocus, row, column);
1266    }//public Component getTableCellRendererComponent
1267  }//class ParameterValueRenderer
1268
1269  class ParameterValueEditor extends AbstractCellEditor
1270                             implements TableCellEditor{
1271    ParameterValueEditor(){
1272      combo = new JComboBox();
1273      textField = new JTextField();
1274      button = new JButton(new ImageIcon(getClass().getResource(
1275                               "/gate/resources/img/loadFile.gif")));
1276      button.setToolTipText("Set from file...");
1277      button.addActionListener(new ActionListener() {
1278        public void actionPerformed(ActionEvent e) {
1279          JFileChooser fileChooser = MainFrame.getFileChooser();
1280          int res = fileChooser.showOpenDialog(ApplicationEditor.this);
1281          if(res == fileChooser.APPROVE_OPTION){
1282            try {
1283              textField.setText(fileChooser.getSelectedFile().
1284                                toURL().toExternalForm());
1285            } catch(IOException ioe){}
1286          }
1287        }
1288      });
1289      textButtonBox = Box.createHorizontalBox();
1290      textButtonBox.add(textField, button);
1291    }//ParameterValueEditor()
1292
1293    public Component getTableCellEditorComponent(JTable table,
1294                                                 Object value,
1295                                                 boolean isSelected,
1296                                                 int row,
1297                                                 int column){
1298
1299      type = ((ParameterDisjunction)
1300              ((DefaultMutableTreeNode)
1301              mainTreeTable.getTree().getPathForRow(row).getLastPathComponent())
1302              .getUserObject()).getType();
1303      ResourceData rData = (ResourceData)Gate.getCreoleRegister().get(type);
1304      if(rData != null){
1305        //Gate type
1306        combo.setModel(new DefaultComboBoxModel(
1307                                          rData.getInstantiations().toArray()));
1308        combo.setSelectedItem(value);
1309        combo.setRenderer(new ComboRenderer());
1310        comboUsed = true;
1311        return combo;
1312      }else{
1313        if(value != null) textField.setText(value.toString());
1314        comboUsed = false;
1315        if(type.equals("java.net.URL")){
1316          return textButtonBox;
1317        }else return textField;
1318      }
1319    }//getTableCellEditorComponent
1320
1321    public Object getCellEditorValue(){
1322      if(comboUsed) return combo.getSelectedItem();
1323      else return textField.getText();
1324    }//public Object getCellEditorValue()
1325
1326    class ComboRenderer extends DefaultListCellRenderer {
1327      public Component getListCellRendererComponent(JList list,
1328                                                    Object value,
1329                                                    int index,
1330                                                    boolean isSelected,
1331                                                    boolean cellHasFocus){
1332        if(value instanceof NameBearer){
1333          String name = (String)(
1334                          (NameBearer)value).getName();
1335          if(name != null){
1336            return super.getListCellRendererComponent(list, name, index,
1337                                                      isSelected, cellHasFocus);
1338          }
1339        }
1340        return super.getListCellRendererComponent(list, value, index,
1341                                                   isSelected, cellHasFocus);
1342      }//public Component getListCellRendererComponent
1343    }//class ComboRenderer
1344
1345    String type;
1346    JComboBox combo;
1347    JTextField textField;
1348    boolean comboUsed;
1349    JButton button;
1350    Box textButtonBox;
1351  }//class ParameterValueEditor
1352/*
1353  XJTable prsTable;
1354  XJTable paramsTable;
1355  PRListTableModel prsTableModel;
1356  PRParametersTableModel paramsTableModel;
1357*/
1358
1359  SerialController controller;
1360  List prList;
1361  Handle handle;
1362  JTreeTable mainTreeTable;
1363  PRsAndParamsTTModel mainTTModel;
1364  //JPopupMenu popup;
1365  JMenu addMenu;
1366  JMenu removeMenu;
1367
1368  XJTable modulesTable;
1369  ModulesTableModel modulesTableModel;
1370  JButton addModuleBtn;
1371  JButton removeModuleBtn;
1372  JButton upBtn;
1373  JButton downBtn;
1374  JButton runBtn;
1375  Action runAction;
1376
1377  /**
1378   * maps from ProcessingResource to List of ParameterDisjunction
1379   */
1380  Map paramsForPR;
1381//  /**
1382//   * Maps from pr to AddPRAction
1383//   */
1384//  Map addActionForPR;
1385//  Map removeActionForPR;
1386  private transient Vector statusListeners;
1387  private transient Vector progressListeners;
1388
1389  public void resourceLoaded(CreoleEvent e) {
1390    if(e.getResource() instanceof ProcessingResource){
1391      modulesTableModel.fireTableDataChanged();
1392    }else{
1393      //this will trigger the seting of the parameters to the new default
1394      mainTreeTable.repaint();
1395    }
1396  }// public void resourceLoaded
1397
1398  public void resourceUnloaded(CreoleEvent e) {
1399    Resource res = e.getResource();
1400    if(res instanceof ProcessingResource){
1401      if(prList.contains(res)){
1402        new RemovePRAction((ProcessingResource)res).actionPerformed(null);
1403        Enumeration enum = ((DefaultMutableTreeNode)mainTTModel.getRoot()).
1404                           children();
1405        if(enum.hasMoreElements()){
1406          DefaultMutableTreeNode node =
1407            (DefaultMutableTreeNode)enum.nextElement();
1408          while(enum.hasMoreElements() && node.getUserObject() != res){
1409            node = (DefaultMutableTreeNode)enum.nextElement();
1410          }
1411          if(node.getUserObject() == res){
1412            mainTTModel.removeNodeFromParent(node);
1413          }
1414        }//(DefaultMutableTreeNode)enum.nextElement();
1415      }else{
1416        modulesTableModel.fireTableDataChanged();
1417      }
1418    }//if(res instanceof ProcessingResource)
1419    //all types of resources could be parameter values
1420    Iterator parListsIter = paramsForPR.values().iterator();
1421    while(parListsIter.hasNext()){
1422      //each value is a list of ParameterDisjunctions
1423      List pdList = (List)parListsIter.next();
1424      if(pdList != null){
1425        Iterator pdIter = pdList.iterator();
1426        while(pdIter.hasNext()){
1427          //each value is a ParameterDisjunction
1428          ParameterDisjunction pd = (ParameterDisjunction)pdIter.next();
1429          if(pd.getValue() == res) pd.clearValue();
1430        }//while(pdIter.hasNext())
1431      }//if(pdLIst != null)
1432    }//while(parListsIter.hasNext())
1433    mainTreeTable.repaint();
1434  }//public void resourceUnloaded(CreoleEvent e)
1435
1436  public void datastoreOpened(CreoleEvent e) {
1437  }
1438  public void datastoreCreated(CreoleEvent e) {
1439  }
1440  public void datastoreClosed(CreoleEvent e) {
1441  }
1442  public synchronized void removeStatusListener(StatusListener l) {
1443    if (statusListeners != null && statusListeners.contains(l)) {
1444      Vector v = (Vector) statusListeners.clone();
1445      v.removeElement(l);
1446      statusListeners = v;
1447    }
1448  }//removeStatusListener
1449
1450  public synchronized void addStatusListener(StatusListener l) {
1451    Vector v = statusListeners == null ? new Vector(2) : (Vector) statusListeners.clone();
1452    if (!v.contains(l)) {
1453      v.addElement(l);
1454      statusListeners = v;
1455    }
1456  }//addStatusListener
1457
1458  protected void fireStatusChanged(String e) {
1459    if (statusListeners != null) {
1460      Vector listeners = statusListeners;
1461      int count = listeners.size();
1462      for (int i = 0; i < count; i++) {
1463        ((StatusListener) listeners.elementAt(i)).statusChanged(e);
1464      }
1465    }
1466  }//addStatusListener
1467
1468  public synchronized void removeProgressListener(ProgressListener l) {
1469    if (progressListeners != null && progressListeners.contains(l)) {
1470      Vector v = (Vector) progressListeners.clone();
1471      v.removeElement(l);
1472      progressListeners = v;
1473    }
1474  }//removeProgressListener
1475
1476  public synchronized void addProgressListener(ProgressListener l) {
1477    Vector v = progressListeners == null ? new Vector(2) : (Vector) progressListeners.clone();
1478    if (!v.contains(l)) {
1479      v.addElement(l);
1480      progressListeners = v;
1481    }
1482  }//addProgressListener
1483
1484  protected void fireProgressChanged(int e) {
1485    if (progressListeners != null) {
1486      Vector listeners = progressListeners;
1487      int count = listeners.size();
1488      for (int i = 0; i < count; i++) {
1489        ((ProgressListener) listeners.elementAt(i)).progressChanged(e);
1490      }
1491    }
1492  }//fireProgressChanged
1493
1494  protected void fireProcessFinished() {
1495    if (progressListeners != null) {
1496      Vector listeners = progressListeners;
1497      int count = listeners.size();
1498      for (int i = 0; i < count; i++) {
1499        ((ProgressListener) listeners.elementAt(i)).processFinished();
1500      }
1501    }
1502  }//fireProcessFinished
1503
1504
1505  /**
1506   * A simple progress listener used to forward the events upstream.
1507   */
1508  protected class InternalProgressListener implements ProgressListener{
1509    public void progressChanged(int i){
1510      fireProgressChanged(i);
1511    }
1512
1513    public void processFinished(){
1514      fireProcessFinished();
1515    }
1516  }//InternalProgressListener
1517
1518  /**
1519   * A simple status listener used to forward the events upstream.
1520   */
1521  protected class InternalStatusListener implements StatusListener{
1522    public void statusChanged(String message){
1523      fireStatusChanged(message);
1524    }
1525  }//InternalStatusListener
1526
1527
1528/*
1529  class PRListTableModel extends AbstractTableModel{
1530    public int getRowCount(){
1531      return controller.size() + 1;
1532    }
1533
1534    public int getColumnCount(){
1535      return 2;
1536    }
1537
1538    public String getColumnName(int columnIndex){
1539      switch (columnIndex){
1540        case 0: return "Processing resource";
1541        case 1: return "Type";
1542        default: return "?";
1543      }
1544    }
1545
1546    public Class getColumnClass(int columnIndex){
1547      switch (columnIndex){
1548        case 0: return ProcessingResource.class;
1549        case 1: return String.class;
1550        default: return Object.class;
1551      }
1552    }
1553
1554    public boolean isCellEditable(int rowIndex, int columnIndex){
1555      return columnIndex == 0;// && rowIndex == controller.size();
1556    }
1557
1558    public Object getValueAt(int rowIndex, int columnIndex){
1559      if(rowIndex >= controller.size()){
1560        switch (columnIndex){
1561          case 0: return null;
1562          case 1: return "- no type -";
1563          default: return Object.class;
1564        }
1565      }
1566      switch (columnIndex){
1567        case 0: return controller.get(rowIndex);
1568        case 1: return ((ProcessingResource)controller.get(rowIndex)).getClass().toString();
1569        default: return Object.class;
1570      }
1571    }
1572
1573    public void setValueAt(Object aValue,
1574                       int rowIndex,
1575                       int columnIndex){
1576      if(columnIndex == 0){
1577        if(rowIndex >= controller.size()){
1578          if(aValue != null) controller.add(aValue);
1579        }else{
1580          if(aValue != null) controller.set(rowIndex, aValue);
1581          else controller.remove(rowIndex);
1582        }
1583      }
1584    }
1585
1586  }//class PRListTableModel extends AbstractTableModel
1587*/
1588/*
1589  class PRRenderer extends DefaultTableCellRenderer{
1590    public Component getTableCellRendererComponent(JTable table,
1591                                                   Object value,
1592                                                   boolean isSelected,
1593                                                   boolean hasFocus,
1594                                                   int row,
1595                                                   int column){
1596
1597      String name = null;
1598      if(value != null){
1599        ProcessingResource res = (ProcessingResource) value;
1600        name = (String)res.getName();
1601        if(name == null){
1602          name = "No name: " + res.getClass().toString();
1603        }
1604      }else{
1605        name = "< Add new... >";
1606      }
1607      return super.getTableCellRendererComponent(table, name, isSelected,
1608                                                 hasFocus, 0, 0);
1609    }
1610  }
1611*/
1612/*
1613  class PREditor extends DefaultCellEditor{
1614    public PREditor(){
1615      super(new JComboBox());
1616      combo = (JComboBox)getComponent();
1617      prsByName = new TreeMap();
1618      setClickCountToStart(2);
1619    }
1620
1621    public Component getTableCellEditorComponent(JTable table,
1622                                             Object value,
1623                                             boolean isSelected,
1624                                             int row,
1625                                             int column){
1626
1627      prsByName.clear();
1628      Iterator prsIter = project.getPRList().iterator();
1629      while(prsIter.hasNext()){
1630        PRHandle handle = (PRHandle)prsIter.next();
1631        ProcessingResource pr = (ProcessingResource)handle.resource;
1632        String prName = (String)handle.resource.getName();
1633        if(prName == null){
1634          prName = "No name: " + pr.getClass().toString();
1635        }
1636        prsByName.put(prName, pr);
1637      }//while(prsIter.hasNext())
1638      if(prsByName.isEmpty()) return null;
1639      prsByName.put("< Delete! >", null);
1640      combo.setModel(new DefaultComboBoxModel(prsByName.keySet().toArray()));
1641      if(value != null){
1642        //select the current value
1643        try{
1644          String currentName = (String)((ProcessingResource)value).getName();
1645          if(prsByName.containsKey(currentName)){
1646            combo.setSelectedItem(currentName);
1647          }
1648        }catch(Exception e){}
1649      }else{
1650        combo.setSelectedItem("< Delete! >");
1651      }
1652      return super.getTableCellEditorComponent(table, value, isSelected,
1653                                               row, column);
1654    }
1655
1656    public Object getCellEditorValue(){
1657      if(prsByName == null || combo.getSelectedItem() == null) return null;
1658      ProcessingResource res = (ProcessingResource)prsByName.get(combo.getSelectedItem());
1659      return res;
1660    }
1661
1662    JComboBox combo;
1663    Map prsByName;
1664  }//class PREditor extends DefaultCellEditor
1665*/
1666/*
1667  class PRParametersTableModel extends AbstractTableModel{
1668    public int getRowCount(){
1669      return controller.size();
1670    }
1671
1672    public int getColumnCount(){
1673      return 4;
1674    }
1675
1676    public String getColumnName(int columnIndex){
1677      switch (columnIndex){
1678        case 0: return "Processing resource";
1679        case 1: return "Parameter name";
1680        case 2: return "Type";
1681        case 3: return "Value";
1682        default: return "?";
1683      }
1684    }
1685
1686    public Class getColumnClass(int columnIndex){
1687      switch (columnIndex){
1688        case 0: return ProcessingResource.class;
1689        case 1: return String.class;
1690        case 2: return String.class;
1691        case 3: return String.class;
1692        default: return Object.class;
1693      }
1694    }
1695
1696    public boolean isCellEditable(int rowIndex, int columnIndex){
1697      return columnIndex == 3;
1698    }
1699
1700    public Object getValueAt(int rowIndex, int columnIndex){
1701      return null;
1702    }
1703
1704    public void setValueAt(Object aValue,
1705                       int rowIndex,
1706                       int columnIndex){
1707    }
1708  }//class PRParametersTableModel
1709*/
1710}//ApplicationViewer
1711