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