adjustable annotation panel height and vertical scrollbar JAL-516,JAL-338,JAL-306
authorjprocter <Jim Procter>
Fri, 4 Feb 2011 10:44:26 +0000 (10:44 +0000)
committerjprocter <Jim Procter>
Fri, 4 Feb 2011 10:44:26 +0000 (10:44 +0000)
src/jalview/appletgui/AlignmentPanel.java
src/jalview/appletgui/AnnotationLabels.java
src/jalview/appletgui/AnnotationPanel.java

index 2d2f4bb..d8e03f7 100755 (executable)
@@ -19,6 +19,8 @@ package jalview.appletgui;
 
 import java.awt.*;
 import java.awt.event.*;
+import java.util.Hashtable;
+import java.util.Vector;
 
 import jalview.datamodel.*;
 
@@ -62,9 +64,15 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
     idPanel = new IdPanel(av, this);
     scalePanel = new ScalePanel(av, this);
     idwidthAdjuster = new IdwidthAdjuster(this);
+//    annotationScroller = new ScrollPane();
+ //   annotationScroller.setBackground(Color.white);
     annotationPanel = new AnnotationPanel(this);
-
-    sequenceHolderPanel.add(annotationPanel, BorderLayout.SOUTH);
+    annotationPanelHolder.add(annotationPanel, BorderLayout.CENTER);
+    // annotationScroller.setPreferredSize(new Dimension(10,80));
+//    annotationScroller.add(annotationPanel);
+//    annotationScroller.getInsets().set(0,0,0,0);
+    
+    sequenceHolderPanel.add(annotationPanelHolder, BorderLayout.SOUTH);
 
     alabels = new AnnotationLabels(this);
 
@@ -75,10 +83,11 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
-
+    
     fontChanged();
     setScrollValues(0, 0);
 
+    apvscroll.addAdjustmentListener(this);
     hscroll.addAdjustmentListener(this);
     vscroll.addAdjustmentListener(this);
 
@@ -100,7 +109,6 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
     annotationSpaceFillerHolder.setSize(d.width,
             annotationPanel.getSize().height);
     alabels.setSize(d.width, annotationPanel.getSize().height);
-
     final AlignmentPanel ap = this;
     av.addPropertyChangeListener(new java.beans.PropertyChangeListener()
     {
@@ -152,7 +160,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
             + fm.getDescent()));
     av.updateSequenceIdColours();
     annotationPanel.image = null;
-    int ap = annotationPanel.adjustPanelHeight();
+    int ap = annotationPanel.adjustPanelHeight(false);
     annotationPanel.repaint();
     Dimension d = calculateIdWidth();
     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);
@@ -515,6 +523,15 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
     int oldX = av.getStartRes();
     int oldY = av.getStartSeq();
 
