update author list in license for (JAL-826)
[jalview.git] / src / jalview / gui / AnnotationLabels.java
index 54263aa..19e6f67 100755 (executable)
@@ -1,24 +1,24 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer
- * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
+ * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * 
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  */
 package jalview.gui;
 
 import java.util.*;
+import java.util.regex.Pattern;
 
 import java.awt.*;
 import java.awt.datatransfer.*;
@@ -31,36 +31,56 @@ import jalview.io.*;
 
 /**
  * DOCUMENT ME!
- *
+ * 
  * @author $author$
  * @version $Revision$
  */
-public class AnnotationLabels
-    extends JPanel implements MouseListener,
-    MouseMotionListener, ActionListener
+public class AnnotationLabels extends JPanel implements MouseListener,
+        MouseMotionListener, ActionListener
 {
+  static String TOGGLE_LABELSCALE = "Scale Label to Column";
+
   static String ADDNEW = "Add New Row";
+
   static String EDITNAME = "Edit Label/Description";
+
   static String HIDE = "Hide This Row";
+
   static String DELETE = "Delete This Row";
+
   static String SHOWALL = "Show All Hidden Rows";
+
   static String OUTPUT_TEXT = "Export Annotation";
+
   static String COPYCONS_SEQ = "Copy Consensus Sequence";
+
   boolean resizePanel = false;
+
   Image image;
+
   AlignmentPanel ap;
+
   AlignViewport av;
+
   boolean resizing = false;
+
   MouseEvent dragEvent;
+
   int oldY;
+
   int selectedRow;
+
   int scrollOffset = 0;
+
   Font font = new Font("Arial", Font.PLAIN, 11);
 
+  private boolean hasHiddenRows;
+
   /**
    * Creates a new AnnotationLabels object.
-   *
-   * @param ap DOCUMENT ME!
+   * 
+   * @param ap
+   *          DOCUMENT ME!
    */
   public AnnotationLabels(AlignmentPanel ap)
   {
@@ -81,14 +101,12 @@ public class AnnotationLabels
       MediaTracker mt = new MediaTracker(this);
       mt.addImage(temp, 0);
       mt.waitForID(0);
-    }
-    catch (Exception ex)
+    } catch (Exception ex)
     {
     }
 
     BufferedImage bi = new BufferedImage(temp.getHeight(this),
-                                         temp.getWidth(this),
-                                         BufferedImage.TYPE_INT_RGB);
+            temp.getWidth(this), BufferedImage.TYPE_INT_RGB);
     Graphics2D g = (Graphics2D) bi.getGraphics();
     g.rotate(Math.toRadians(90));
     g.drawImage(temp, 0, -bi.getWidth(this), this);
@@ -105,8 +123,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param y DOCUMENT ME!
+   * 
+   * @param y
+   *          DOCUMENT ME!
    */
   public void setScrollOffset(int y)
   {
@@ -114,15 +133,23 @@ public class AnnotationLabels
     repaint();
   }
 
