src/org/gel/mauve/gui/navigation/SearchResultPanel.java

Go to the documentation of this file.
00001 package org.gel.mauve.gui.navigation;
00002 
00003 import java.awt.Color;
00004 import java.awt.Component;
00005 import java.awt.FlowLayout;
00006 import java.awt.Graphics;
00007 import java.util.Collections;
00008 import java.util.Comparator;
00009 import java.util.Enumeration;
00010 import java.util.Hashtable;
00011 import java.util.LinkedList;
00012 import java.util.StringTokenizer;
00013 import java.util.Vector;
00014 
00015 import javax.swing.Icon;
00016 import javax.swing.JLabel;
00017 import javax.swing.JPanel;
00018 import javax.swing.JScrollBar;
00019 import javax.swing.JScrollPane;
00020 import javax.swing.JTree;
00021 import javax.swing.SwingUtilities;
00022 import javax.swing.UIManager;
00023 import javax.swing.event.TreeModelListener;
00024 import javax.swing.event.TreeSelectionEvent;
00025 import javax.swing.event.TreeSelectionListener;
00026 import javax.swing.plaf.ColorUIResource;
00027 import javax.swing.tree.DefaultMutableTreeNode;
00028 import javax.swing.tree.DefaultTreeCellRenderer;
00029 import javax.swing.tree.DefaultTreeModel;
00030 import javax.swing.tree.TreeCellRenderer;
00031 import javax.swing.tree.TreeModel;
00032 import javax.swing.tree.TreePath;
00033 import javax.swing.tree.TreeSelectionModel;
00034 
00035 import org.biojava.bio.Annotation;
00036 import org.biojava.bio.seq.Feature;
00037 import org.biojava.bio.symbol.Location;
00038 import org.gel.mauve.Genome;
00039 import org.gel.mauve.MauveConstants;
00040 import org.gel.mauve.SeqFeatureData;
00041 import org.gel.mauve.gui.SequenceNavigator;
00042 
00051 public class SearchResultPanel extends JPanel implements TreeModel,
00052                 TreeCellRenderer, TreeSelectionListener, MauveConstants {
00053 
00057         protected JTree tree;
00058 
00062         protected DefaultTreeModel model;
00063 
00067         protected DefaultTreeCellRenderer renderer;
00068 
00072         protected SequenceNavigator navigator;
00073 
00077         protected DefaultMutableTreeNode root;
00078 
00082         protected JScrollPane scroller;
00083 
00088         protected int result_state;
00089 
00093         protected boolean searching;
00094 
00098         public static final String NO_RESULTS = "No results to display. . .";
00099 
00103         public static final String MATCHLESS = "No features found. . .";
00104         
00108         protected static final String SEARCHING = "Searching. . .";
00109 
00113         protected static final String ROOT = "Root";
00114 
00118         public static final Icon PLUS_ICON = SignedIcon.getSignedIcon (true);
00119 
00123         public static final Icon MINUS_ICON = SignedIcon.getSignedIcon (false);
00124 
00128         protected Hashtable genome_data;
00129 
00133         protected Object [] genome_indexes;
00134 
00143         public SearchResultPanel (Vector genomes, SequenceNavigator nav) {
00144                 super (new FlowLayout (FlowLayout.LEFT));
00145                 navigator = nav;
00146                 genome_data = new Hashtable ();
00147                 genome_indexes = new Object [genomes.size ()];
00148                 for (int i = 0; i < genomes.size (); i++) {
00149                         genome_data.put (genomes.get (i), new LinkedList ());
00150                         genome_indexes[i] = genomes.get (i);
00151                 }
00152                 initGUI ();
00153         }
00154 
00159         protected void initGUI () {
00160                 UIManager.put ("Tree.hash", new ColorUIResource (Color.BLACK));
00161                 tree = new JTree ();
00162                 tree.setRootVisible (false);
00163                 tree.setBackground (navigator.getBackground ());
00164                 tree.getSelectionModel ().setSelectionMode (
00165                                 TreeSelectionModel.SINGLE_TREE_SELECTION);
00166                 model = (DefaultTreeModel) tree.getModel ();
00167                 renderer = (DefaultTreeCellRenderer) tree.getCellRenderer ();
00168                 renderer.setBackgroundNonSelectionColor (navigator.getBackground ());
00169                 renderer.setClosedIcon (PLUS_ICON);
00170                 renderer.setOpenIcon (MINUS_ICON);
00171                 renderer.setLeafIcon (null);
00172                 tree.setCellRenderer (this);
00173                 tree.setModel (this);
00174                 tree.setEditable (false);
00175                 tree.addTreeSelectionListener (this);
00176                 tree.setToggleClickCount (1);
00177                 root = new DefaultMutableTreeNode (ROOT);
00178                 add (tree);
00179                 scroller = new JScrollPane (this);
00180                 scroller.getVerticalScrollBar ().setUnitIncrement (
00181                                 renderer.getPreferredSize ().height);
00182         }
00183 
00189         public JScrollPane getScrollPane () {
00190                 return scroller;
00191         }
00192 
00200         public void displayFeatures (Object [] data) {
00201                 resetData (data);
00202                 int prev_result = result_state;
00203                 Object [] first = new Object [3];
00204                 for (int i = 0; i < genome_indexes.length; i++) {
00205                         LinkedList list = (LinkedList) genome_data.get (genome_indexes[i]);
00206                         if (result_state == 0 && list.size () > 0) {
00207                                 first[2] = (Feature) list.get (0);
00208                                 first[1] = genome_indexes[i];
00209                                 first[0] = ROOT;
00210                         }
00211                         result_state += list.size ();
00212                         if (result_state > 1)
00213                                 break;
00214                 }
00215                 searching = false;
00216                 model.nodeStructureChanged (root);
00217                 Object [] path = new Object [(result_state == 0) ? 1 : 2];
00218                 path[0] = ROOT;
00219                 if (result_state > 0) {
00220                         for (int i = 0; i < getChildCount (ROOT); i++) {
00221                                 Object kid = getChild (ROOT, i);
00222                                 path[1] = kid;
00223                                 tree.expandPath (new TreePath (path));
00224                         }
00225                         if (prev_result == 0)
00226                                 tree.setSelectionPath (new TreePath (first));
00227                 } else {
00228                         tree.expandPath (new TreePath (path));
00229                         try {
00230                                 Thread.currentThread ().wait (100);
00231                         } catch (Exception e) {
00232                                 // ok probably. . .
00233                         }
00234                 }
00235                 navigator.reloadGUI ();
00236         }
00237 
00242         public void waitForResults () {
00243                 searching = true;
00244                                 SwingUtilities.invokeLater(new Runnable(){
00245                         public void run(){
00246                                 model.nodeStructureChanged (root);
00247                         }
00248                 });
00249         }
00250 
00259         protected void resetData (Object [] data) {
00260                 Enumeration keys = null;
00261                 if (result_state != 0 && navigator.shouldClear ()) {
00262                         keys = genome_data.keys ();
00263                         while (keys.hasMoreElements ()) {
00264                                 LinkedList remove = (LinkedList) genome_data.get (keys
00265                                                 .nextElement ());
00266                                 remove.clear ();
00267                         }
00268                         result_state = 0;
00269                 }
00270                 for (int i = 0; i < data.length; i++) {
00271                         LinkedList new_data = (LinkedList) data[i];
00272                         Object key = new_data.remove (0);
00273                         LinkedList old = (LinkedList) genome_data.get (key);
00274                         old.addAll (new_data);
00275                         SeqFeatureData.removeLocationDuplicates (old);
00276                 }
00277         }
00278 
00286         public static String getDisplayText (Feature feat) {
00287                 String data = "";
00288                 Annotation note = feat.getAnnotation ();
00289                 StringTokenizer fields = SeqFeatureData.separateFields (LOC_NAME);
00290                 while (fields.hasMoreTokens () && data.length () == 0) {
00291                         String field = fields.nextToken ();
00292                         if (note.containsProperty (field))
00293                                 data += (String) note.getProperty (field);
00294                 }
00295                 Location loci = feat.getLocation ();
00296                 data += " (" + loci.getMin () + "-" + loci.getMax () + ")";
00297                 data.trim ();
00298                 return data;
00299         }
00300 
00305         public void valueChanged (TreeSelectionEvent event) {
00306                 if (event.getNewLeadSelectionPath () != null) {
00307                         Object [] path = event.getNewLeadSelectionPath ().getPath ();
00308                         if (path != null && path.length == 3 && path[2] != MATCHLESS)
00309                                 navigator.displayFeature ((Feature) path[2], (Genome) path[1]);
00310                 }
00311         }
00312 
00316         public Component getTreeCellRendererComponent (JTree tree, Object val,
00317                         boolean selected, boolean expanded, boolean leaf, int row,
00318                         boolean focus) {
00319                 JLabel label = (JLabel) renderer.getTreeCellRendererComponent (tree,
00320                                 val, selected, expanded, leaf, row, focus);
00321                 if (val instanceof Feature)
00322                         label.setText (getDisplayText ((Feature) val));
00323                 return label;
00324         }
00325 
00329         public void addTreeModelListener (TreeModelListener listen) {
00330                 model.addTreeModelListener (listen);
00331         }
00332 
00342         public Object getChild (Object parent, int index) {
00343                 if (parent == ROOT) {
00344                         if (searching)
00345                                 return SEARCHING;
00346                         else if (result_state == 0)
00347                                 return NO_RESULTS;
00348                         else
00349                                 return genome_indexes[index];
00350                 }
00351                 LinkedList children = (LinkedList) genome_data.get (parent);
00352                 if (children != null) {
00353                         try {
00354                                 return children.get (index);
00355                         } catch (IndexOutOfBoundsException e) {
00356                                 return MATCHLESS;
00357                         }
00358                 } else
00359                         return null;
00360 
00361         }
00362 
00370         public int getChildCount (Object parent) {
00371                 if (parent == ROOT) {
00372                         if (searching || result_state == 0)
00373                                 return 1;
00374                         else
00375                                 return genome_data.size ();
00376                 }
00377                 LinkedList children = (LinkedList) genome_data.get (parent);
00378                 if (children != null) {
00379                         int size = ((LinkedList) genome_data.get (parent)).size ();
00380                         if (size == 0)
00381                                 return 1;
00382                         else
00383                                 return size;
00384                 } else
00385                         return 0;
00386         }
00387 
00397         public int getIndexOfChild (Object parent, Object child) {
00398                 if (parent == ROOT) {
00399                         if (child == SEARCHING) {
00400                                 if (searching)
00401                                         return 0;
00402                                 else
00403                                         return -1;
00404                         }
00405                         if (child == NO_RESULTS) {
00406                                 if (result_state == 0)
00407                                         return 0;
00408                                 else
00409                                         return -1;
00410                         } else {
00411                                 for (int i = 0; i < genome_indexes.length; i++) {
00412                                         if (genome_indexes[i].equals (child))
00413                                                 return i;
00414                                 }
00415                         }
00416                 } else if (child == MATCHLESS)
00417                         return 0;
00418                 else if (genome_data.contains (parent)) {
00419                         LinkedList kids = (LinkedList) genome_data.get (parent);
00420                         return kids.indexOf (child);
00421                 }
00422                 return -1;
00423         }
00424 
00430         public Object getRoot () {
00431                 return ROOT;
00432         }
00433 
00441         public boolean isLeaf (Object node) {
00442                 if (node != ROOT && !genome_data.containsKey (node))
00443                         return true;
00444                 else
00445                         return false;
00446         }
00447 
00451         public void removeTreeModelListener (TreeModelListener list) {
00452                 model.removeTreeModelListener (list);
00453         }
00454 
00458         public void valueForPathChanged (TreePath path, Object val) {
00459                 model.valueForPathChanged (path, val);
00460         }
00461 
00469         public static class SignedIcon implements Icon {
00470 
00474                 private boolean plus;
00475 
00479                 private static SignedIcon PLUS = new SignedIcon (true);
00480 
00481                 private static SignedIcon MINUS = new SignedIcon (false);
00482 
00489                 private SignedIcon (boolean p) {
00490                         plus = p;
00491                 }
00492 
00501                 public static SignedIcon getSignedIcon (boolean plus) {
00502                         return plus ? PLUS : MINUS;
00503                 }
00504 
00505                 public int getIconHeight () {
00506                         return 16;
00507                 }
00508 
00509                 public int getIconWidth () {
00510                         return 16;
00511                 }
00512 
00516                 public void paintIcon (Component comp, Graphics g, int x, int y) {
00517                         g.drawRect (3, 3, 8, 8);
00518                         g.drawLine (5, 7, 9, 7);
00519                         if (plus)
00520                                 g.drawLine (7, 5, 7, 9);
00521                 }
00522 
00523         }
00524 }

Generated on Mon Aug 19 06:03:42 2013 for Mauve by doxygen 1.3.6