+    if (evt == null || evt.getSource()==apvscroll)
+    {
+      annotationPanel.setScrollOffset(apvscroll.getValue());
+      alabels.setScrollOffset(apvscroll.getValue());
+      //annotationPanel.image=null;
+      //alabels.image=null;
+      //alabels.repaint();
+      //annotationPanel.repaint();
+    }
     if (evt == null || evt.getSource() == hscroll)
     {
       int x = hscroll.getValue();
@@ -604,10 +621,11 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
     invalidate();
     Dimension d = idPanel.idCanvas.getSize();
     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
+    annotationPanelHolder.setSize(seqPanel.getSize().width, annotationPanel.getSize().height);
     annotationSpaceFillerHolder.setSize(d.width,
             annotationPanel.getSize().height);
 
-    alabels.setSize(d.width, annotationPanel.getSize().height);
+    alabels.setSize(d.width, annotationPanelHolder.getSize().height);
 
     if (av.getWrapAlignment())
     {
@@ -624,7 +642,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
       if (canvasWidth > 0)
       {
         int max = maxwidth / canvasWidth;
-        vscroll.setMaximum(max);
+        vscroll.setMaximum(1+max);
         vscroll.setUnitIncrement(1);
         vscroll.setVisibleAmount(1);
       }
@@ -680,6 +698,11 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
 
   BorderLayout borderLayout2 = new BorderLayout();
 
+  Panel annotationPanelHolder = new Panel();
+  protected Scrollbar apvscroll=new Scrollbar();
+
+  BorderLayout borderLayout12 = new BorderLayout();
+
   private void jbInit() throws Exception
   {
     // idPanelHolder.setPreferredSize(new Dimension(70, 10));
@@ -704,7 +727,13 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
     hscroll.setOrientation(Scrollbar.HORIZONTAL);
     hscrollHolder.setLayout(borderLayout10);
     hscrollFillerPanel.setBackground(Color.white);
+    apvscroll.setOrientation(Scrollbar.VERTICAL);
+    apvscroll.setVisible(true);
+    apvscroll.addAdjustmentListener(this);
 
+    annotationPanelHolder.setBackground(Color.white);
+    annotationPanelHolder.setLayout(borderLayout12);
+    annotationPanelHolder.add(apvscroll, BorderLayout.EAST);
     // hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));
     hscrollHolder.setBackground(Color.white);
 
@@ -726,4 +755,119 @@ public class AlignmentPanel extends Panel implements AdjustmentListener
     this.add(sequenceHolderPanel, BorderLayout.CENTER);
   }
 
+  /**
+   * hides or shows dynamic annotation rows based on groups and av state flags
+   */
+  public void updateAnnotation()
+  {
+    updateAnnotation(false);
+  }
+
+  public void updateAnnotation(boolean applyGlobalSettings)
+  {
+    // TODO: this should be merged with other annotation update stuff - that
+    // sits on AlignViewport
+    boolean updateCalcs = false;
+    boolean conv = av.isShowGroupConservation();
+    boolean cons = av.isShowGroupConsensus();
+    boolean showprf = av.isShowSequenceLogo();
+    boolean showConsHist = av.isShowConsensusHistogram();
+
+    boolean sortg = true;
+
+    // remove old automatic annotation
+    // add any new annotation
+
+    Vector gr = av.alignment.getGroups(); // OrderedBy(av.alignment.getSequencesArray());
+    // intersect alignment annotation with alignment groups
+
+    AlignmentAnnotation[] aan = av.alignment.getAlignmentAnnotation();
+    Hashtable oldrfs = new Hashtable();
+    if (aan != null)
+    {
+      for (int an = 0; an < aan.length; an++)
+      {
+        if (aan[an].autoCalculated && aan[an].groupRef != null)
+        {
+          oldrfs.put(aan[an].groupRef, aan[an].groupRef);
+          av.alignment.deleteAnnotation(aan[an]);
+          aan[an] = null;
+        }
+      }
+    }
+    SequenceGroup sg;
+    if (gr != null)
+    {
+      for (int g = 0; g < gr.size(); g++)
+      {
+        updateCalcs = false;
+        sg = (SequenceGroup) gr.elementAt(g);
+        if (applyGlobalSettings || !oldrfs.containsKey(sg))
+        {
+          // set defaults for this group's conservation/consensus
+          sg.setshowSequenceLogo(showprf);
+          sg.setShowConsensusHistogram(showConsHist);
+        }
+        if (conv)
+        {
+          updateCalcs = true;
+          av.alignment.addAnnotation(sg.getConservationRow(), 0);
+        }
+        if (cons)
+        {
+          updateCalcs = true;
+          av.alignment.addAnnotation(sg.getConsensus(), 0);
+        }
+        // refresh the annotation rows
+        if (updateCalcs)
+        {
+          sg.recalcConservation();
+        }
+      }
+    }
+    oldrfs.clear();
+    adjustAnnotationHeight();
+  }
+  /**
+   * automatically adjust annotation panel height for new annotation
+   * whilst ensuring the alignment is still visible.
+   */
+  public void adjustAnnotationHeight()
+  {
+    // TODO: display vertical annotation scrollbar if necessary
+    // this is called after loading new annotation onto alignment
+    if (alignFrame.getHeight() == 0)
+    {
+      System.out.println("NEEDS FIXING");
+    }
+    fontChanged();
+    int height = annotationPanel.adjustPanelHeight();
+    if (hscroll.isVisible())
+    {
+      height += hscroll.getPreferredSize().height;
+    }
+    int mheight=height;
+    // sets initial preferred height
+    if (height > alignFrame.getHeight() / 2)
+    {
+      height = alignFrame.getHeight() / 2;
+    }
+    apvscroll.setValues(apvscroll.getValue(), height, 0, mheight);
+    annotationPanel.setScrollOffset(apvscroll.getValue());
+    alabels.setScrollOffset(apvscroll.getValue());
+    apvscroll.addNotify();
+    hscroll.addNotify();
+
+    annotationPanelHolder.setPreferredSize(new Dimension(annotationPanel
+            .getWidth(), height));
+
+    annotationSpaceFillerHolder.setPreferredSize(new Dimension(
+            annotationSpaceFillerHolder.getWidth(), height));
+    
+    //annotationScroller.validate();// repaint();
+    validate();
+    addNotify();
+    repaint();
+  }
+
 }
index 2184851..059e07f 100755 (executable)
@@ -21,6 +21,7 @@ import java.util.*;
 
 import java.awt.*;
 import java.awt.event.*;
+import java.awt.image.BufferedImage;
 
 import jalview.datamodel.*;
 
@@ -64,6 +65,31 @@ public class AnnotationLabels extends Panel implements ActionListener,
     this.ap = ap;
     this.av = ap.av;
     setLayout(null);
+
+    java.net.URL url = getClass().getResource("/images/idwidth.gif");
+    Image temp = null;
+
+    if (url != null)
+    {
+      temp = java.awt.Toolkit.getDefaultToolkit().createImage(url);
+    }
+
+    try
+    {
+      MediaTracker mt = new MediaTracker(this);
+      mt.addImage(temp, 0);
+      mt.waitForID(0);
+    } catch (Exception ex)
+    {
+    }
+
+    BufferedImage bi = new BufferedImage(temp.getHeight(this),
+            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);
+    image = (Image) bi;
+
     addMouseListener(this);
     addMouseMotionListener(this);
   }
