View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  /*****************************************************************************
25  * OrganisationPanel.java
26  *
27  * Panel through which agent relationships are specified
28  ***************************************************************************/
29  
30  package zeus.generator.agent;
31  
32  import java.awt.*;
33  import java.awt.event.*;
34  import java.util.*;
35  import javax.swing.*;
36  import javax.swing.table.*;
37  import javax.swing.border.*;
38  import javax.swing.event.*;
39  
40  import zeus.util.*;
41  import zeus.concepts.*;
42  import zeus.generator.*;
43  import zeus.generator.util.*;
44  import zeus.ontology.*;
45  import zeus.gui.fields.*;
46  import zeus.gui.help.*;
47  
48  public class OrganisationPanel extends JPanel {
49  
50    static final String[] ERROR_MESSAGE = {
51       /* 0 */ "Please select a row before\ncalling this operation"
52    };
53  
54    protected ControlPanel       controlPane;
55    protected AgentDescription   agent;
56    protected AcquaintanceModel  acquaintanceModel;
57    protected JTable             acquaintanceTable;
58    protected AbilityModel       abilityModel;
59    protected JTable             abilityTable;
60    protected AgentGenerator     generator;
61    protected GeneratorModel     genmodel;
62    protected OntologyDb         ontologyDb;
63    protected AgentEditor        editor;
64    protected AbilitySpec[]      clipboard = null;
65    protected FactToolBar        factToolBar;
66  
67    public OrganisationPanel(AgentGenerator generator,
68                             GeneratorModel genmodel,
69                             OntologyDb ontologyDb,
70                             AgentEditor editor,
71                             AgentDescription agent)  {
72  
73       this.agent = agent;
74       this.generator = generator;
75       this.genmodel = genmodel;
76       this.editor = editor;
77       this.ontologyDb = ontologyDb;
78  
79       GridBagLayout gridBagLayout = new GridBagLayout();
80       GridBagConstraints gbc = new GridBagConstraints();
81       setLayout(gridBagLayout);
82       setBackground(Color.lightGray);
83  	
84       setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
85       controlPane = new ControlPanel(editor,"Agent Organisation Panel",false,false);
86  	
87       JPanel acquaintancePanel = new JPanel();	
88       JPanel dataPanel = new JPanel();
89   
90       gbc.gridwidth = GridBagConstraints.REMAINDER;
91       gbc.anchor = GridBagConstraints.NORTHWEST;
92       gbc.fill = GridBagConstraints.HORIZONTAL;
93       gbc.insets = new Insets(8,8,8,8);
94       gridBagLayout.setConstraints(controlPane,gbc);
95       add(controlPane);
96  
97       // Add the panel containing the other agents table to the panel.
98       gbc.anchor = GridBagConstraints.NORTHEAST;
99       gbc.fill = GridBagConstraints.BOTH;
100      gbc.gridwidth = GridBagConstraints.REMAINDER;
101      gbc.insets = new Insets(8,8,8,8);
102      gbc.weightx = gbc.weighty = 1;
103      gridBagLayout.setConstraints(acquaintancePanel,gbc);
104      add(acquaintancePanel);
105 
106      // Add the panel containing the known suppliers
107      gbc.anchor = GridBagConstraints.SOUTH;
108      gbc.fill = GridBagConstraints.BOTH;
109      gbc.insets = new Insets(8,8,8,8);
110      gbc.weightx = gbc.weighty = 1;
111      gridBagLayout.setConstraints(dataPanel,gbc);
112      add(dataPanel);
113 
114      // Create acquaintance info area
115      AttributeModel attributeModel = new AttributeModel();
116      AttributeTable attributeTable = new AttributeTable(attributeModel);
117      abilityModel = new AbilityModel(ontologyDb,attributeModel);
118      acquaintanceModel = new AcquaintanceModel(genmodel,ontologyDb,
119         abilityModel,agent.getAcquaintances());
120 
121      attributeModel.addChangeListener(editor);
122      abilityModel.addChangeListener(editor);
123      acquaintanceModel.addChangeListener(editor);
124 
125      TableColumnModel tm = new DefaultTableColumnModel();
126      TableColumn column;
127      column = new TableColumn(AcquaintanceModel.AGENT,12,
128         new DefaultTableCellRenderer(),
129 	new DefaultCellEditor(new NameField()));
130      column.setHeaderValue(acquaintanceModel.getColumnName(AcquaintanceModel.AGENT));
131      tm.addColumn(column);
132      column = new TableColumn(AcquaintanceModel.RELATION,12,
133         new DefaultTableCellRenderer(), new RelationEditor());
134      column.setHeaderValue(acquaintanceModel.getColumnName(AcquaintanceModel.RELATION));
135      tm.addColumn(column);
136 
137      acquaintanceTable = new JTable(acquaintanceModel,tm);
138      acquaintanceTable.getTableHeader().setReorderingAllowed(false);
139      acquaintanceTable.setColumnSelectionAllowed(false);
140 
141      ListSelectionModel selectionModel = acquaintanceTable.getSelectionModel();
142      selectionModel.addListSelectionListener(new SymListAction1());
143 
144      JScrollPane scrollPane = new JScrollPane(acquaintanceTable);
145      scrollPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
146      scrollPane.setPreferredSize(new Dimension(340,120));
147      acquaintanceTable.setBackground(Color.white);
148 
149      gridBagLayout = new GridBagLayout();
150      acquaintancePanel.setLayout(gridBagLayout);
151      acquaintancePanel.setBackground(Color.lightGray);
152 
153      acquaintanceTable.setMinimumSize(new Dimension(400,140));
154 
155      TitledBorder border = BorderFactory.createTitledBorder("Acquaintances");
156      border.setTitlePosition(TitledBorder.TOP);
157      border.setTitleJustification(TitledBorder.RIGHT);
158      border.setTitleFont(new Font("Helvetica", Font.BOLD, 14));
159      border.setTitleColor(java.awt.Color.blue);
160      acquaintancePanel.setBorder(border);
161 
162      JToolBar toolbar = new AcquaintanceToolBar();
163      gbc = new GridBagConstraints();
164      gbc.anchor = GridBagConstraints.WEST;
165      gbc.fill = GridBagConstraints.NONE;
166      gbc.gridwidth = GridBagConstraints.REMAINDER;
167      gbc.insets = new Insets(0,8,0,0);
168      gridBagLayout.setConstraints(toolbar,gbc);
169      acquaintancePanel.add(toolbar);
170 
171      gbc = new GridBagConstraints();
172      gbc.gridwidth = GridBagConstraints.REMAINDER;     
173      gbc.anchor = GridBagConstraints.WEST;
174      gbc.fill = GridBagConstraints.BOTH;
175      gbc.weightx = gbc.weighty = 1;
176      gbc.insets = new Insets(8,8,8,8);
177      gridBagLayout.setConstraints(scrollPane,gbc);
178      acquaintancePanel.add(scrollPane);
179 
180      // Create data info area     
181      tm = new DefaultTableColumnModel();     
182      column = new TableColumn(AbilityModel.TYPE,12);
183      column.setHeaderValue(abilityModel.getColumnName(AbilityModel.TYPE));
184      tm.addColumn(column);
185      column = new TableColumn(AbilityModel.COST,12,     
186         new DefaultTableCellRenderer(),
187         new DefaultCellEditor(new RealNumberField()));
188      column.setHeaderValue(abilityModel.getColumnName(AbilityModel.COST));
189      tm.addColumn(column);
190      column = new TableColumn(AbilityModel.TIME,12,     
191         new DefaultTableCellRenderer(),
192         new DefaultCellEditor(new WholeNumberField()));
193      column.setHeaderValue(abilityModel.getColumnName(AbilityModel.TIME));
194      tm.addColumn(column);
195 
196      abilityTable = new JTable(abilityModel,tm);
197      abilityTable.getTableHeader().setReorderingAllowed(false);
198      abilityTable.setColumnSelectionAllowed(false);
199 
200      selectionModel = abilityTable.getSelectionModel();
201      selectionModel.addListSelectionListener(new SymListAction2());
202 
203      scrollPane = new JScrollPane(abilityTable);
204      scrollPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
205      scrollPane.setPreferredSize(new Dimension(400,100));
206      abilityTable.setBackground(Color.white);
207 
208      gridBagLayout = new GridBagLayout();
209      dataPanel.setLayout(gridBagLayout);
210      dataPanel.setBackground(Color.lightGray);
211 
212      abilityTable.setMinimumSize(new Dimension(400,120));
213      attributeTable.setMinimumSize(new Dimension(400,140));
214 
215      border = BorderFactory.createTitledBorder("Acquaintance Abilities");
216      border.setTitlePosition(TitledBorder.TOP);
217      border.setTitleJustification(TitledBorder.RIGHT);
218      border.setTitleFont(new Font("Helvetica", Font.BOLD, 14));
219      border.setTitleColor(Color.blue);
220      dataPanel.setBorder(border);
221 
222      factToolBar = new FactToolBar();
223      factToolBar.setEnabled(false);
224 
225      gbc = new GridBagConstraints();
226      gbc.anchor = GridBagConstraints.WEST;
227      gbc.fill = GridBagConstraints.NONE;
228      gbc.gridwidth = GridBagConstraints.REMAINDER;
229      gbc.insets = new Insets(0,8,0,0);
230      gridBagLayout.setConstraints(factToolBar,gbc);
231      dataPanel.add(factToolBar);
232 
233      gbc.gridwidth = GridBagConstraints.REMAINDER;
234      gbc.anchor = GridBagConstraints.WEST;
235      gbc.fill = GridBagConstraints.BOTH;
236      gbc.weightx = gbc.weighty = 1;
237      gbc.insets = new Insets(8,8,8,8);
238      gridBagLayout.setConstraints(scrollPane,gbc);
239      dataPanel.add(scrollPane);
240 
241      gbc.gridwidth = GridBagConstraints.REMAINDER;
242      gbc.anchor = GridBagConstraints.WEST;
243      gbc.fill = GridBagConstraints.BOTH;
244      gbc.weightx = gbc.weighty = 1;
245      gbc.insets = new Insets(8,8,8,8);
246      gridBagLayout.setConstraints(attributeTable,gbc);
247      dataPanel.add(attributeTable);
248   }
249 
250   // Begin inner classes
251 
252   class AcquaintanceToolBar extends JToolBar implements ActionListener {
253      protected JToggleButton  helpBtn, allBtn, peerBtn, nonpeerBtn;
254      protected HelpWindow     helpWin;
255      protected JButton        resetBtn;
256      protected JButton        newBtn;
257      protected JButton        editBtn;
258      protected JButton        deleteBtn;
259      protected JPopupMenu     popup;
260      protected JMenuItem      addMenuItem;
261 
262      public AcquaintanceToolBar() {
263         setBackground(Color.lightGray);
264         setBorder(new BevelBorder(BevelBorder.LOWERED));
265         setFloatable(false);
266         String path = SystemProps.getProperty("gif.dir") + "generator" +
267            System.getProperty("file.separator");
268 
269         // new Button
270         newBtn = new JButton(new ImageIcon(path + "new1.gif"));
271 	newBtn.setMargin(new Insets(0,0,0,0));		
272         add(newBtn);
273         newBtn.setToolTipText("New acquaintance");    
274         newBtn.addActionListener(this);
275         addSeparator();
276 
277         editBtn = new JButton(new ImageIcon(path + "edit1.gif"));
278 	editBtn.setMargin(new Insets(0,0,0,0));	
279         add(editBtn);
280         editBtn.setToolTipText("Edit this acquaintance");
281         editBtn.addActionListener(this);
282    
283         deleteBtn = new JButton(new ImageIcon(path + "delete1.gif"));
284 	deleteBtn.setMargin(new Insets(0,0,0,0));
285         add(deleteBtn);
286         deleteBtn.setToolTipText("Delete this acquaintance");
287         deleteBtn.addActionListener(this);
288    
289         addSeparator();
290        
291         // Reset Button
292         resetBtn = new JButton(new ImageIcon(path + "reset.gif" ));
293 	resetBtn.setMargin(new Insets(0,0,0,0));	
294         add(resetBtn);
295         resetBtn.setToolTipText("Reset acquaintance to peer");    
296         resetBtn.addActionListener(this);
297         addSeparator();
298     
299         ButtonGroup group = new ButtonGroup();
300     
301         // All Button
302         allBtn = new JToggleButton(new ImageIcon(path + "all.gif"), true);
303 	allBtn.setMargin(new Insets(0,0,0,0));
304         add(allBtn);
305         allBtn.setToolTipText("Show all acquaintances");
306         allBtn.addActionListener(this);
307         group.add(allBtn);
308     
309         // Peers Button
310         peerBtn = new JToggleButton(new ImageIcon(path + "peers.gif"));
311 	peerBtn.setMargin(new Insets(0,0,0,0));	
312         add(peerBtn);
313         peerBtn.setToolTipText("Show peers only");
314         peerBtn.addActionListener(this);
315         group.add(peerBtn);
316     
317         // Non-Peers Button
318         nonpeerBtn = new JToggleButton(new ImageIcon(path + "others.gif"));
319 	nonpeerBtn.setMargin(new Insets(0,0,0,0));	
320         add(nonpeerBtn);
321         nonpeerBtn.setToolTipText("Show non-peers only");
322         nonpeerBtn.addActionListener(this);
323         group.add(nonpeerBtn);
324     
325         addSeparator();
326 
327         // Help Button
328         helpBtn = new JToggleButton(new ImageIcon(path + "help.gif"));
329 	helpBtn.setMargin(new Insets(0,0,0,0));	
330         add(helpBtn);
331         helpBtn.setToolTipText("Help");
332         helpBtn.addActionListener(this);
333 
334         // ---- Popup Menu for Acquaintances ----
335         popup = new JPopupMenu("Add new acquaintance");
336         addMenuItem = new JMenuItem("Create new acquaintance");
337         addMenuItem.addActionListener(this);
338 
339         CompoundBorder cbr = new CompoundBorder(new EtchedBorder(),
340                                                 new EmptyBorder(5,5,5,5));
341         popup.setBorder(cbr);
342      }
343 
344      public void actionPerformed(ActionEvent e) {
345         Object src = e.getSource();
346 
347         if ( src == newBtn ) {
348            popup.removeAll();
349            popup.add(addMenuItem);
350            popup.addSeparator();
351 
352            String[] items = genmodel.getAgentNames();
353            Vector names = new Vector();
354            names.addElement(editor.getObjectName());
355            for(int i = 0; i < acquaintanceModel.getRowCount(); i++ ) 
356               names.addElement(acquaintanceModel.getValueAt(i,AcquaintanceModel.AGENT));
357            Vector allNames = Misc.stringVector(items);
358            Vector validNames = Misc.difference(allNames,names);
359 
360            JMenuItem mi;
361            for(int i = 0; i < validNames.size(); i++ ) {
362               mi = new JMenuItem((String)validNames.elementAt(i));
363               mi.addActionListener(this);
364               mi.setActionCommand("NEW_ACQUAINTANCE");
365               popup.add(mi);
366            }
367            popup.pack();
368            popup.show(newBtn,0,0);
369         }
370         else if ( src == addMenuItem )
371            addNewAcquaintance();
372         else if ( e.getActionCommand().equals("NEW_ACQUAINTANCE") )
373            addNewAcquaintance(((JMenuItem)src).getText());         
374         else if ( src == editBtn )
375            editAcquaintance();
376         else if ( src == deleteBtn )
377            removeAcquaintance();
378         if ( src == resetBtn )
379            resetAcquaintance();
380         else if ( src == allBtn )
381            acquaintanceModel.setFilter(AcquaintanceModel.ALL);
382         else if ( src == peerBtn )
383            acquaintanceModel.setFilter(AcquaintanceModel.PEERS);
384         else if ( src == nonpeerBtn )
385            acquaintanceModel.setFilter(AcquaintanceModel.OTHERS);
386         else if ( src == helpBtn ) {
387            if (helpBtn.isSelected() ) {
388               Point dispos = getLocation();
389               helpWin = new HelpWindow(SwingUtilities.getRoot(this),
390                  dispos, "generator", "Activity Org-1");
391               helpWin.setSource(helpBtn);
392            }
393            else {
394               helpWin.dispose();
395            }
396         }
397      }
398   }
399 
400   class FactToolBar extends JToolBar
401                     implements ActionListener,
402                                FactSelector {
403 
404      protected FactDialog    factWin;
405      protected HelpWindow    helpWin;
406      protected JToggleButton helpBtn;
407      protected JButton       newBtn;
408      protected JButton       deleteBtn;
409      protected JButton       cutBtn;
410      protected JButton       copyBtn;
411      protected JButton       pasteBtn;
412     
413      public FactToolBar() {
414         setBackground(Color.lightGray);
415         setBorder(new BevelBorder(BevelBorder.LOWERED));
416         setFloatable(false);
417     
418         String sep = System.getProperty("file.separator");
419         String path = SystemProps.getProperty("gif.dir") + "generator" + sep;
420 
421         // New Button
422         newBtn = new JButton(new ImageIcon(path + "new1.gif"));
423 	newBtn.setMargin(new Insets(0,0,0,0));	
424         add(newBtn);
425         newBtn.setToolTipText("New");    
426         newBtn.addActionListener(this);
427 
428         // Delete Button
429         deleteBtn = new JButton(new ImageIcon(path + "delete1.gif"));
430 	deleteBtn.setMargin(new Insets(0,0,0,0));	
431         add(deleteBtn);
432         deleteBtn.setToolTipText("Delete");
433         deleteBtn.addActionListener(this);
434 
435         addSeparator();
436      
437         // Cut Button
438         cutBtn = new JButton(new ImageIcon(path + "cut.gif"));
439 	cutBtn.setMargin(new Insets(0,0,0,0));	
440         add(cutBtn);
441         cutBtn.setToolTipText("Cut");
442         cutBtn.addActionListener(this);
443 
444         // Copy Button
445         copyBtn = new JButton(new ImageIcon(path + "copy.gif"));
446 	copyBtn.setMargin(new Insets(0,0,0,0));	
447         add(copyBtn);
448         copyBtn.setToolTipText("Copy");
449         copyBtn.addActionListener(this);
450 
451         // Paste Button
452         pasteBtn = new JButton(new ImageIcon(path + "paste.gif"));
453 	pasteBtn.setMargin(new Insets(0,0,0,0));	
454         add(pasteBtn);
455         pasteBtn.setToolTipText("Paste");
456         pasteBtn.addActionListener(this);
457       
458         addSeparator();
459       
460         // Help Button
461         helpBtn = new JToggleButton(new ImageIcon(path + "help.gif"));
462 	helpBtn.setMargin(new Insets(0,0,0,0));
463         add(helpBtn);
464         helpBtn.setToolTipText("Help");
465         helpBtn.addActionListener(this);
466 
467         factWin = new FactDialog(editor, ontologyDb); 
468      }
469   
470      public void setEnabled(boolean set) {
471         newBtn.setEnabled(set);
472         deleteBtn.setEnabled(set);
473         cutBtn.setEnabled(set);
474         copyBtn.setEnabled(set);
475         pasteBtn.setEnabled(set);
476      }
477 
478      public void factSelected(String[] names)  {
479         // Fact Selector callback to add new entries
480         abilityModel.addNewRows(names);
481      }
482 
483      public void actionPerformed(ActionEvent e)  {
484         Object src = e.getSource();
485         if ( src == newBtn ) {
486            factWin.setLocationRelativeTo(newBtn);
487            factWin.display(this);
488         }
489         else if ( src == deleteBtn ) {
490            deleteSelectedAbilities();
491         }  
492         else if ( src == copyBtn ) {
493            clipboard = getSelectedAbilities();
494         }
495         else if ( src == pasteBtn ) {
496            abilityModel.addRows(clipboard);
497            abilityTable.clearSelection();
498         }
499         else if ( src == cutBtn ) {
500            clipboard = cutSelectedAbilities();
501         }
502         else if ( src == helpBtn ) {
503           if ( helpBtn.isSelected() ) {
504               Point dispos = getLocation();
505               helpWin = new HelpWindow(editor, dispos, "generator", "Activity Org-2");
506               helpWin.setSource(helpBtn);
507           }
508           else
509               helpWin.dispose();
510         }
511      }
512   }
513 
514   class RelationEditor extends DefaultCellEditor {
515      public RelationEditor() {
516         super( new JComboBox(AcquaintanceModel.RELATIONS_LIST) {
517                       public void contentsChanged(ListDataEvent e) {
518                          selectedItemReminder = null; 
519                          super.contentsChanged(e);
520                       }
521                }
522         );
523         setClickCountToStart(2);
524      }
525   }
526 
527   class SymListAction1 implements ListSelectionListener {
528      public void valueChanged(ListSelectionEvent e) {
529         int row = acquaintanceTable.getSelectedRow();
530         acquaintanceModel.selectRow(row);
531         factToolBar.setEnabled(row != -1);
532         repaint(); // swing bug?
533      }
534   }
535 
536   class SymListAction2 implements ListSelectionListener {
537      public void valueChanged(ListSelectionEvent e) {
538         abilityModel.selectRow(abilityTable.getSelectedRow());
539         repaint(); // swing bug?
540      }
541   }
542 
543   // End of inner classes
544 
545   void errorMsg(int tag) {
546      JOptionPane.showMessageDialog(this,ERROR_MESSAGE[tag],
547                                    "Error", JOptionPane.ERROR_MESSAGE);
548   }
549 
550   protected void resetAcquaintance() {
551      int row = acquaintanceTable.getSelectedRow();
552      if (row == -1) {
553         errorMsg(0);
554         return;
555      }
556      acquaintanceModel.setValueAt(
557         SystemProps.getProperty("organisation.relations.default"),
558         row,AcquaintanceModel.RELATION);
559   } 
560 
561   protected String getSelectedAcquaintanceName() {
562     int row = acquaintanceTable.getSelectedRow();
563     if ( row == -1 ) {
564        errorMsg(0);
565        return null;
566     }
567     return (String)acquaintanceModel.getValueAt(row,AcquaintanceModel.AGENT);
568   }
569 
570   protected String getSelectedAcquaintanceId() {
571     int row = acquaintanceTable.getSelectedRow();
572     if ( row == -1 ) {
573        errorMsg(0);
574        return null;
575     }
576     return (String)acquaintanceModel.getValueAt(row,AcquaintanceModel.ID);
577   }
578   
579   protected void addNewAcquaintance() {
580     acquaintanceModel.addNewRow();
581     factToolBar.setEnabled(false);
582   }
583 
584   protected void addNewAcquaintance(String name) {
585     acquaintanceModel.addNewRow(name);
586     factToolBar.setEnabled(false);
587   }
588 
589   protected void editAcquaintance() {
590     String id = getSelectedAcquaintanceId();
591     if ( id == null ) return;
592     generator.editAgent(id);
593   }
594 
595   protected void removeAcquaintance() {
596     int row = acquaintanceTable.getSelectedRow();
597     if ( row == -1 ) {
598        errorMsg(0);
599        return;
600     }
601     acquaintanceModel.removeRow(row);
602     factToolBar.setEnabled(false);
603     repaint(); // swing bug?
604   }
605 
606   protected void reset(Acquaintance[] data) {
607      acquaintanceModel.reset(data);
608      factToolBar.setEnabled(false);
609   }
610   
611   protected Acquaintance[] getData() {
612      return acquaintanceModel.getData();
613   }
614   
615   protected AbilitySpec[] getSelectedAbilities()  {
616     int[] srows = abilityTable.getSelectedRows();
617     AbilitySpec[] data = new AbilitySpec[srows.length];
618     for(int i = 0; i < srows.length; i++)
619        data[i] = (AbilitySpec)abilityModel.getValueAt(srows[i],AbilityModel.ABILITY);
620     return data;
621   }
622   
623   protected AbilitySpec[] cutSelectedAbilities()  {
624      AbilitySpec[] data = getSelectedAbilities();
625      abilityModel.removeRows(abilityTable.getSelectedRows());
626      repaint(); // swing bug?
627      return data;
628   }
629  
630   protected void deleteSelectedAbilities()  {
631      int row = abilityTable.getSelectedRow();
632      if ( row == -1 ) {
633         errorMsg(0);
634         return;
635      }
636      cutSelectedAbilities();
637   }
638 
639   public void save() {
640      agent.setAcquaintances(acquaintanceModel.getData());
641   }
642 }