+  /**
+   * sets selectedRow to -2 if no annotation preset, -1 if no visible row is at
+   * y
+   * 
+   * @param y
+   *          coordinate position to search for a row
+   */
   void getSelectedRow(int y)
   {
     int height = 0;
     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
-
+    selectedRow = -2;
     if (aa != null)
     {
       for (int i = 0; i < aa.length; i++)
       {
+        selectedRow = -1;
         if (!aa[i].visible)
         {
           continue;
@@ -142,19 +169,18 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void actionPerformed(ActionEvent evt)
   {
-    int dif = 0;
     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
 
     if (evt.getActionCommand().equals(ADDNEW))
     {
       AlignmentAnnotation newAnnotation = new AlignmentAnnotation(null,
-          null,
-          new Annotation[ap.av.alignment.getWidth()]);
+              null, new Annotation[ap.av.alignment.getWidth()]);
 
       if (!editLabelDescription(newAnnotation))
       {
@@ -163,10 +189,6 @@ public class AnnotationLabels
 
       ap.av.alignment.addAnnotation(newAnnotation);
       ap.av.alignment.setAnnotationIndex(newAnnotation, 0);
-      if (aa != null)
-      {
-        dif = aa[aa.length - 1].height;
-      }
     }
     else if (evt.getActionCommand().equals(EDITNAME))
     {
@@ -176,66 +198,68 @@ public class AnnotationLabels
     else if (evt.getActionCommand().equals(HIDE))
     {
       aa[selectedRow].visible = false;
-
-      if (aa[selectedRow].label.equals("Quality"))
-      {
-        ap.av.quality = null;
-      }
-
-      dif = aa[selectedRow].height * -1;
     }
     else if (evt.getActionCommand().equals(DELETE))
     {
       ap.av.alignment.deleteAnnotation(aa[selectedRow]);
-      dif = aa[selectedRow].height * -1;
     }
     else if (evt.getActionCommand().equals(SHOWALL))
     {
       for (int i = 0; i < aa.length; i++)
       {
-        if (!aa[i].visible && aa[i].annotations!=null)
+        if (!aa[i].visible && aa[i].annotations != null)
         {
-          dif += aa[i].height;
           aa[i].visible = true;
         }
       }
     }
     else if (evt.getActionCommand().equals(OUTPUT_TEXT))
     {
-      new AnnotationExporter().exportAnnotations(
-          ap,
-          new AlignmentAnnotation[]
-          {aa[selectedRow]},
-          null, null
-          );
+      new AnnotationExporter().exportAnnotations(ap,
+              new AlignmentAnnotation[]
+              { aa[selectedRow] }, null, null);
     }
     else if (evt.getActionCommand().equals(COPYCONS_SEQ))
     {
-      SequenceI cons = av.getConsensusSeq();
+      SequenceI cons = null;
+      if (aa[selectedRow].groupRef != null)
+      {
+        cons = aa[selectedRow].groupRef.getConsensusSeq();
+      }
+      else
+      {
+        cons = av.getConsensusSeq();
+      }
       if (cons != null)
       {
         copy_annotseqtoclipboard(cons);
       }
 
     }
+    else if (evt.getActionCommand().equals(TOGGLE_LABELSCALE))
+    {
+      aa[selectedRow].scaleColLabel = !aa[selectedRow].scaleColLabel;
+    }
 
-    ap.annotationPanel.adjustPanelHeight();
-    ap.annotationScroller.validate();
-    ap.paintAlignment(true);
+    ap.validateAnnotationDimensions(false);
+    ap.addNotify();
+    ap.repaint();
+    //validate();
+    //ap.paintAlignment(true);
   }
 
   /**
    * DOCUMENT ME!
-   *
-   * @param e DOCUMENT ME!
+   * 
+   * @param e
+   *          DOCUMENT ME!
    */
   boolean editLabelDescription(AlignmentAnnotation annotation)
   {
     EditNameDialog dialog = new EditNameDialog(annotation.label,
-                                               annotation.description,
-                                               "       Annotation Name ",
-                                               "Annotation Description ",
-                                               "Edit Annotation Name/Description");
+            annotation.description, "       Annotation Name ",
+            "Annotation Description ", "Edit Annotation Name/Description",
+            ap.alignFrame);
 
     if (!dialog.accept)
     {
@@ -245,7 +269,7 @@ public class AnnotationLabels
     annotation.label = dialog.getName();
 
     String text = dialog.getDescription();
-    if (text!=null && text.length() == 0)
+    if (text != null && text.length() == 0)
     {
       text = null;
     }
@@ -256,8 +280,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void mousePressed(MouseEvent evt)
   {
@@ -267,8 +292,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void mouseReleased(MouseEvent evt)
   {
@@ -278,9 +304,13 @@ public class AnnotationLabels
 
     if (start != end)
     {
-      //Swap these annotations
-      AlignmentAnnotation startAA = ap.av.alignment.getAlignmentAnnotation()[
-          start];
+      // Swap these annotations
+      AlignmentAnnotation startAA = ap.av.alignment
+              .getAlignmentAnnotation()[start];
+      if (end == -1)
+      {
+        end = ap.av.alignment.getAlignmentAnnotation().length - 1;
+      }
       AlignmentAnnotation endAA = ap.av.alignment.getAlignmentAnnotation()[end];
 
       ap.av.alignment.getAlignmentAnnotation()[end] = startAA;
@@ -295,8 +325,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void mouseEntered(MouseEvent evt)
   {
@@ -309,8 +340,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void mouseExited(MouseEvent evt)
   {
@@ -323,8 +355,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void mouseDragged(MouseEvent evt)
   {
@@ -338,13 +371,13 @@ public class AnnotationLabels
       dif /= ap.av.charHeight;
       dif *= ap.av.charHeight;
 
-      if ( (d.height - dif) > 20)
+      if ((d.height - dif) > 20)
       {
         ap.annotationScroller.setPreferredSize(new Dimension(d.width,
-            d.height - dif));
+                d.height - dif));
         d = ap.annotationSpaceFillerHolder.getPreferredSize();
         ap.annotationSpaceFillerHolder.setPreferredSize(new Dimension(
-            d.width, d.height - dif));
+                d.width, d.height - dif));
         ap.paintAlignment(true);
       }
 
@@ -358,8 +391,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void mouseMoved(MouseEvent evt)
   {
@@ -367,25 +401,47 @@ public class AnnotationLabels
 
     getSelectedRow(evt.getY() - scrollOffset);
 
-
     if (selectedRow > -1
-        && ap.av.alignment.getAlignmentAnnotation().length > selectedRow)
+            && ap.av.alignment.getAlignmentAnnotation().length > selectedRow)
     {
-      AlignmentAnnotation aa = ap.av.alignment.
-          getAlignmentAnnotation()[selectedRow];
-
-      StringBuffer desc = new StringBuffer("<html>");
-
-      if (aa.description != null && !aa.description.equals("New description"))
+      AlignmentAnnotation aa = ap.av.alignment.getAlignmentAnnotation()[selectedRow];
+      
+      StringBuffer desc = new StringBuffer();
+      if (aa.description != null
+              && !aa.description.equals("New description"))
       {
-        desc.append(aa.description+"<br>");
+        // TODO: we could refactor and merge this code with the code in jalview.gui.SeqPanel.mouseMoved(..) that formats sequence feature tooltips
+        desc.append(aa.getDescription(true).trim());
+        // check to see if the description is an html fragment.
+        if (desc.length()<6 || (desc.substring(0,6).toLowerCase().indexOf("<html>")<0))
+        {
+          // clean the description ready for embedding in html
+          desc = new StringBuffer(Pattern.compile("<").matcher(desc).replaceAll("&lt;"));        
+          desc.insert(0, "<html>");
+        } else {
+               // remove terminating html if any
+               int i=desc.substring(desc.length()-7).toLowerCase().lastIndexOf("</html>");
+               if (i>-1) {
+                 desc.setLength(desc.length()-7+i);
+               }
+        }
+        if (aa.hasScore())
+        {
+          desc.append("<br/>");
+        }
+        
+        
+      } else {
+        // begin the tooltip's html fragment
+        desc.append("<html>");
       }
-      if(aa.hasScore())
+      if (aa.hasScore())
       {
-        desc.append("Score: "+aa.score);
+        // TODO: limit precision of score to avoid noise from imprecise doubles (64.7 becomes 64.7+/some tiny value).
+        desc.append(" Score: " + aa.score);
       }
 
-      if(desc.length()!=6)
+      if (desc.length() > 6)
       {
         desc.append("</html>");
         this.setToolTipText(desc.toString());
@@ -398,26 +454,61 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param evt DOCUMENT ME!
+   * 
+   * @param evt
+   *          DOCUMENT ME!
    */
   public void mouseClicked(MouseEvent evt)
   {
-    if (!SwingUtilities.isRightMouseButton(evt))
-    {
-      return;
-    }
-
     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
-
-    if ( (aa == null) || (aa.length == 0))
+    if (SwingUtilities.isLeftMouseButton(evt))
     {
-      JPopupMenu pop = new JPopupMenu("Annotations");
-      JMenuItem item = new JMenuItem(ADDNEW);
-      item.addActionListener(this);
-      pop.add(item);
-      pop.show(this, evt.getX(), evt.getY());
+      if (selectedRow > -1 && selectedRow < aa.length)
+      {
+        if (aa[selectedRow].groupRef != null)
+        {
+          if (evt.getClickCount() >= 2)
+          {
+            // todo: make the ap scroll to the selection - not necessary, first click highlights/scrolls, second selects
+            ap.seqPanel.ap.idPanel.highlightSearchResults(null);
+            ap.av.setSelectionGroup(// new SequenceGroup(
+            aa[selectedRow].groupRef); // );
+            ap.paintAlignment(false);
+            PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
+            ap.av.sendSelection();
+          }
+          else
+          {
+            ap.seqPanel.ap.idPanel
+                    .highlightSearchResults(aa[selectedRow].groupRef
+                            .getSequences(null));
+          }
+          return;
+        }
+        else if (aa[selectedRow].sequenceRef != null)
+        {
+          Vector sr = new Vector();
+          sr.addElement(aa[selectedRow].sequenceRef);
+          if (evt.getClickCount() == 1)
+          {
+            ap.seqPanel.ap.idPanel.highlightSearchResults(sr);
+          }
+          else if (evt.getClickCount() >= 2)
+          {
+            ap.seqPanel.ap.idPanel.highlightSearchResults(null);
+            SequenceGroup sg = new SequenceGroup();
+            sg.addSequence(aa[selectedRow].sequenceRef, false);
+            ap.av.setSelectionGroup(sg);
+            ap.av.sendSelection();
+            ap.paintAlignment(false);
+            PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
+          }
 
+        }
+      }
+    }
+    if (!SwingUtilities.isRightMouseButton(evt))
+    {
       return;
     }
 
@@ -425,6 +516,17 @@ public class AnnotationLabels
     JMenuItem item = new JMenuItem(ADDNEW);
     item.addActionListener(this);
     pop.add(item);
+    if (selectedRow < 0)
+    {
+      if (hasHiddenRows)
+      { // let the user make everything visible again
+        item = new JMenuItem(SHOWALL);
+        item.addActionListener(this);
+        pop.add(item);
+      }
+      pop.show(this, evt.getX(), evt.getY());
+      return;
+    }
     item = new JMenuItem(EDITNAME);
     item.addActionListener(this);
     pop.add(item);
@@ -434,56 +536,166 @@ public class AnnotationLabels
     item = new JMenuItem(DELETE);
     item.addActionListener(this);
     pop.add(item);
-    item = new JMenuItem(SHOWALL);
-    item.addActionListener(this);
-    pop.add(item);
+    if (hasHiddenRows)
+    {
+      item = new JMenuItem(SHOWALL);
+      item.addActionListener(this);
+      pop.add(item);
+    }
     item = new JMenuItem(OUTPUT_TEXT);
     item.addActionListener(this);
     pop.add(item);
-    // annotation object should be typed
-    if (aa[selectedRow] == ap.av.consensus)
-    {
-      pop.addSeparator();
-      final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
-          "Ignore Gaps In Consensus",
-          ap.av.getIgnoreGapsConsensus());
-      cbmi.addActionListener(new ActionListener()
+    // TODO: annotation object should be typed for autocalculated/derived
+    // property methods
+    if (selectedRow < aa.length)
+    {
+      if (!aa[selectedRow].autoCalculated)
       {
-        public void actionPerformed(ActionEvent e)
+        if (aa[selectedRow].graph == AlignmentAnnotation.NO_GRAPH)
         {
-          ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
+          // display formatting settings for this row.
+          pop.addSeparator();
+          // av and sequencegroup need to implement same interface for
+          item = new JCheckBoxMenuItem(TOGGLE_LABELSCALE,
+                  aa[selectedRow].scaleColLabel);
+          item.addActionListener(this);
+          pop.add(item);
         }
-      });
-      pop.add(cbmi);
-      final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ);
-      consclipbrd.addActionListener(this);
-      pop.add(consclipbrd);
+      }
+      else if (aa[selectedRow].label.indexOf("Consensus") > -1)
+      {
+        pop.addSeparator();
+        // av and sequencegroup need to implement same interface for
+        final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
+                "Ignore Gaps In Consensus",
+                (aa[selectedRow].groupRef != null) ? aa[selectedRow].groupRef
+                        .getIgnoreGapsConsensus() : ap.av
+                        .getIgnoreGapsConsensus());
+        final AlignmentAnnotation aaa = aa[selectedRow];
+        cbmi.addActionListener(new ActionListener()
+        {
+          public void actionPerformed(ActionEvent e)
+          {
+            if (aaa.groupRef != null)
+            {
+              // TODO: pass on reference to ap so the view can be updated.
+              aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState());
+              ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
+            }
+            else
+            {
+              ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
+            }
+          }
+        });
+        pop.add(cbmi);
+        // av and sequencegroup need to implement same interface for
+        if (aaa.groupRef != null)
+        {
+          final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+                  "Show Group Histogram",
+                  aa[selectedRow].groupRef.isShowConsensusHistogram());
+          chist.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              // TODO: pass on reference
+              // to ap
+              // so the
+              // view
+              // can be
+              // updated.
+              aaa.groupRef.setShowConsensusHistogram(chist.getState());
+              ap.repaint();
+              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
+            }
+          });
+          pop.add(chist);
+          final JCheckBoxMenuItem cprofl = new JCheckBoxMenuItem(
+                  "Show Group Logo",
+                  aa[selectedRow].groupRef.isShowSequenceLogo());
+          cprofl.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              // TODO: pass on reference
+              // to ap
+              // so the
+              // view
+              // can be
+              // updated.
+              aaa.groupRef.setshowSequenceLogo(cprofl.getState());
+              ap.repaint();
+              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
+            }
+          });
+          pop.add(cprofl);
+        }
+        else
+        {
+          final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+                  "Show Histogram", av.isShowConsensusHistogram());
+          chist.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              // TODO: pass on reference
+              // to ap
+              // so the
+              // view
+              // can be
+              // updated.
+              av.setShowConsensusHistogram(chist.getState());
+              ap.repaint();
+              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
+            }
+          });
+          pop.add(chist);
+          final JCheckBoxMenuItem cprof = new JCheckBoxMenuItem(
+                  "Show Logo", av.isShowSequenceLogo());
+          cprof.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              // TODO: pass on reference
+              // to ap
+              // so the
+              // view
+              // can be
+              // updated.
+              av.setShowSequenceLogo(cprof.getState());
+              ap.repaint();
+              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
+            }
+          });
+          pop.add(cprof);
+        }
+        final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ);
+        consclipbrd.addActionListener(this);
+        pop.add(consclipbrd);
+      }
     }