@@ -200,9 +226,13 @@ public class AnnotationLabels extends Panel implements ActionListener,
 
   }
 
+  boolean resizePanel = false;
+
   public void mouseMoved(MouseEvent evt)
   {
-    int row = getSelectedRow(evt.getY() - scrollOffset);
+    resizePanel = evt.getY() < 10;
+
+    int row = getSelectedRow(evt.getY() + scrollOffset);
 
     if (row > -1)
     {
@@ -226,8 +256,38 @@ public class AnnotationLabels extends Panel implements ActionListener,
 
   }
 
+  MouseEvent dragEvent = null;
+
   public void mouseDragged(MouseEvent evt)
   {
+    dragEvent = evt;
+
+    if (resizePanel)
+    {
+      Dimension d = ap.annotationPanelHolder.getSize(),e = ap.annotationSpaceFillerHolder.getSize();;
+      int dif = evt.getY() - oldY;
+
+      dif /= ap.av.charHeight;
+      dif *= ap.av.charHeight;
+
+      if ((d.height - dif) > 20)
+      {
+        
+        setPreferredSize(new Dimension(e.width,d.height-dif));
+        ap.annotationSpaceFillerHolder.setPreferredSize(new Dimension(e.width, d.height - dif));
+        ap.annotationPanelHolder.setPreferredSize(new Dimension(d.width, d.height - dif));
+        ap.apvscroll.setValues(ap.apvscroll.getValue(), d.height-dif, 0, ap.annotationPanel.adjustPanelHeight(false));
+        
+        ap.validate();
+        //ap.paintAlignment(true);
+      }
+
+      ap.addNotify();
+    }
+    else
+    {
+      repaint();
+    }
   }
 
   public void mouseClicked(MouseEvent evt)
@@ -236,34 +296,75 @@ public class AnnotationLabels extends Panel implements ActionListener,
 
   public void mouseReleased(MouseEvent evt)
   {
+    resizePanel = false;
+    dragEvent = null;
+    repaint();
+    ap.annotationPanel.repaint();
   }
 
   public void mouseEntered(MouseEvent evt)
   {
+    if (evt.getY() < 10)
+    {
+      resizePanel = true;
+      repaint();
+    }
   }
 
   public void mouseExited(MouseEvent evt)
   {
+
+    if (dragEvent == null)
+    {
+      resizePanel = false;
+    }
+    else
+    {
+      if (!resizePanel)
+      {
+        dragEvent = null;
+      }
+    }
+    repaint();
   }
 
   public void mousePressed(MouseEvent evt)
   {
-    selectedRow = getSelectedRow(evt.getY() - scrollOffset);
+    oldY = evt.getY();
+    // todo: move below to mouseClicked ?
+    selectedRow = getSelectedRow(evt.getY() + scrollOffset);
+
     AlignmentAnnotation[] aa = ap.av.alignment.getAlignmentAnnotation();
 
     // DETECT RIGHT MOUSE BUTTON IN AWT
     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
     {
 
+      PopupMenu popup = new PopupMenu("Annotations");
 
-    PopupMenu popup = new PopupMenu("Annotations");
-
-    MenuItem item = new MenuItem(ADDNEW);
-    item.addActionListener(this);
-    popup.add(item);
-    if (selectedRow < 0)
-    {
-      // this never happens at moment: - see comment on JAL-563
+      MenuItem item = new MenuItem(ADDNEW);
+      item.addActionListener(this);
+      popup.add(item);
+      if (selectedRow < 0)
+      {
+        // this never happens at moment: - see comment on JAL-563
+        if (hasHiddenRows)
+        {
+          item = new MenuItem(SHOWALL);
+          item.addActionListener(this);
+          popup.add(item);
+        }
+        this.add(popup);
+        popup.show(this, evt.getX(), evt.getY());
+        return;
+      }
+      // add the rest if there are actually rows to show
+      item = new MenuItem(EDITNAME);
+      item.addActionListener(this);
+      popup.add(item);
+      item = new MenuItem(HIDE);
+      item.addActionListener(this);
+      popup.add(item);
       if (hasHiddenRows)
       {
         item = new MenuItem(SHOWALL);
@@ -271,49 +372,34 @@ public class AnnotationLabels extends Panel implements ActionListener,
         popup.add(item);
       }
       this.add(popup);
-      popup.show(this, evt.getX(), evt.getY());
-      return;
-    }
-    // add the rest if there are actually rows to show
-    item = new MenuItem(EDITNAME);
-    item.addActionListener(this);
-    popup.add(item);
-    item = new MenuItem(HIDE);
-    item.addActionListener(this);
-    popup.add(item);
-    if (hasHiddenRows)
-    {
-      item = new MenuItem(SHOWALL);
+      item = new MenuItem(OUTPUT_TEXT);
       item.addActionListener(this);
       popup.add(item);
-    }
-    this.add(popup);
-    item = new MenuItem(OUTPUT_TEXT);
-    item.addActionListener(this);
-    popup.add(item);
 
-    if (aa[selectedRow] == ap.av.consensus)
-    {
-      popup.addSeparator();
-      final CheckboxMenuItem cbmi = new CheckboxMenuItem(
-              "Ignore Gaps In Consensus", ap.av.getIgnoreGapsConsensus());
-
-      cbmi.addItemListener(new ItemListener()
+      if (aa[selectedRow] == ap.av.consensus)
       {
-        public void itemStateChanged(ItemEvent e)
+        popup.addSeparator();
+        final CheckboxMenuItem cbmi = new CheckboxMenuItem(
+                "Ignore Gaps In Consensus", ap.av.getIgnoreGapsConsensus());
+
+        cbmi.addItemListener(new ItemListener()
         {
-          ap.av.setIgnoreGapsConsensus(cbmi.getState());
-          ap.paintAlignment(true);
-        }
-      });
-      popup.add(cbmi);
-      item = new MenuItem(COPYCONS_SEQ);
-      item.addActionListener(this);
-      popup.add(item);
-    }
+          public void itemStateChanged(ItemEvent e)
+          {
+            ap.av.setIgnoreGapsConsensus(cbmi.getState());
+            ap.paintAlignment(true);
+          }
+        });
+        popup.add(cbmi);
+        item = new MenuItem(COPYCONS_SEQ);
+        item.addActionListener(this);
+        popup.add(item);
+      }
 
-    popup.show(this, evt.getX(), evt.getY());
-    } else {
+      popup.show(this, evt.getX(), evt.getY());
+    }
+    else
+    {
       // selection action.
       if (selectedRow > -1 && selectedRow < aa.length)
       {
@@ -321,7 +407,8 @@ public class AnnotationLabels extends Panel implements ActionListener,
         {
           if (evt.getClickCount() >= 2)
           {
-            // todo: make the ap scroll to the selection - not necessary, first click highlights/scrolls, second selects
+            // 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); // );
@@ -417,7 +504,7 @@ public class AnnotationLabels extends Panel implements ActionListener,
     g.setColor(Color.white);
     g.fillRect(0, 0, getSize().width, getSize().height);
 
-    g.translate(0, scrollOffset);
+    g.translate(0, -scrollOffset);
     g.setColor(Color.black);
 
     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
@@ -443,6 +530,27 @@ public class AnnotationLabels extends Panel implements ActionListener,
         g.drawString(aa[i].label, x, y + offset);
       }
     }
+    g.translate(0, +scrollOffset);
+    if (resizePanel)
+    {
+      g.setColor(Color.red);
+      g.setPaintMode();
+      g.drawLine(2, 8, 5, 2);
+      g.drawLine(5, 2, 8, 8);
+    }
+    else if (dragEvent != null && aa != null)
+    {
+      g.setColor(Color.lightGray);
+      g.drawString(aa[selectedRow].label, dragEvent.getX(),
+              dragEvent.getY());
+    }
+
+    if ((aa == null) || (aa.length < 1))
+    {
+      g.setColor(Color.black);
+      g.drawString("Right click", 2, 8);
+      g.drawString("to add annotation", 2, 18);
+    }
   }
 
 }
