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