-
     pop.show(this, evt.getX(), evt.getY());
   }
 
   /**
    * do a single sequence copy to jalview and the system clipboard
-   *
-   * @param sq sequence to be copied to clipboard
+   * 
+   * @param sq
+   *          sequence to be copied to clipboard
    */
   protected void copy_annotseqtoclipboard(SequenceI sq)
   {
     SequenceI[] seqs = new SequenceI[]
-        {
-        sq};
+    { sq };
     String[] omitHidden = null;
     SequenceI[] dseqs = new SequenceI[]
-        {
-        sq.getDatasetSequence()};
+    { sq.getDatasetSequence() };
     if (dseqs[0] == null)
     {
       dseqs[0] = new Sequence(sq);
-      dseqs[0].setSequence(
-          jalview.analysis.AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars,
-              sq.getSequenceAsString()));
+      dseqs[0].setSequence(jalview.analysis.AlignSeq.extractGaps(
+              jalview.util.Comparison.GapChars, sq.getSequenceAsString()));
 
       sq.setDatasetSequence(dseqs[0]);
     }
@@ -491,16 +703,14 @@ public class AnnotationLabels
     if (av.hasHiddenColumns)
     {
       omitHidden = av.getColumnSelection().getVisibleSequenceStrings(0,
-          sq.getLength(), seqs);
+              sq.getLength(), seqs);
     }
 