index c3f17f9..11a957a 100755 (executable)
@@ -21,6 +21,10 @@ import java.util.*;
 
 import java.awt.*;
 import java.awt.event.*;
+import java.awt.font.LineMetrics;
+import java.awt.geom.AffineTransform;
+
+import jalview.analysis.AAFrequency;
 import jalview.datamodel.*;
 import jalview.schemes.ColourSchemeI;
 
@@ -76,7 +80,8 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
     this.ap = ap;
     av = ap.av;
     setLayout(null);
-    adjustPanelHeight();
+    int height = adjustPanelHeight();
+    ap.apvscroll.setValues(0, getHeight(), 0, height);
 
     addMouseMotionListener(this);
 
@@ -92,7 +97,6 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
 
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
-    ap.alabels.setScrollOffset(-evt.getValue());
   }
 
   /**
@@ -256,7 +260,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
       return;
     }
 
-    int height = 0;
+    int height = -scrollOffset;
     activeRow = -1;
 
     for (int i = 0; i < aa.length; i++)
@@ -370,7 +374,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
     }
 
     int row = -1;
-    int height = 0;
+    int height = -scrollOffset;
     for (int i = 0; i < aa.length; i++)
     {
 
@@ -417,6 +421,12 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
 
   public int adjustPanelHeight()
   {
+    return adjustPanelHeight(true);
+  }
+
+  public int adjustPanelHeight(boolean repaint)
+  {
+
     // setHeight of panels
     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
     int height = 0;
@@ -459,8 +469,11 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
     {
       height = 20;
     }
-    this.setSize(getSize().width, height);
-    repaint();
+    this.setPreferredSize(new Dimension(getSize().width, height));
+    if (repaint)
+    {
+      repaint();
+    }
 
     return height;
 
@@ -601,7 +614,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
     }
 
     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();
-
+    g.translate(0, -scrollOffset);
     int x = 0;
     int y = 0;
     int column = 0;
@@ -988,6 +1001,7 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
         y += aa[i].height;
       }
     }
+    g.translate(0, +scrollOffset);
   }
 
   public void drawLineGraph(Graphics g, AlignmentAnnotation aa, int sRes,
@@ -1107,15 +1121,20 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
     int column;
     int aaMax = aa.annotations.length - 1;
     boolean renderHistogram = true, renderProfile = false;
-    /*
-     * Logos are disabled for 2.5 release : Bug # 0060064 if (aa.autoCalculated
-     * && aa.label.startsWith("Consensus")) { // TODO: generalise this to have
-     * render styles for consensus/profile data if (aa.groupRef!=null) {
-     * renderHistogram = aa.groupRef.isShowConsensusHistogram(); renderProfile =
-     * aa.groupRef.isShowSequenceLogo(); } else { renderHistogram =
-     * av.isShowConsensusHistogram(); renderProfile = av.isShowSequenceLogo(); }
-     * }
-     */
+    if (aa.autoCalculated && aa.label.startsWith("Consensus"))
+    { // TODO: generalise this to have render styles for consensus/profile data
+      if (aa.groupRef != null)
+      {
+        renderHistogram = aa.groupRef.isShowConsensusHistogram();
+        renderProfile = aa.groupRef.isShowSequenceLogo();
+      }
+      else
+      {
+        renderHistogram = av.isShowConsensusHistogram();
+        renderProfile = av.isShowSequenceLogo();
+      }
+    }
+
     while (x < eRes - sRes)
     {
       column = sRes + x;
@@ -1155,22 +1174,37 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
         }
       }
       // draw profile if available
