added feature gradient colours and sortby feature score/density to feature settings...
[jalview.git] / src / jalview / gui / FeatureSettings.java
index 632ad00..f5580b9 100755 (executable)
@@ -30,8 +30,11 @@ import javax.swing.*;
 import javax.swing.event.*;
 import javax.swing.table.*;
 
+import jalview.analysis.AlignmentSorter;
+import jalview.commands.OrderCommand;
 import jalview.datamodel.*;
 import jalview.io.*;
+import jalview.schemes.GraduatedColor;
 
 public class FeatureSettings extends JPanel
 {
@@ -90,6 +93,11 @@ public class FeatureSettings extends JPanel
       public void mousePressed(MouseEvent evt)
       {
         selectedRow = table.rowAtPoint(evt.getPoint());
+        if (javax.swing.SwingUtilities.isRightMouseButton(evt))
+        {
+          popupSort((String) table.getValueAt(selectedRow, 0), fr.minmax,
+                  evt.getX(), evt.getY());
+        }
       }
     });
 
@@ -140,7 +148,7 @@ public class FeatureSettings extends JPanel
         {
           fs.handlingUpdate = true;
           fs.resetTable(null); // new groups may be added with new seuqence
-                                // feature types only
+          // feature types only
           fs.handlingUpdate = false;
         }
       }
@@ -162,6 +170,78 @@ public class FeatureSettings extends JPanel
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
   }
 
+  protected void popupSort(final String type, final Hashtable minmax,
+          int x, int y)
+  {
+    JPopupMenu men = new JPopupMenu("Settings for " + type);
+    JMenuItem scr = new JMenuItem("Sort by Score");
+    men.add(scr);
+    final FeatureSettings me = this;
+    scr.addActionListener(new ActionListener()
+    {
+
+      public void actionPerformed(ActionEvent e)
+      {
+        me.sortByScore(new String[]
+        { type });
+      }
+
+    });
+    JMenuItem dens = new JMenuItem("Sort by Density");
+    dens.addActionListener(new ActionListener()
+    {
+
+      public void actionPerformed(ActionEvent e)
+      {
+        me.sortByDens(new String[]
+        { type });
+      }
+
+    });
+    men.add(dens);
+    if (minmax != null)
+    {
+      final Object typeMinMax = minmax.get(type);
+      final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height");
+      // this is broken at the moment
+      chb.setSelected(minmax.get(type) != null);
+      chb.addActionListener(new ActionListener()
+      {
+
+        public void actionPerformed(ActionEvent e)
+        {
+          chb.setState(chb.getState());
+          if (chb.getState())
+          {
+            minmax.put(type, null);
+          }
+          else
+          {
+            minmax.put(type, typeMinMax);
+          }
+        }
+
+      });
+      men.add(chb);
+      if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
+      {
+        // graduated colourschemes for those where minmax exists for the positional features
+        JMenuItem mxcol = new JMenuItem("Min Max Colour");
+        men.add(mxcol);
+        mxcol.addActionListener(new ActionListener()
+        {
+
+          public void actionPerformed(ActionEvent e)
+          {
+            new FeatureColourChooser(me, type);
+          }
+
+        });
+      }
+    }
+    men.show(table, x, y);
+  }
+
   /**
    * true when Feature Settings are updating from feature renderer
    */
@@ -375,8 +455,8 @@ public class FeatureSettings extends JPanel
     {
       if (!handlingUpdate)
         fr.findAllFeatures(groupChanged != null); // prod to update
-                                                  // colourschemes. but don't
-                                                  // affect display
+      // colourschemes. but don't
+      // affect display
       // First add the checks in the previous render order,
       // in case the window has been closed and reopened
       for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
@@ -583,8 +663,8 @@ public class FeatureSettings extends JPanel
       if (awidth[0] > 0)
       {
         width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
-                                          // weight - but have to make per
-                                          // sequence, too (awidth[2])
+        // weight - but have to make per
+        // sequence, too (awidth[2])
         // if (width[i]==1) // hack to distinguish single width sequences.
         num++;
       }
@@ -681,6 +761,10 @@ public class FeatureSettings extends JPanel
 
   JButton optimizeOrder = new JButton();
 
+  JButton sortByScore = new JButton();
+
+  JButton sortByDens = new JButton();
+
   JPanel transbuttons = new JPanel(new BorderLayout());
 
   private void jbInit() throws Exception
@@ -707,6 +791,24 @@ public class FeatureSettings extends JPanel
         orderByAvWidth();
       }
     });
