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