sequences are private in SequenceGroup
[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     filter1.addListSelectionListener(this);\r
55     filter2.addListSelectionListener(this);\r
56     filter3.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 authority = new Vector();\r
277     Vector type = new Vector();\r
278     Vector label = new Vector();\r
279 \r
280     authority.addElement("Any");\r
281     type.addElement("Any");\r
282     label.addElement("Any");\r
283     label.addElement("NOT IMPLEMENTED YET");\r
284     filter3.setEnabled(false);\r
285 \r
286     for (int i = 0; i < sources.length; i++)\r
287     {\r
288       DasSource ds = sources[i];\r
289 \r
290       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
291 \r
292       for (int j = 0; j < dcs.length; j++)\r
293       {\r
294         if (!type.contains(dcs[j].getCategory()))\r
295           type.addElement(dcs[j].getCategory());\r
296 \r
297         if (!authority.contains(dcs[j].getName()))\r
298           authority.addElement(dcs[j].getName());\r
299       }\r
300 \r
301       String[] slabels = ds.getLabels();\r
302       for (int s = 0; s < slabels.length; s++)\r
303       {\r
304         if (!label.contains(slabels[s]))\r
305         {\r
306           label.addElement(slabels[s]);\r
307         }\r
308       }\r
309 \r
310     }\r
311 \r
312     filter1.setListData(authority);\r
313     filter2.setListData(type);\r
314     filter3.setListData(label);\r
315 \r
316     javax.swing.SwingUtilities.invokeLater(new Runnable()\r
317     {\r
318       public void run()\r
319       {\r
320         filter1.setSelectedIndex(0);\r
321         filter2.setSelectedIndex(0);\r
322         filter3.setSelectedIndex(0);\r
323       }\r
324     });\r
325   }\r
326 \r
327   public void amendLocal(boolean newSource)\r
328   {\r
329     String url = "http://localhost:8080/", nickname = "";\r
330 \r
331     if(!newSource)\r
332     {\r
333       int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
334       nickname = table.getValueAt(selectedRow, 0).toString();\r
335       url = ((DasSource)localSources.get(nickname)).getUrl();\r
336     }\r
337 \r
338     JTextField nametf = new JTextField(nickname, 40);\r
339     JTextField urltf = new JTextField(url, 40);\r
340 \r
341     JPanel panel = new JPanel(new BorderLayout());\r
342     JPanel pane12 = new JPanel(new BorderLayout());\r
343     pane12.add(new JLabel("Nickname: "), BorderLayout.CENTER);\r
344     pane12.add(nametf, BorderLayout.EAST);\r
345     panel.add(pane12, BorderLayout.NORTH);\r
346     pane12 = new JPanel(new BorderLayout());\r
347     pane12.add(new JLabel("URL: "), BorderLayout.CENTER);\r
348     pane12.add(urltf, BorderLayout.EAST);\r
349     panel.add(pane12, BorderLayout.SOUTH);\r
350 \r
351 \r
352     int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
353         panel, "Enter Nickname & URL of Local DAS Source",\r
354         JOptionPane.OK_CANCEL_OPTION);\r
355 \r
356        if (reply != JOptionPane.OK_OPTION )\r
357        {\r
358            return;\r
359        }\r
360 \r
361        if(!urltf.getText().endsWith("/"))\r
362          urltf.setText(urltf.getText()+"/");\r
363 \r
364        Das1Source local = new Das1Source();\r
365 \r
366        local.setUrl(urltf.getText());\r
367        local.setNickname(nametf.getText());\r
368 \r
369 \r
370        if(localSources==null)\r
371          localSources = new Hashtable();\r
372 \r
373        localSources.put(local.getNickname(), local);\r
374 \r
375        if(!newSource && !nickname.equals(nametf.getText()))\r
376        {\r
377          localSources.remove(nickname);\r
378        }\r
379 \r
380        int size = dasSources.length;\r
381        int adjust = newSource ? 1 : 0;\r
382 \r
383        Object[][] data = new Object[size+adjust][2];\r
384        for (int i = 0; i < size; i++)\r
385        {\r
386          if(!newSource && dasSources[i].getNickname().equals(nickname))\r
387          {\r
388            ((DasSource)dasSources[i]).setNickname(local.getNickname());\r
389            ((DasSource)dasSources[i]).setUrl(local.getUrl());\r
390            data[i][0] = local.getNickname();\r
391            data[i][1] = new Boolean(true);\r
392          }\r
393          else\r
394          {\r
395            data[i][0] = dasSources[i].getNickname();\r
396            data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
397                getNickname()));\r
398          }\r
399        }\r
400 \r
401        if(newSource)\r
402        {\r
403          data[size][0] = local.getNickname();\r
404          data[size][1] = new Boolean(true);\r
405          selectedSources.add(local.getNickname());\r
406        }\r
407 \r
408        DasSource [] tmp = new DasSource[size+adjust];\r
409 \r
410        System.arraycopy(dasSources, 0, tmp, 0, size);\r
411 \r
412        if(newSource)\r
413          tmp[size] = local;\r
414 \r
415        dasSources = tmp;\r
416 \r
417        refreshTableData(data);\r
418 \r
419        SwingUtilities.invokeLater(new Runnable()\r
420        {\r
421          public void run()\r
422          {\r
423            scrollPane.getVerticalScrollBar().setValue(\r
424                scrollPane.getVerticalScrollBar().getMaximum()\r
425                );\r
426          }\r
427        });\r
428 \r
429        displayFullDetails(local.getNickname());\r
430      }\r
431 \r
432     public void editRemoveLocalSource(MouseEvent evt)\r
433     {\r
434       int selectedRow = table.getSelectionModel().getMinSelectionIndex();\r
435       if(selectedRow==-1)\r
436         return;\r
437 \r
438       String nickname = table.getValueAt(selectedRow, 0).toString();\r
439 \r
440       if (!localSources.containsKey(nickname))\r
441       {\r
442         JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
443         "You can only edit or remove local DAS Sources!",\r
444          "Public DAS source - not editable",\r
445          JOptionPane.WARNING_MESSAGE);\r
446         return;\r
447       }\r
448 \r
449 \r
450       Object[] options = {"Edit", "Remove", "Cancel"};\r
451       int choice = JOptionPane.showInternalOptionDialog(Desktop.desktop,\r
452     "Do you want to edit or remove "+nickname+"?",\r
453     "Edit / Remove Local DAS Source",\r
454     JOptionPane.YES_NO_CANCEL_OPTION,\r
455     JOptionPane.QUESTION_MESSAGE,\r
456     null,\r
457     options,\r
458     options[2]);\r
459 \r
460       switch(choice)\r
461       {\r
462         case 0: amendLocal(false);   break;\r
463         case 1:\r
464           localSources.remove(nickname);\r
465           selectedSources.remove(nickname);\r
466           Object[][] data = new Object[dasSources.length-1][2];\r
467           DasSource [] tmp = new DasSource[dasSources.length-1];\r
468           int index = 0;\r
469           for (int i = 0; i < dasSources.length; i++)\r
470           {\r
471             if (dasSources[i].getNickname().equals(nickname))\r
472             {\r
473               continue;\r
474             }\r
475             else\r
476             {\r
477               tmp[index] = dasSources[i];\r
478               data[index][0] = dasSources[i].getNickname();\r
479               data[index][1] = new Boolean(selectedSources.contains(dasSources[i].\r
480                   getNickname()));\r
481               index++;\r
482             }\r
483           }\r
484            dasSources = tmp;\r
485            refreshTableData(data);\r
486            SwingUtilities.invokeLater(new Runnable()\r
487            {\r
488              public void run()\r
489              {\r
490                scrollPane.getVerticalScrollBar().setValue(\r
491                    scrollPane.getVerticalScrollBar().getMaximum()\r
492                    );\r
493              }\r
494            });\r
495 \r
496           break;\r
497       }\r
498     }\r
499 \r
500     void appendLocalSources()\r
501     {\r
502       if(localSources==null)\r
503         return;\r
504 \r
505       int size = dasSources!=null ? dasSources.length : 0;\r
506       int lsize = localSources.size();\r
507 \r
508       Object[][] data = new Object[size+lsize][2];\r
509       for (int i = 0; i < size; i++)\r
510       {\r
511         data[i][0] = dasSources[i].getNickname();\r
512         data[i][1] = new Boolean(selectedSources.contains(dasSources[i].\r
513             getNickname()));\r
514       }\r
515 \r
516       DasSource [] tmp = new DasSource[size+lsize];\r
517       if(dasSources!=null)\r
518         System.arraycopy(dasSources, 0, tmp, 0, size);\r
519 \r
520       Enumeration en = localSources.keys();\r
521       int index = size;\r
522       while(en.hasMoreElements())\r
523       {\r
524         String key = en.nextElement().toString();\r
525         data[index][0] = key;\r
526         data[index][1] = new Boolean(false);\r
527         tmp[index] = new Das1Source();\r
528         tmp[index].setNickname(key);\r
529         tmp[index].setUrl( ((DasSource)localSources.get(key)).getUrl() );\r
530 \r
531         index++;\r
532       }\r
533 \r
534          dasSources = tmp;\r
535 \r
536          refreshTableData(data);\r
537   }\r
538 \r
539   public void valueChanged(ListSelectionEvent evt)\r
540   {\r
541     //Called when the MainTable selection changes\r
542     if (evt.getValueIsAdjusting())\r
543     {\r
544       return;\r
545     }\r
546 \r
547     displayFullDetails(null);\r
548 \r
549     // Filter the displayed data sources\r
550     int dSize = dasSources.length;\r
551     ArrayList names = new ArrayList();\r
552     ArrayList selected = new ArrayList();\r
553     DasSource ds;\r
554 \r
555     // capabilities.get\r
556     for (int i = 0; i < dSize; i++)\r
557     {\r
558       ds = dasSources[i];\r
559 \r
560       if (!selectedInList(filter3, ds.getLabels()))\r
561       {\r
562         continue;\r
563       }\r
564 \r
565       DasCoordinateSystem[] dcs = ds.getCoordinateSystem();\r
566       for (int j = 0; j < dcs.length; j++)\r
567       {\r
568         if (selectedInList(filter1, new String[]\r
569                            {dcs[j].getName()})\r
570             && selectedInList(filter2, new String[]\r
571                               {dcs[j].getCategory()}))\r
572         {\r
573           names.add(ds.getNickname());\r
574           selected.add(new Boolean(\r
575               selectedSources.contains(ds.getNickname())));\r
576           break;\r
577         }\r
578       }\r
579     }\r
580 \r
581     dSize = names.size();\r
582     Object[][] data = new Object[dSize][2];\r
583     for (int d = 0; d < dSize; d++)\r
584     {\r
585       data[d][0] = names.get(d);\r
586       data[d][1] = selected.get(d);\r
587     }\r
588 \r
589     refreshTableData(data);\r
590   }\r
591 \r
592   boolean selectedInList(JList list, String[] items)\r
593   {\r
594     Object[] selection = list.getSelectedValues();\r
595     for (int i = 0; i < selection.length; i++)\r
596     {\r
597       if (selection[i].equals("Any"))\r
598         return true;\r
599 \r
600       for (int j = 0; j < items.length; j++)\r
601       {\r
602         if (selection[i].equals(items[j]))\r
603           return true;\r
604       }\r
605     }\r
606 \r
607     return false;\r
608   }\r
609 \r
610   void setSelectedFromProperties()\r
611   {\r
612      String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE", "uniprot");\r
613      StringTokenizer st = new StringTokenizer(active, "\t");\r
614      selectedSources = new Vector();\r
615      while(st.hasMoreTokens())\r
616      {\r
617        selectedSources.addElement(st.nextToken());\r
618      }\r
619 \r
620      String local = jalview.bin.Cache.getProperty("DAS_LOCAL_SOURCE");\r
621      if(local!=null)\r
622      {\r
623        if(localSources == null)\r
624          localSources = new Hashtable();\r
625 \r
626        st = new StringTokenizer(local, "\t");\r
627        while(st.hasMoreTokens())\r
628        {\r
629          String token = st.nextToken();\r
630          int bar = token.indexOf("|");\r
631          Das1Source source = new Das1Source();\r
632 \r
633          source.setUrl(token.substring(bar + 1));\r
634          source.setNickname(token.substring(0, bar));\r
635 \r
636          localSources.put(source.getNickname(), source);\r
637        }\r
638      }\r
639   }\r
640 \r
641   void saveProperties(Properties properties)\r
642   {\r
643     properties.setProperty("DAS_REGISTRY_URL", registryURL.getText());\r
644 \r
645     StringBuffer sb = new StringBuffer();\r
646     for(int r=0; r<table.getModel().getRowCount(); r++)\r
647     {\r
648       if( ((Boolean)table.getValueAt(r,1)).booleanValue())\r
649       {\r
650         sb.append(table.getValueAt(r,0)+"\t");\r
651       }\r
652     }\r
653 \r
654     properties.setProperty("DAS_ACTIVE_SOURCE", sb.toString() );\r
655 \r
656     if(localSources!=null)\r
657     {\r
658       sb = new StringBuffer();\r
659       Enumeration en = localSources.keys();\r
660       while(en.hasMoreElements())\r
661       {\r
662         String token = en.nextElement().toString();\r
663         sb.append(token+"|"\r
664                   + ((DasSource)localSources.get(token)).getUrl()\r
665                   +"\t");\r
666       }\r
667 \r
668       properties.setProperty("DAS_LOCAL_SOURCE", sb.toString());\r
669     }\r
670 \r
671   }\r
672 \r
673   class DASTableModel\r
674       extends AbstractTableModel\r
675   {\r
676 \r
677     public DASTableModel(Object[][] data)\r
678     {\r
679       this.data = data;\r
680     }\r
681 \r
682     private String[] columnNames = new String[]  {"Nickname", "Use Source"};\r
683 \r
684     private Object[][] data;\r
685 \r
686     public int getColumnCount()\r
687     {\r
688       return columnNames.length;\r
689     }\r
690 \r
691     public int getRowCount()\r
692     {\r
693       return data.length;\r
694     }\r
695 \r
696     public String getColumnName(int col)\r
697     {\r
698       return columnNames[col];\r
699     }\r
700 \r
701     public Object getValueAt(int row, int col)\r
702     {\r
703       return data[row][col];\r
704     }\r
705 \r
706     /*\r
707      * JTable uses this method to determine the default renderer/\r
708      * editor for each cell.  If we didn't implement this method,\r
709      * then the last column would contain text ("true"/"false"),\r
710      * rather than a check box.\r
711      */\r
712     public Class getColumnClass(int c)\r
713     {\r
714       return getValueAt(0, c).getClass();\r
715     }\r
716 \r
717     /*\r
718      * Don't need to implement this method unless your table's\r
719      * editable.\r
720      */\r
721     public boolean isCellEditable(int row, int col)\r
722     {\r
723       //Note that the data/cell address is constant,\r
724       //no matter where the cell appears onscreen.\r
725       return col == 1;\r
726 \r
727     }\r
728 \r
729     /*\r
730      * Don't need to implement this method unless your table's\r
731      * data can change.\r
732      */\r
733     public void setValueAt(Object value, int row, int col)\r
734     {\r
735       data[row][col] = value;\r
736       fireTableCellUpdated(row, col);\r
737 \r
738       String name = getValueAt(row,0).toString();\r
739       boolean selected = ((Boolean)value).booleanValue();\r
740 \r
741       if(selectedSources.contains(name) && !selected)\r
742         selectedSources.remove(name);\r
743 \r
744       if(!selectedSources.contains(name) && selected)\r
745         selectedSources.add(name);\r
746     }\r
747   }\r
748 }\r
749 \r
750 \r