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