JAL-1075 better layout and info box for source browser
[jalview.git] / src / jalview / gui / JDatabaseTree.java
1 package jalview.gui;
2
3 import jalview.bin.Cache;
4 import jalview.ws.seqfetcher.DbSourceProxy;
5
6 import java.awt.BorderLayout;
7 import java.awt.Component;
8 import java.awt.Container;
9 import java.awt.Dimension;
10 import java.awt.FlowLayout;
11 import java.awt.event.ActionEvent;
12 import java.awt.event.ActionListener;
13 import java.util.ArrayList;
14 import java.util.Hashtable;
15 import java.util.List;
16 import java.util.Vector;
17
18 import javax.swing.JButton;
19 import javax.swing.JFrame;
20 import javax.swing.JLabel;
21 import javax.swing.JPanel;
22 import javax.swing.JScrollPane;
23 import javax.swing.JTree;
24 import javax.swing.JViewport;
25 import javax.swing.event.TreeSelectionEvent;
26 import javax.swing.event.TreeSelectionListener;
27 import javax.swing.tree.DefaultMutableTreeNode;
28 import javax.swing.tree.DefaultTreeCellRenderer;
29 import javax.swing.tree.DefaultTreeModel;
30 import javax.swing.tree.MutableTreeNode;
31 import javax.swing.tree.TreeCellRenderer;
32 import javax.swing.tree.TreeModel;
33 import javax.swing.tree.TreePath;
34 import javax.swing.tree.TreeSelectionModel;
35
36 import com.sun.java.help.search.DBPartParameters;
37
38 public class JDatabaseTree extends JalviewDialog
39 {
40   JButton getDatabaseSelectorButton()
41   {
42     final JButton viewdbs = new JButton("--- Select Database ---");
43     viewdbs.addActionListener(new ActionListener()
44     {
45
46       @Override
47       public void actionPerformed(ActionEvent arg0)
48       {
49         showDialog(null);
50       }
51     });
52     return viewdbs;
53   }
54
55   JScrollPane svp;
56
57   JTree dbviews;
58
59   private jalview.ws.SequenceFetcher sfetcher;
60
61   private JLabel dbstatus;
62
63   public JDatabaseTree(jalview.ws.SequenceFetcher sfetch)
64   {
65     initDialogFrame(this, true, false, "Select Database Retrieval Source",
66             650, 490);
67     /*
68      * Dynamically generated database list will need a translation function from
69      * internal source to externally distinct names. UNIPROT and UP_NAME are
70      * identical DB sources, and should be collapsed.
71      */
72     DefaultMutableTreeNode tn = null, root = new DefaultMutableTreeNode();
73     Hashtable<DbSourceProxy, DefaultMutableTreeNode> tns = new Hashtable<DbSourceProxy, DefaultMutableTreeNode>();
74     Hashtable<String, DefaultMutableTreeNode> source = new Hashtable<String, DefaultMutableTreeNode>();
75     sfetcher = sfetch;
76     String dbs[] = sfetch.getSupportedDb();
77     Hashtable ht = new Hashtable();
78     for (int i = 0; i < dbs.length; i++)
79     {
80       tn = source.get(dbs[i]);
81       List<DbSourceProxy> srcs = sfetch.getSourceProxy(dbs[i]);
82       if (tn == null)
83       {
84         source.put(dbs[i], tn = new DefaultMutableTreeNode(dbs[i], true));
85       }
86       for (DbSourceProxy dbp : srcs)
87       {
88         if (ht.get(dbp.getDbName()) == null)
89         {
90           tn.add(new DefaultMutableTreeNode(dbp, false));
91           ht.put(dbp.getDbName(), dbp.getDbName());
92         }
93         else
94         {
95           System.err.println("dupe ig for : " + dbs[i] + " \t"
96                   + dbp.getDbName());
97         }
98       }
99     }
100     for (int i = 0; i < dbs.length; i++)
101     {
102       tn = source.get(dbs[i]);
103       if (tn == null)
104       {
105         continue;
106       }
107       if (tn.getChildCount() == 1)
108       {
109         // remove nodes with only one child
110         source.put(dbs[i], tn = (DefaultMutableTreeNode) tn.getChildAt(0));
111       }
112       root.add(tn);
113     }
114     svp = new JScrollPane();
115     // svp.setAutoscrolls(true);
116     dbviews = new JTree(new DefaultTreeModel(root, false));
117     dbviews.setCellRenderer(new DbTreeRenderer(this));
118
119     dbviews.getSelectionModel().setSelectionMode(
120             TreeSelectionModel.SINGLE_TREE_SELECTION);
121     svp.getViewport().setView(dbviews);
122     // svp.getViewport().setMinimumSize(new Dimension(300,200));
123     // svp.setSize(300,250);
124     // JPanel panel=new JPanel();
125     // panel.setSize(new Dimension(350,220));
126     // panel.add(svp);
127     dbviews.addTreeSelectionListener(new TreeSelectionListener()
128     {
129
130       @Override
131       public void valueChanged(TreeSelectionEvent arg0)
132       {
133         _setSelectionState();
134       }
135     });
136     JPanel jc = new JPanel(new BorderLayout()), j = new JPanel(
137             new FlowLayout());
138     jc.add(svp, BorderLayout.CENTER);
139
140     java.awt.Font f;
141     // TODO: make the panel resize and fit this in
142     dbstatus = new JLabel(" "); // set the height correctly for layout
143     dbstatus.setFont(f = JvSwingUtils.getLabelFont(false, true));
144     dbstatus.setSize(new Dimension(290, 50));
145     jc.add(dbstatus, BorderLayout.SOUTH);
146     jc.validate();
147     // j.setPreferredSize(new Dimension(300,50));
148     add(jc, BorderLayout.CENTER);
149     j.add(ok);
150     j.add(cancel);
151     add(j, BorderLayout.SOUTH);
152     validate();
153   }
154
155   private class DbTreeRenderer extends DefaultTreeCellRenderer implements
156           TreeCellRenderer
157   {
158     JDatabaseTree us;
159
160     public DbTreeRenderer(JDatabaseTree me)
161     {
162       us = me;
163     }
164
165     private Component returnLabel(String txt)
166     {
167       JLabel jl = new JLabel(txt);
168       jl.setFont(JvSwingUtils.getLabelFont());
169       return jl;
170     }
171
172     @Override
173     public Component getTreeCellRendererComponent(JTree tree, Object value,
174             boolean selected, boolean expanded, boolean leaf, int row,
175             boolean hasFocus)
176     {
177       String val = "";
178       if (value != null && value instanceof DefaultMutableTreeNode)
179       {
180         DefaultMutableTreeNode vl = (DefaultMutableTreeNode) value;
181         value = vl.getUserObject();
182         if (value instanceof DbSourceProxy)
183         {
184           val = (((DbSourceProxy) value).getDbName());
185         }
186         else
187         {
188           if (value instanceof String)
189           {
190             val = ((String) value);
191           }
192         }
193       }
194       if (value == null)
195       {
196         val = ("");
197       }
198       return super.getTreeCellRendererComponent(tree, val, selected,
199               expanded, leaf, row, hasFocus);
200
201     }
202   }
203
204   List<DbSourceProxy> selection = null;
205
206   @Override
207   protected void raiseClosed()
208   {
209     for (ActionListener al : lstners)
210     {
211       al.actionPerformed(null);
212     }
213   }
214
215   @Override
216   protected void okPressed()
217   {
218     _setSelectionState();
219     closeDialog();
220   }
221
222   @Override
223   protected void cancelPressed()
224   {
225     closeDialog();
226   }
227
228   private void showDialog(Container parent)
229   {
230     validate();
231     waitForInput();
232   }
233
234   public boolean hasSelection()
235   {
236     return selection == null ? false : selection.size() == 0 ? false : true;
237   }
238
239   public List<DbSourceProxy> getSelectedSources()
240   {
241     return selection;
242   }
243
244   private void _setSelectionState()
245   {
246     if (dbviews.getSelectionCount() == 0)
247     {
248       selection = null;
249     }
250     List<DbSourceProxy> srcs = new ArrayList<DbSourceProxy>();
251     for (TreePath tp : dbviews.getSelectionPaths())
252     {
253       DefaultMutableTreeNode dmt = (DefaultMutableTreeNode) tp
254               .getLastPathComponent();
255       if (dmt.getUserObject() != null)
256       {
257         if (dmt.getUserObject() instanceof DbSourceProxy)
258         {
259           srcs.add((DbSourceProxy) dmt.getUserObject());
260         }
261         else
262         {
263           srcs.addAll(sfetcher.getSourceProxy((String) dmt.getUserObject()));
264         }
265       }
266     }
267     updateDbStatus(srcs);
268     selection = srcs;
269   }
270
271   private void updateDbStatus(List<DbSourceProxy> srcs)
272   {
273     int x = 0;
274     for (DbSourceProxy dbs : srcs)
275     {
276       String tq = dbs.getTestQuery();
277       if (tq != null && tq.trim().length()>0 && dbs.isValidReference(tq))
278       {
279         x++;
280       }
281     }
282
283     dbstatus.setText("Selected "
284             + srcs.size()
285             + " database"
286             + (srcs.size() == 1 ? "" : "s")
287             + " to fetch from"
288             + (srcs.size() > 0 ? " with " + x + " test quer"
289                     + (x == 1 ? "y" : "ies")  : "."));
290     dbstatus.invalidate();
291   }
292
293   public String getSelectedItem()
294   {
295     if (hasSelection())
296     {
297       return getSelectedSources().get(0).getDbName();
298     }
299     return null;
300   }
301
302   public String getExampleQueries()
303   {
304     if (!hasSelection())
305     {
306       return null;
307     }
308     StringBuffer sb = new StringBuffer();
309     for (DbSourceProxy dbs : getSelectedSources())
310     {
311       if (sb.length() > 0)
312       {
313         sb.append(";");
314       }
315       sb.append(dbs.getTestQuery());
316     }
317     return sb.toString();
318   }
319
320   List<ActionListener> lstners = new Vector<ActionListener>();
321
322   public void addActionListener(ActionListener actionListener)
323   {
324     lstners.add(actionListener);
325   }
326
327   public void removeActionListener(ActionListener actionListener)
328   {
329     lstners.remove(actionListener);
330   }
331
332   public static void main(String args[])
333   {
334     Cache.getDasSourceRegistry();
335     JDatabaseTree jdt = new JDatabaseTree(new jalview.ws.SequenceFetcher());
336     JFrame foo = new JFrame();
337     foo.setLayout(new BorderLayout());
338     foo.add(jdt.getDatabaseSelectorButton(), BorderLayout.CENTER);
339     foo.pack();
340     foo.setVisible(true);
341     int nultimes = 5;
342     final Thread us = Thread.currentThread();
343     jdt.addActionListener(new ActionListener()
344     {
345
346       @Override
347       public void actionPerformed(ActionEvent e)
348       {
349         us.interrupt();
350       }
351     });
352     do
353     {
354       try
355       {
356         Thread.sleep(50);
357       } catch (InterruptedException x)
358       {
359         nultimes--;
360         if (!jdt.hasSelection())
361         {
362           System.out.println("No Selection");
363         }
364         else
365         {
366           System.out.println("Selection: " + jdt.getSelectedItem());
367           int s = 1;
368           for (DbSourceProxy pr : jdt.getSelectedSources())
369           {
370             System.out.println("Source " + s++ + ": " + pr.getDbName()
371                     + " (" + pr.getDbSource() + ") Version "
372                     + pr.getDbVersion() + ". Test:\t" + pr.getTestQuery());
373           }
374           System.out.println("Test queries: " + jdt.getExampleQueries());
375         }
376       }
377     } while (nultimes > 0 && foo.isVisible());
378     foo.setVisible(false);
379   }
380 }