-      // Disabled for 2.5 release: see bug #0060064
-      /**
-       * if (aa.annotations[column].value!=0 && renderProfile) { int profl[] =
-       * getProfileFor(aa,column); int ht = y1; //,htn=y2-y1;//aa.graphHeight;
-       * float wdth; double ht2=0; char[] dc = new char[1]; // LineMetrics lm;
-       * for (int c=1;profl!=null && c<profl[0];) { dc[0] = (char) profl[c++];
-       * wdth = av.charWidth; wdth/=(float) fm .charsWidth(dc,0,1);
-       * 
-       * if (c>2) { ht+=(int)ht2; } { // not java 1.1 compatible: Bug # 0060064
-       * g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(wdth,
-       * (ht2=(htn*((double)profl[c++])/100.0))/av.charHeight))); lm =
-       * g.getFontMetrics().getLineMetrics(dc,0,1, g);
-       * g.setColor(profcolour.findColour(dc[0]));
-       * g.drawChars(dc,0,1,x*av.charWidth, (int) (ht+lm.getHeight())); } }
-       * g.setFont(ofont); }
-       **/
+      if (aa.annotations[column].value != 0 && renderProfile)
+      {
+        int profl[] = getProfileFor(aa, column);
+        int ht = y1, htn = y2 - y1;// aa.graphHeight;
+        float wdth;
+        double ht2 = 0;
+        char[] dc = new char[1];
+        LineMetrics lm;
+        for (int c = 1; profl != null && c < profl[0];)
+        {
+          dc[0] = (char) profl[c++];
+          wdth = av.charWidth;
+          wdth /= (float) fm.charsWidth(dc, 0, 1);
+
+          if (c > 2)
+          {
+            ht += (int) ht2;
+          }
+          { // not java 1.1 compatible: Bug # 0060064
+            g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(
+                    wdth, (ht2 = (htn * ((double) profl[c++]) / 100.0))
+                            / av.charHeight)));
+            lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g);
+            g.setColor(profcolour.findColour(dc[0]));
+            g.drawChars(dc, 0, 1, x * av.charWidth,
+                    (int) (ht + lm.getHeight()));
+          }
+        }
+        g.setFont(ofont);
+      }
+
       x++;
 
     }
