0f4cf5f0b7da83fc828ac2a47332e18ccf090bc3
[jalview.git] / src / jalview / gui / DasSourceBrowser.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.jbgui.*;\r
22 import javax.swing.table.AbstractTableModel;\r
23 import javax.swing.event.*;\r
24 import jalview.util.TableSorter;\r
25 import java.awt.event.*;\r
26 import javax.swing.*;\r
27 import java.util.*;\r
28 \r
29 \r
30 import org.biojava.dasobert.dasregistry.DasCoordinateSystem;\r
31 import org.biojava.dasobert.dasregistry.DasSource;\r
32 import org.biojava.dasobert.dasregistry.Das1Source;\r
33 import java.awt.BorderLayout;\r
34 \r
35 public class DasSourceBrowser extends GDasSourceBrowser\r
36     implements Runnable, ListSelectionListener\r
37 {\r
38   static DasSource[] dasSources = null;\r
39 \r
40   Hashtable localSources = null;\r
41 \r
42   Vector selectedSources;\r
43 \r
44   public DasSourceBrowser()\r
45   {\r
46     registryURL.setText(jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
47         "http://www.spice-3d.org/dasregistry/das1/sources") );\r
48 \r
49     setSelectedFromProperties();\r
50 \r
51     displayFullDetails(null);\r
52     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
53 \r
54     capabilities.addListSelectionListener(this);\r
55     coords1.addListSelectionListener(this);\r
56     coords2.addListSelectionListener(this);\r
57 \r
58     //Ask to be notified of selection changes.\r
59     ListSelectionModel rowSM = table.getSelectionModel();\r
60     rowSM.addListSelectionListener(new ListSelectionListener()\r
61     {\r
62       public void valueChanged(ListSelectionEvent e)\r
63       {\r
64         //Ignore extra messages.\r
65         if (e.getValueIsAdjusting())\r
66           return;\r
67 \r
68         ListSelectionModel lsm = (ListSelectionModel) e.getSource();\r
69         if (!lsm.isSelectionEmpty())\r
70         {\r
71           int selectedRow = lsm.getMinSelectionIndex();\r
72           displayFullDetails(table.getValueAt(selectedRow, 0).toString());\r
73         }\r
74       }\r
75     });\r
76 \r
77     table.addMouseListener(new MouseAdapter()\r
78         {\r
79           public void mouseClicked(MouseEvent evt)\r
80           {\r
81             if(evt.getClickCount()==2\r
82                || SwingUtilities.isRightMouseButton(evt))\r
83               editRemoveLocalSource(evt);\r
84           }\r
85         });\r
86 \r
87     if(dasSources==null)\r
88     {\r
89     Thread worker = new Thread(this);\r
90     worker.start();\r
91     }\r
92     else\r
93      {\r
94        init();\r
95      }\r
96   }\r
97 \r
98   void init()\r
99   {\r
100     int dSize = dasSources.length;\r
101     Object[][] data = new Object[dSize][2];\r
102     for (int i = 0; i < dSize; i++)\r
103     {\r
104       data[i][0] = dasSources[i].getNickname();\r
105       data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
106           getNickname()));\r
107     }\r
108 \r
109     refreshTableData(data);\r
110     setCapabilities(dasSources);\r
111 \r
112     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
113         {\r
114           public void run()\r
115           {\r
116             TableSorter sorter = (TableSorter)table.getModel();\r
117             sorter.setSortingStatus(1, TableSorter.DESCENDING);\r
118             sorter.setSortingStatus(1, TableSorter.NOT_SORTED);\r
119           }\r
120         });\r
121 \r
122     progressBar.setIndeterminate(false);\r
123     progressBar.setVisible(false);\r
124     addLocal.setVisible(true);\r
125     refresh.setVisible(true);\r
126   }\r
127 \r
128 \r
129   public void refreshTableData(Object[][] data)\r
130   {\r
131     TableSorter sorter = new TableSorter(new DASTableModel(data));\r
132     sorter.setTableHeader(table.getTableHeader());\r
133     table.setModel(sorter);\r
134   }\r
135 \r
136   void displayFullDetails(String nickName)\r
137   {\r
138 \r
139     StringBuffer text = new StringBuffer(\r
140         "<HTML><font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\">");\r
141 \r
142     if (nickName == null)\r
143     {\r
144       fullDetails.setText(text +\r
145                           "Select a DAS service from the table"\r
146                           + " to read a full description here.</font></html>");\r
147       return;\r
148     }\r
149 \r
150     int dSize = dasSources.length;\r
151     for (int i = 0; i < dSize; i++)\r
152     {\r
153       if (!dasSources[i].getNickname().equals(nickName))\r
154         continue;\r
155 \r
156       DasSource ds = dasSources[i];\r
157 \r
158       text.append("<font color=\"#0000FF\">Id:</font> " + dasSources[i].getId() +\r
159                   "<br>");\r
160       text.append("<font color=\"#0000FF\">Nickname:</font> " +\r
161                   dasSources[i].getNickname() + "<br>");\r
162       text.append("<font color=\"#0000FF\">URL:</font> " + dasSources[i].getUrl() +\r
163                   "<br>");\r
164 \r
165       text.append("<font color=\"#0000FF\">Admin Email:</font> <a href=\"mailto:"\r
166                   +dasSources[i].getAdminemail()\r
167                   +"\">"+dasSources[i].getAdminemail()+"</a>" +\r
168                   "<br>");\r
169 \r
170 \r
171       text.append("<font color=\"#0000FF\">Registered at:</font> " + dasSources[i].getRegisterDate() +\r
172                         "<br>");\r
173 \r
174       text.append("<font color=\"#0000FF\">Last successful test:</font> " + dasSources[i].getLeaseDate() +\r
175                         "<br>");\r
176 \r
177       text.append("<font color=\"#0000FF\">Labels:</font> ");\r
178       for(int s=0; s<dasSources[i].getLabels().length; s++)\r
179       {\r
180         text.append( dasSources[i].getLabels()[s]);\r
181         if(s<dasSources[i].getLabels().length-1)\r
182           text.append(",");\r
183         text.append(" ");\r
184       }\r
185       text.append("<br>");\r
186 \r
187 \r
188 \r
189       text.append("<font color=\"#0000FF\">Capabilities:</font> ");\r
190       String[] scap = dasSources[i].getCapabilities();\r
191       for (int j = 0; j < scap.length; j++)\r
192       {\r
193         text.append(scap[j]);\r
194         if (j < scap.length - 1)\r
195           text.append(", ");\r
196       }\r
197       text.append("<br>");\r
198 \r
199       text.append("<font color=\"#0000FF\">Coordinates:</font> ");\r
200       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
201       for (int j = 0; j < dcs.length; j++)\r
202       {\r
203         text.append("(" + dcs[j].getUniqueId() + ") "\r
204                     + dcs[j].getCategory() + ", " + dcs[j].getName());\r
205         if (dcs[j].getNCBITaxId() != 0)\r
206           text.append(", " + dcs[j].getNCBITaxId());\r
207         if (dcs[j].getOrganismName().length() > 0)\r
208           text.append(", " + dcs[j].getOrganismName());\r
209 \r
210         text.append("<br>");\r
211       }\r
212 \r
213       text.append("<font color=\"#0000FF\">Description:</font> " +\r
214                   dasSources[i].getDescription() + "<br>");\r
215 \r
216 \r
217       if (dasSources[i].getHelperurl()!=null\r
218           && dasSources[i].getHelperurl().length() > 0)\r
219       {\r
220         text.append("<font color=\"#0000FF\"><a href=\"" +\r
221                     dasSources[i].getHelperurl()\r
222                     + "\">Go to site</a></font<br>");\r
223       }\r
224 \r
225       text.append("</font></html>");\r
226 \r
227       break;\r
228     }\r
229 \r
230     fullDetails.setText(text.toString());\r
231     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
232     {\r
233       public void run()\r
234       {\r
235         fullDetailsScrollpane.getVerticalScrollBar().setValue(0);\r
236       }\r
237     });\r
238   }\r
239 \r
240 \r
241   public void run()\r
242   {\r
243     addLocal.setVisible(false);\r
244     refresh.setVisible(false);\r
245     progressBar.setVisible(true);\r
246     progressBar.setIndeterminate(true);\r
247 \r
248     dasSources = jalview.io.DasSequenceFeatureFetcher.getDASSources();\r
249 \r
250     appendLocalSources();\r
251 \r
252     init();\r
253   }\r
254 \r
255   public DasSource[] getDASSource()\r
256   {\r
257     if(dasSources==null)\r
258     {\r
259      dasSources = jalview.io.DasSequenceFeatureFetcher.getDASSources();\r
260      appendLocalSources();\r
261     }\r
262 \r
263     return dasSources;\r
264   }\r
265 \r
266   public void refresh_actionPerformed(ActionEvent e)\r
267   {\r
268     saveProperties(jalview.bin.Cache.applicationProperties);\r
269 \r
270     Thread worker = new Thread(this);\r
271     worker.start();\r
272   }\r
273 \r
274   private void setCapabilities(DasSource[] sources)\r
275   {\r
276     Vector vcapabilities = new Vector();\r
277     Vector vcoords = new Vector();\r
278     Vector vcoords2 = new Vector();\r
279 \r
280     vcapabilities.addElement("All");\r
281     vcoords.addElement("All");\r
282     vcoords2.addElement("All");\r
283 \r
284     for (int i = 0; i < sources.length; i++)\r
285     {\r
286       DasSource ds = sources[i];\r
287       String[] scap = ds.getCapabilities();\r
288       for (int s = 0; s < scap.length; s++)\r
289       {\r
290         if (!vcapabilities.contains(scap[s]))\r
291         {\r
292           vcapabilities.addElement(scap[s]);\r
293         }\r
294       }\r
295 \r
296       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
297 \r
298       for (int j = 0; j < dcs.length; j++)\r
299       {\r
300         if (!vcoords.contains(dcs[j].getCategory()))\r
301           vcoords.addElement(dcs[j].getCategory());\r
302 \r
303         if (!vcoords2.contains(dcs[j].getName()))\r
304           vcoords2.addElement(dcs[j].getName());\r
305       }\r
306     }\r
307 \r
308     capabilities.setListData(vcapabilities);\r
309     coords1.setListData(vcoords);\r
310     coords2.setListData(vcoords2);\r
311 \r
312     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
313     {\r
314       public void run()\r
315       {\r
316         capabilities.setSelectedIndex(0);\r
317         coords1.setSelectedIndex(0);\r
318         coords2.setSelectedIndex(0);\r
319       }\r
320     });\r
321   }\r
322 \r
323   public void amendLocal(boolean newSource)\r
324   {\r
325     String url = "http://localhost:8080/", nickname = "";\r
326 \r
327     if(!newSource)\r
328     {\r
329       int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
330       nickname = table.getValueAt(selectedRow, 0).toString();\r
331       url = ((DasSource)localSources.get(nickname)).getUrl();\r
332     }\r
333 \r
334     JTextField nametf = new JTextField(nickname, 40);\r
335     JTextField urltf = new JTextField(url, 40);\r
336 \r
337     JPanel panel = new JPanel(new BorderLayout());\r
338     JPanel pane12 = new JPanel(new BorderLayout());\r
339     pane12.add(new JLabel("Nickname: "), BorderLayout.CENTER);\r
340     pane12.add(nametf, BorderLayout.EAST);\r
341     panel.add(pane12, BorderLayout.NORTH);\r
342     pane12 = new JPanel(new BorderLayout());\r
343     pane12.add(new JLabel("URL: "), BorderLayout.CENTER);\r
344     pane12.add(urltf, BorderLayout.EAST);\r
345     panel.add(pane12, BorderLayout.SOUTH);\r
346 \r
347 \r
348     int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
349         panel, "Enter Nickname & URL of Local DAS Source",\r
350         JOptionPane.OK_CANCEL_OPTION);\r
351 \r
352        if (reply != JOptionPane.OK_OPTION )\r
353        {\r
354            return;\r
355        }\r
356 \r
357        if(!urltf.getText().endsWith("/"))\r
358          urltf.setText(urltf.getText()+"/");\r
359 \r
360        Das1Source local = new Das1Source();\r
361 \r
362        local.setUrl(urltf.getText());\r
363        local.setNickname(nametf.getText());\r
364 \r
365 \r
366        if(localSources==null)\r
367          localSources = new Hashtable();\r
368 \r
369        localSources.put(local.getNickname(), local);\r
370 \r
371        if(!newSource && !nickname.equals(nametf.getText()))\r
372        {\r
373          localSources.remove(nickname);\r
374        }\r
375 \r
376        int size = dasSources.length;\r
377        int adjust = newSource ? 1 : 0;\r
378 \r
379        Object[][] data = new Object[size+adjust][2];\r
380        for (int i = 0; i < size; i++)\r
381        {\r
382          if(!newSource && dasSources[i].getNickname().equals(nickname))\r
383          {\r
384            ((DasSource)dasSources[i]).setNickname(local.getNickname());\r
385            ((DasSource)dasSources[i]).setUrl(local.getUrl());\r
386            data[i][0] = local.getNickname();\r
387            data[i][1] = new Boolean(true);\r
388          }\r
389          else\r
390          {\r
391            data[i][0] = dasSources[i].getNickname();\r
392            data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
393                getNickname()));\r
394          }\r
395        }\r
396 \r
397        if(newSource)\r
398        {\r
399          data[size][0] = local.getNickname();\r
400          data[size][1] = new Boolean(true);\r
401          selectedSources.add(local.getNickname());\r
402        }\r
403 \r
404        DasSource [] tmp = new DasSource[size+adjust];\r
405 \r
406        System.arraycopy(dasSources, 0, tmp, 0, size);\r
407 \r
408        if(newSource)\r
409          tmp[size] = local;\r
410 \r
411        dasSources = tmp;\r
412 \r
413        refreshTableData(data);\r
414 \r
415        SwingUtilities.invokeLater(new Runnable()\r
416        {\r
417          public void run()\r
418          {\r
419            scrollPane.getVerticalScrollBar().setValue(\r
420                scrollPane.getVerticalScrollBar().getMaximum()\r
421                );\r
422          }\r
423        });\r
424 \r
425        displayFullDetails(local.getNickname());\r
426      }\r
427 \r
428     public void editRemoveLocalSource(MouseEvent evt)\r
429     {\r
430       int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
431       if(selectedRow==-1)\r
432         return;\r
433 \r
434       String nickname = table.getValueAt(selectedRow, 0).toString();\r
435 \r
436       if (!localSources.containsKey(nickname))\r
437       {\r
438         JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
439         "You can only edit or remove local DAS Sources!",\r
440          "Public DAS source - not editable",\r
441          JOptionPane.WARNING_MESSAGE);\r
442         return;\r
443       }\r
444 \r
445 \r
446       Object[] options = {"Edit", "Remove", "Cancel"};\r
447       int choice = JOptionPane.showInternalOptionDialog(Desktop.desktop,\r
448     "Do you want to edit or remove "+nickname+"?",\r
449     "Edit / Remove Local DAS Source",\r
450     JOptionPane.YES_NO_CANCEL_OPTION,\r
451     JOptionPane.QUESTION_MESSAGE,\r
452     null,\r
453     options,\r
454     options[2]);\r
455 \r
456       switch(choice)\r
457       {\r
458         case 0: amendLocal(false);   break;\r
459         case 1:\r
460           localSources.remove(nickname);\r
461           selectedSources.remove(nickname);\r
462           Object[][] data = new Object[dasSources.length-1][2];\r
463           DasSource [] tmp = new DasSource[dasSources.length-1];\r
464           int index = 0;\r
465           for (int i = 0; i < dasSources.length; i++)\r
466           {\r
467             if (dasSources[i].getNickname().equals(nickname))\r
468             {\r
469               continue;\r
470             }\r
471             else\r
472             {\r
473               tmp[index] = dasSources[i];\r
474               data[index][0] = dasSources[i].getNickname();\r
475               data[index][1] = new Boolean(selectedSources.contains(dasSources[i].\r
476                   getNickname()));\r
477               index++;\r
478             }\r
479           }\r
480            dasSources = tmp;\r
481            refreshTableData(data);\r
482            SwingUtilities.invokeLater(new Runnable()\r
483            {\r
484              public void run()\r
485              {\r
486                scrollPane.getVerticalScrollBar().setValue(\r
487                    scrollPane.getVerticalScrollBar().getMaximum()\r
488                    );\r
489              }\r
490            });\r
491 \r
492           break;\r
493       }\r
494     }\r
495 \r
496     void appendLocalSources()\r
497     {\r
498       if(localSources==null)\r
499         return;\r
500 \r
501       int size = dasSources!=null ? dasSources.length : 0;\r
502       int lsize = localSources.size();\r
503 \r
504       Object[][] data = new Object[size+lsize][2];\r
505       for (int i = 0; i < size; i++)\r
506       {\r
507         data[i][0] = dasSources[i].getNickname();\r
508         data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
509             getNickname()));\r
510       }\r
511 \r
512       DasSource [] tmp = new DasSource[size+lsize];\r
513       if(dasSources!=null)\r
514         System.arraycopy(dasSources, 0, tmp, 0, size);\r
515 \r
516       Enumeration en = localSources.keys();\r
517       int index = size;\r
518       while(en.hasMoreElements())\r
519       {\r
520         String key = en.nextElement().toString();\r
521         data[index][0] = key;\r
522         data[index][1] = new Boolean(false);\r
523         tmp[index] = new Das1Source();\r
524         tmp[index].setNickname(key);\r
525         tmp[index].setUrl( ((DasSource)localSources.get(key)).getUrl() );\r
526 \r
527         index++;\r
528       }\r
529 \r
530          dasSources = tmp;\r
531 \r
532          refreshTableData(data);\r
533   }\r
534 \r
535   public void valueChanged(ListSelectionEvent evt)\r
536   {\r
537     //Called when the MainTable selection changes\r
538     if (evt.getValueIsAdjusting())\r
539     {\r
540       return;\r
541     }\r
542 \r
543     displayFullDetails(null);\r
544 \r
545     // Filter the displayed data sources\r
546     int dSize = dasSources.length;\r
547     ArrayList names = new ArrayList();\r
548     ArrayList selected = new ArrayList();\r
549     DasSource ds;\r
550 \r
551     // capabilities.get\r
552     for (int i = 0; i < dSize; i++)\r
553     {\r
554       ds = dasSources[i];\r
555 \r
556       if (!selectedInList(capabilities, ds.getCapabilities()))\r
557       {\r
558         continue;\r
559       }\r
560 \r
561       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
562       for (int j = 0; j < dcs.length; j++)\r
563       {\r
564         if (selectedInList(coords1, new String[]\r
565                            {dcs[j].getCategory()})\r
566             && selectedInList(coords2, new String[]\r
567                               {dcs[j].getName()}))\r
568         {\r
569           names.add(ds.getNickname());\r
570           selected.add(new Boolean(\r
571               selectedSources.contains(ds.getNickname())));\r
572           break;\r
573         }\r
574       }\r
575     }\r
576 \r
577     dSize = names.size();\r
578     Object[][] data = new Object[dSize][2];\r
579     for (int d = 0; d < dSize; d++)\r
580     {\r
581       data[d][0] = names.get(d);\r
582       data[d][1] = selected.get(d);\r
583     }\r
584 \r
585     refreshTableData(data);\r
586   }\r
587 \r
588   boolean selectedInList(JList list, String[] items)\r
589   {\r
590     Object[] selection = list.getSelectedValues();\r
591     for (int i = 0; i < selection.length; i++)\r
592     {\r
593       if (selection[i].equals("All"))\r
594         return true;\r
595 \r
596       for (int j = 0; j < items.length; j++)\r
597       {\r
598         if (selection[i].equals(items[j]))\r
599           return true;\r
600       }\r
601     }\r
602 \r
603     return false;\r
604   }\r
605 \r
606   void setSelectedFromProperties()\r
607   {\r
608      String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");\r
609      StringTokenizer st = new StringTokenizer(active, "\t");\r
610      selectedSources = new Vector();\r
611      while(st.hasMoreTokens())\r
612      {\r
613        selectedSources.addElement(st.nextToken());\r
614      }\r
615 \r
616      String local = jalview.bin.Cache.getProperty("DAS_LOCAL_SOURCE");\r
617      if(local!=null)\r
618      {\r
619        if(localSources == null)\r
620          localSources = new Hashtable();\r
621 \r
622        st = new StringTokenizer(local, "\t");\r
623        while(st.hasMoreTokens())\r
624        {\r
625          String token = st.nextToken();\r
626          int bar = token.indexOf("|");\r
627          Das1Source source = new Das1Source();\r
628 \r
629          source.setUrl(token.substring(bar + 1));\r
630          source.setNickname(token.substring(0, bar));\r
631 \r
632          localSources.put(source.getNickname(), source);\r
633        }\r
634      }\r
635   }\r
636 \r
637   void saveProperties(Properties properties)\r
638   {\r
639     properties.setProperty("DAS_REGISTRY_URL", registryURL.getText());\r
640 \r
641     StringBuffer sb = new StringBuffer();\r
642     for(int r=0; r<table.getModel().getRowCount(); r++)\r
643     {\r
644       if( ((Boolean)table.getValueAt(r,1)).booleanValue())\r
645       {\r
646         sb.append(table.getValueAt(r,0)+"\t");\r
647       }\r
648     }\r
649 \r
650     properties.setProperty("DAS_ACTIVE_SOURCE", sb.toString() );\r
651 \r
652     if(localSources!=null)\r
653     {\r
654       sb = new StringBuffer();\r
655       Enumeration en = localSources.keys();\r
656       while(en.hasMoreElements())\r
657       {\r
658         String token = en.nextElement().toString();\r
659         sb.append(token+"|"\r
660                   + ((DasSource)localSources.get(token)).getUrl()\r
661                   +"\t");\r
662       }\r
663 \r
664       properties.setProperty("DAS_LOCAL_SOURCE", sb.toString());\r
665     }\r
666 \r
667   }\r
668 \r
669   class DASTableModel\r
670       extends AbstractTableModel\r
671   {\r
672 \r
673     public DASTableModel(Object[][] data)\r
674     {\r
675       this.data = data;\r
676     }\r
677 \r
678     private String[] columnNames = new String[]  {"Nickname", "Use Source"};\r
679 \r
680     private Object[][] data;\r
681 \r
682     public int getColumnCount()\r
683     {\r
684       return columnNames.length;\r
685     }\r
686 \r
687     public int getRowCount()\r
688     {\r
689       return data.length;\r
690     }\r
691 \r
692     public String getColumnName(int col)\r
693     {\r
694       return columnNames[col];\r
695     }\r
696 \r
697     public Object getValueAt(int row, int col)\r
698     {\r
699       return data[row][col];\r
700     }\r
701 \r
702     /*\r
703      * JTable uses this method to determine the default renderer/\r
704      * editor for each cell.  If we didn't implement this method,\r
705      * then the last column would contain text ("true"/"false"),\r
706      * rather than a check box.\r
707      */\r
708     public Class getColumnClass(int c)\r
709     {\r
710       return getValueAt(0, c).getClass();\r
711     }\r
712 \r
713     /*\r
714      * Don't need to implement this method unless your table's\r
715      * editable.\r
716      */\r
717     public boolean isCellEditable(int row, int col)\r
718     {\r
719       //Note that the data/cell address is constant,\r
720       //no matter where the cell appears onscreen.\r
721       return col == 1;\r
722 \r
723     }\r
724 \r
725     /*\r
726      * Don't need to implement this method unless your table's\r
727      * data can change.\r
728      */\r
729     public void setValueAt(Object value, int row, int col)\r
730     {\r
731       data[row][col] = value;\r
732       fireTableCellUpdated(row, col);\r
733 \r
734       String name = getValueAt(row,0).toString();\r
735       boolean selected = ((Boolean)value).booleanValue();\r
736 \r
737       if(selectedSources.contains(name) && !selected)\r
738         selectedSources.remove(name);\r
739 \r
740       if(!selectedSources.contains(name) && selected)\r
741         selectedSources.add(name);\r
742     }\r
743   }\r
744 }\r
745 \r
746 \r