+    sortByScore.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    sortByScore.setText("Seq sort by Score");
+    sortByScore.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        sortByScore(null);
+      }
+    });
+    sortByDens.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    sortByDens.setText("Seq Sort by density");
+    sortByDens.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        sortByDens(null);
+      }
+    });
     cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
     cancel.setText("Cancel");
     cancel.addActionListener(new ActionListener()
@@ -793,6 +895,8 @@ public class FeatureSettings extends JPanel
     buttonPanel.add(cancel);
     buttonPanel.add(loadColours);
     buttonPanel.add(saveColours);
+    buttonPanel.add(sortByScore);
+    buttonPanel.add(sortByDens);
     bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
     dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
     dasButtonPanel.add(fetchDAS);
@@ -802,6 +906,118 @@ public class FeatureSettings extends JPanel
     settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
   }
 
+  protected void sortByDens(String[] typ)
+  {
+    sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
+  }
+
+  protected void sortBy(String[] typ, String methodText, final String method)
+  {
+    if (typ == null)
+    {
+      typ = getDisplayedFeatureTypes();
+    }
+    String gps[] = null;
+    gps = getDisplayedFeatureGroups();
+    if (typ != null)
+    {
+      for (int i = 0; i < typ.length; i++)
+      {
+        System.err.println("Sorting on Types:" + typ[i]);
+      }
+    }
+    if (gps != null)
+    {
+
+      for (int i = 0; i < gps.length; i++)
+      {
+        System.err.println("Sorting on groups:" + gps[i]);
+      }
+    }
+    AlignmentPanel alignPanel = af.alignPanel;
+    AlignmentI al = alignPanel.av.getAlignment();
+
+    int start, stop;
+    SequenceGroup sg = alignPanel.av.getSelectionGroup();
+    if (sg != null)
+    {
+      start = sg.getStartRes();
+      stop = sg.getEndRes();
+    }
+    else
+    {
+      start = 0;
+      stop = al.getWidth();
+    }
+    SequenceI[] oldOrder = al.getSequencesArray();
+    AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
+    af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
+            .getAlignment()));
+    alignPanel.paintAlignment(true);
+
+  }
+
+  protected void sortByScore(String[] typ)
+  {
+    sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
+  }
+
+  private String[] getDisplayedFeatureTypes()
+  {
+    String[] typ = null;
+    if (fr != null)
+    {
+      synchronized (fr.renderOrder)
+      {
+        typ = new String[fr.renderOrder.length];
+        System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
+        for (int i = 0; i < typ.length; i++)
+        {
+          if (af.viewport.featuresDisplayed.get(typ[i]) == null)
+          {
+            typ[i] = null;
+          }
+        }
+      }
+    }
+    return typ;
+  }
+
+  private String[] getDisplayedFeatureGroups()
+  {
+    String[] gps = null;
+    if (fr != null)
+    {
+
+      if (fr.featureGroups != null)
+      {
+        Enumeration en = fr.featureGroups.keys();
+        gps = new String[fr.featureColours.size()];
+        int g = 0;
+        boolean valid = false;
+        while (en.hasMoreElements())
+        {
+          String gp = (String) en.nextElement();
+          Boolean on = (Boolean) fr.featureGroups.get(gp);
+          if (on != null && on.booleanValue())
+          {
+            valid = true;
+            gps[g++] = gp;
+          }
+        }
+        while (g < gps.length)
+        {
+          gps[g++] = null;
+        }
+        if (!valid)
+        {
+          return null;
+        }
+      }
+    }
+    return gps;
+  }
+
   public void fetchDAS_actionPerformed(ActionEvent e)
   {
     fetchDAS.setEnabled(false);
@@ -850,6 +1066,38 @@ public class FeatureSettings extends JPanel
   }
 
   /**
+   * blocking call to initialise the das source browser
+   */
+  public void initDasSources()
+  {
+    dassourceBrowser.initDasSources();
+  }
+
+  /**
+   * examine the current list of das sources and return any matching the given
+   * nicknames in sources
+   * 
+   * @param sources
+   *                Vector of Strings to resolve to DAS source nicknames.
+   * @return sources that are present in source list.
+   */
+  public Vector resolveSourceNicknames(Vector sources)
+  {
+    return dassourceBrowser.resolveSourceNicknames(sources);
+  }
+
+  /**
+   * get currently selected das sources. ensure you have called initDasSources
+   * before calling this.
+   * 
+   * @return vector of selected das source nicknames
+   */
+  public Vector getSelectedSources()
+  {
+    return dassourceBrowser.getSelectedSources();
+  }
+
+  /**
    * properly initialise DAS fetcher and then initiate a new thread to fetch
    * features from the named sources (rather than any turned on by default)
    * 
@@ -857,40 +1105,8 @@ public class FeatureSettings extends JPanel
    */
   public void fetchDasFeatures(Vector sources)
   {
-    Thread thr = new Thread(new Runnable()
-    {
-      public void run()
-      {
-        // this actually initialises the das source list
-        dassourceBrowser.paintComponent(null); // yuk
-      }
-    });
-    thr.start();
-    while (dassourceBrowser.loadingDasSources
-            || dassourceBrowser.dasSources == null)
-    {
-      try
-      {
-        Thread.sleep(10);
-      } catch (Exception e)
-      {
-      }
-      ;
-    }
-    Vector resolved = new Vector();
-    if (sources != null)
-    {
-      for (int i = 0; i < dassourceBrowser.dasSources.length; i++)
-      {
-        if (sources.contains(dassourceBrowser.dasSources[i].getNickname()))
-        {
-          if (!resolved.contains(dassourceBrowser.dasSources[i]))
-          {
-            resolved.addElement(dassourceBrowser.dasSources[i]);
-          }
-        }
-      }
-    }
+    initDasSources();
+    Vector resolved = resolveSourceNicknames(sources);
     if (resolved.size() == 0)
     {
       resolved = dassourceBrowser.getSelectedSources();
@@ -1028,8 +1244,26 @@ public class FeatureSettings extends JPanel
             Object color, boolean isSelected, boolean hasFocus, int row,
             int column)
     {
-      Color newColor = (Color) color;
-      setBackground(newColor);
+      Color newColor;
+      color = fr.featureColours.get((String) table.getModel().getValueAt(
+              row, 0));
+      if (color instanceof GraduatedColor)
+      {
+        newColor = ((GraduatedColor) color).getMaxColor();
+        Color minCol = ((GraduatedColor) color).getMinColor();;
+        setBackground(newColor);
+        setToolTipText("RGB value: Max (" + newColor.getRed() + ", "
+                + newColor.getGreen() + ", " + newColor.getBlue()
+                + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
+                + ", " + minCol.getBlue() + ")");
+      }
+      else
+      {
+        newColor = (Color) color;
+        setBackground(newColor);
+        setToolTipText("RGB value: " + newColor.getRed() + ", "
+                + newColor.getGreen() + ", " + newColor.getBlue());
+      }
       if (isSelected)
       {
         if (selectedBorder == null)
@@ -1049,8 +1283,6 @@ public class FeatureSettings extends JPanel
         setBorder(unselectedBorder);
       }
 
-      setToolTipText("RGB value: " + newColor.getRed() + ", "
-              + newColor.getGreen() + ", " + newColor.getBlue());
       return this;
     }
   }