@@ -1182,20 +1216,26 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
     }
   }
 
-  /*
-   * Disabled for 2.5 release - see bug #0060064 private int[]
-   * getProfileFor(AlignmentAnnotation aa, int column) { // if
-   * (aa.autoCalculated && aa.label.startsWith("Consensus")) { if
-   * (aa.groupRef!=null && aa.groupRef.consensusData!=null) { // &&
-   * aa.groupRef.isShowSequenceLogo()) { return
-   * AAFrequency.extractProfile(aa.groupRef
-   * .consensusData[column],aa.groupRef.getIgnoreGapsConsensus()); } // TODO
-   * extend annotation row to enable dynamic and static profile data to be
-   * stored if (aa.groupRef==null && aa.sequenceRef==null) // &&
-   * av.isShowSequenceLogo()) { return
-   * AAFrequency.extractProfile(av.hconsensus[column
-   * ],av.getIgnoreGapsConsensus()); } // } return null; }
-   */
+  private int[] getProfileFor(AlignmentAnnotation aa, int column)
+  {
+    // if (aa.autoCalculated && aa.label.startsWith("Consensus")) {
+    if (aa.groupRef != null && aa.groupRef.consensusData != null)
+    {
+      // && aa.groupRef.isShowSequenceLogo()) {
+      return AAFrequency.extractProfile(aa.groupRef.consensusData[column],
+              aa.groupRef.getIgnoreGapsConsensus());
+    }
+    // TODO extend annotation row to enable dynamic and static profile data to
+    // be stored
+    if (aa.groupRef == null && aa.sequenceRef == null)
+    // && av.isShowSequenceLogo())
+    {
+      return AAFrequency.extractProfile(av.hconsensus[column],
+              av.getIgnoreGapsConsensus());
+    }
+    // }
+    return null;
+  }
 
   // used by overview window
   public void drawGraph(Graphics g, AlignmentAnnotation aa, int width,
@@ -1224,4 +1264,12 @@ public class AnnotationPanel extends Panel implements AdjustmentListener,
       x += av.charWidth;
     }
   }
+
+  int scrollOffset = 0;
+
+  public void setScrollOffset(int value)
+  {
+    scrollOffset = value;
+    repaint();
+  }
 }