-    String output = new FormatAdapter().formatSequences(
-        "Fasta",
-        seqs,
-        omitHidden);
+    String output = new FormatAdapter().formatSequences("Fasta", seqs,
+            omitHidden);
 
     Toolkit.getDefaultToolkit().getSystemClipboard()
-        .setContents(new StringSelection(output), Desktop.instance);
+            .setContents(new StringSelection(output), Desktop.instance);
 
     Vector hiddenColumns = null;
     if (av.hasHiddenColumns)
@@ -508,26 +718,25 @@ public class AnnotationLabels
       hiddenColumns = new Vector();
       for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)
       {
-        int[] region = (int[])
-            av.getColumnSelection().getHiddenColumns().elementAt(i);
+        int[] region = (int[]) av.getColumnSelection().getHiddenColumns()
+                .elementAt(i);
 
         hiddenColumns.addElement(new int[]
-                                 {region[0],
-                                 region[1]});
+        { region[0], region[1] });
       }
     }
 
     Desktop.jalviewClipboard = new Object[]
-        {
-        seqs,
-        ds, // what is the dataset of a consensus sequence ? need to flag sequence as special.
-        hiddenColumns};
+    { seqs, ds, // what is the dataset of a consensus sequence ? need to flag
+        // sequence as special.
+        hiddenColumns };
   }
 
   /**
    * DOCUMENT ME!
-   *
-   * @param g1 DOCUMENT ME!
+   * 
+   * @param g1
+   *          DOCUMENT ME!
    */
   public void paintComponent(Graphics g)
   {
@@ -542,7 +751,7 @@ public class AnnotationLabels
     if (av.antiAlias)
     {
       g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-                          RenderingHints.VALUE_ANTIALIAS_ON);
+              RenderingHints.VALUE_ANTIALIAS_ON);
     }
 
     drawComponent(g2, width);
@@ -551,8 +760,9 @@ public class AnnotationLabels
 
   /**
    * DOCUMENT ME!
-   *
-   * @param g DOCUMENT ME!
+   * 
+   * @param g
+   *          DOCUMENT ME!
    */
   public void drawComponent(Graphics g, int width)
   {
@@ -577,27 +787,28 @@ public class AnnotationLabels
     int y = 0;
     int x = 0;
     int graphExtras = 0;
-    int offset =0;
+    int offset = 0;
 
     if (aa != null)
     {
+      hasHiddenRows = false;
       for (int i = 0; i < aa.length; i++)
       {
         g.setColor(Color.black);
 
         if (!aa[i].visible)
         {
+          hasHiddenRows = true;
           continue;
         }
 
-
         y += aa[i].height;
 
-        offset = -aa[i].height/2;
+        offset = -aa[i].height / 2;
 
-        if(aa[i].hasText)
+        if (aa[i].hasText)
         {
-          offset += fm.getHeight()/2;
+          offset += fm.getHeight() / 2;
           offset -= fm.getDescent();
         }
         else
@@ -626,15 +837,14 @@ public class AnnotationLabels
             if (aa[gg].graphGroup == aa[i].graphGroup)
             {
               x = width - fm.stringWidth(aa[gg].label) - 3;
-              g.drawString(aa[gg].label, x,y - graphExtras);
+              g.drawString(aa[gg].label, x, y - graphExtras);
               if (aa[gg].annotations[0] != null)
               {
                 g.setColor(aa[gg].annotations[0].colour);
               }
 
               g.drawLine(x, y - graphExtras - 3,
-                         x + fm.stringWidth(aa[gg].label),
-                         y - graphExtras - 3);
+                      x + fm.stringWidth(aa[gg].label), y - graphExtras - 3);
 
               g.setColor(Color.black);
               graphExtras += fontHeight + 8;
@@ -643,13 +853,7 @@ public class AnnotationLabels
         }
         else
         {
-          if(aa[i].belowAlignment)
-            g.setColor(Color.ORANGE);
-          else
-            g.setColor(Color.red);
-
-          g.drawString(aa[i].label, x, y +offset);
-
+          g.drawString(aa[i].label, x, y + offset);
         }
       }
     }
@@ -662,10 +866,10 @@ public class AnnotationLabels
     {
       g.setColor(Color.lightGray);
       g.drawString(aa[selectedRow].label, dragEvent.getX(),
-                   dragEvent.getY() - scrollOffset);
+              dragEvent.getY() - scrollOffset);
     }
 
-    if ( (aa == null) || (aa.length < 1))
+    if ((aa == null) || (aa.length < 1))
     {
       g.drawString("Right click", 2, 8);
       g.drawString("to add annotation", 2, 18);