Merge branch 'releases/Release_2_11_3_Branch'
[jalview.git] / src / jalview / gui / AnnotationLabels.java
index ffc565c..7c5afcd 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import java.awt.Canvas;
 import java.awt.Color;
 import java.awt.Cursor;
 import java.awt.Dimension;
@@ -87,7 +88,7 @@ public class AnnotationLabels extends JPanel
   /**
    * height in pixels for allowing height adjuster to be active
    */
-  private static int HEIGHT_ADJUSTER_HEIGHT = 10;
+  public static int HEIGHT_ADJUSTER_HEIGHT = 10;
 
   private static final Font font = new Font("Arial", Font.PLAIN, 11);
 
@@ -135,6 +136,10 @@ public class AnnotationLabels extends JPanel
 
   private boolean resizePanel = false;
 
+  private int annotationIdWidth = -1;
+
+  public static final String RESIZE_MARGINS_MARK_PREF = "RESIZE_MARGINS_MARK";
+
   /**
    * Creates a new AnnotationLabels object
    * 
@@ -512,8 +517,10 @@ public class AnnotationLabels extends JPanel
           public void actionPerformed(ActionEvent e)
           {
             sel_row.setShowGroupsForContactMatrix(chitem.getState());
-            ap.getAnnotationPanel()
-                    .paint(ap.getAnnotationPanel().getGraphics());
+            // so any annotation colour changes are propagated - though they
+            // probably won't be unless the annotation row colours are removed
+            // too!
+            ap.alignmentChanged();
           }
         });
         pop.add(chitem);
@@ -559,7 +566,10 @@ public class AnnotationLabels extends JPanel
                                 "action.clustering_matrix_for",
                                 cm.getAnnotDescr(), 5f),
                         progBar = System.currentTimeMillis());
-                cm.setGroupSet(GroupSet.makeGroups(cm, 5f, true));
+                cm.setGroupSet(GroupSet.makeGroups(cm, true));
+                cm.randomlyReColourGroups();
+                cm.transferGroupColorsTo(alignmentAnnotation);
+                ap.alignmentChanged();
                 ap.alignFrame.showContactMapTree(alignmentAnnotation, cm);
                 ap.alignFrame.setProgressBar(null, progBar);
               }
@@ -783,9 +793,15 @@ public class AnnotationLabels extends JPanel
     {
       Dimension d = ap.annotationScroller.getPreferredSize();
       int dif = evt.getY() - oldY;
+      dif -= dif % ap.av.getCharHeight();
 
-      dif /= ap.av.getCharHeight();
-      dif *= ap.av.getCharHeight();
+      // don't allow setting an annotation panel height larger than visible
+      // (otherwise you can't get back)
+      if (d.height - dif > ap.idPanelHolder.getHeight()
+              - ap.getIdSpaceFillerPanel1().getHeight())
+      {
+        return;
+      }
 
       if ((d.height - dif) > 20)
       {
@@ -1102,7 +1118,7 @@ public class AnnotationLabels extends JPanel
     if (av.hasHiddenColumns())
     {
       Iterator<int[]> it = av.getAlignment().getHiddenColumns()
-              .getVisContigsIterator(0, sq.getLength(), false);
+              .getVisContigsIterator(0, sq.getLength() + 1, false);
       omitHidden = new String[] { sq.getSequenceStringFromIterator(it) };
     }
 
@@ -1158,8 +1174,7 @@ public class AnnotationLabels extends JPanel
               RenderingHints.VALUE_ANTIALIAS_ON);
     }
 
-    drawComponent(g2, true, width);
-
+    drawComponent(g2, true, width, true);
   }
 
   /**
@@ -1174,7 +1189,7 @@ public class AnnotationLabels extends JPanel
    */
   public void drawComponent(Graphics g, int width)
   {
-    drawComponent(g, false, width);
+    drawComponent(g, false, width, true);
   }
 
   /**
@@ -1189,72 +1204,141 @@ public class AnnotationLabels extends JPanel
    * @param width
    *          Width for scaling labels
    */
-  public void drawComponent(Graphics g, boolean clip, int givenWidth)
+  public void drawComponent(Graphics g, boolean clip, int givenWidth,
+          boolean forGUI)
   {
     int width = givenWidth;
-    IdwidthAdjuster iwa = ap.idwidthAdjuster;
-    if ((Cache.getDefault(ADJUST_ANNOTATION_LABELS_WIDTH_PREF, true)
-            || Jalview.isHeadlessMode()))
+    IdwidthAdjuster iwa = null;
+    if (ap != null)
     {
-      Graphics2D g2d = (Graphics2D) g;
-      Graphics dummy = g2d.create();
-      int annotationIdWidth = drawLabels(dummy, clip, width, false);
-      Dimension d = ap.calculateDefaultAlignmentIdWidth();
-      int alignmentIdWidth = d.width;
-      if (!iwa.manuallyAdjusted())
-      {
-        // If no manual adjustment to ID column with has been made then adjust
-        // width match widest of alignment or annotation id widths
-        width = Math.max(alignmentIdWidth, annotationIdWidth);
-      }
-      else if (annotationIdWidth > givenWidth
-              && annotationIdWidth > alignmentIdWidth)
-      {
-        // otherwise if the annotation id width has become larger than the
-        // current id width, increase
-        width = annotationIdWidth;
-      }
-      // set the width if it's changed
-      if (width != ap.av.getIdWidth())
+      iwa = ap.idwidthAdjuster;
+      if (Cache.getDefault(ADJUST_ANNOTATION_LABELS_WIDTH_PREF, true)
+              || Jalview.isHeadlessMode())
       {
-        iwa.setWidth(width);
-        ap.validateAnnotationDimensions(false);
+        Graphics2D g2d = (Graphics2D) g;
+        Graphics dummy = g2d.create();
+        int newAnnotationIdWidth = drawLabels(dummy, clip, width, false,
+                forGUI, null, false);
+        dummy.dispose();
+        Dimension d = ap.calculateDefaultAlignmentIdWidth();
+        int alignmentIdWidth = d.width;
+        if (iwa != null && !iwa.manuallyAdjusted())
+        {
+          // If no manual adjustment to ID column with has been made then adjust
+          // width match widest of alignment or annotation id widths
+          boolean allowShrink = Cache.getDefault("ALLOW_SHRINK_ID_WIDTH",
+                  false);
+          width = Math.max(alignmentIdWidth, newAnnotationIdWidth);
+          if (clip && width < givenWidth && !allowShrink)
+          {
+            width = givenWidth;
+          }
+        }
+        else if (newAnnotationIdWidth != annotationIdWidth
+                && newAnnotationIdWidth > givenWidth
+                && newAnnotationIdWidth > alignmentIdWidth)
+        {
+          // otherwise if the annotation id width has become larger than the
+          // current id width, increase
+          width = newAnnotationIdWidth;
+          annotationIdWidth = newAnnotationIdWidth;
+        }
+        // set the width if it's changed
+        if (width != ap.av.getIdWidth())
+        {
+          iwa.setWidth(width);
+        }
       }
     }
-    drawLabels(g, clip, width, true);
+    else
+    {
+      int newAnnotationIdWidth = drawLabels(g, clip, width, false, forGUI,
+              null, false);
+      width = newAnnotationIdWidth < givenWidth ? givenWidth
+              : Math.min(newAnnotationIdWidth, givenWidth);
+    }
+    drawLabels(g, clip, width, true, forGUI, null, false);
   }
 
   /**
    * Render the full set of annotation Labels for the alignment at the given
-   * cursor. If actuallyDraw is false then no actual drawing will occur, but the
-   * widest label width will be returned.
+   * cursor. If actuallyDraw is false or g is null then no actual drawing will
+   * occur, but the widest label width will be returned. If g is null then
+   * fmetrics must be supplied.
    * 
    * @param g
-   *          Graphics2D instance (needed for font scaling)
+   *          Graphics2D instance (used for rendering and font scaling if no
+   *          fmetrics supplied)
    * @param clip
    *          - true indicates that only current visible area needs to be
    *          rendered
    * @param width
    *          Width for scaling labels
+   * @param actuallyDraw
+   *          - when false, no graphics are rendered to g0
+   * @param forGUI
+   *          - when false, GUI relevant marks like indicators for dragging
+   *          annotation panel height are not rendered
+   * @param fmetrics
+   *          FontMetrics if Graphics object g is null
+   * @param includeHidden
+   *          - when true returned width includes labels in hidden row width
+   *          calculation
+   * @return the width of the annotation labels.
    */
-  public int drawLabels(Graphics g, boolean clip, int width,
-          boolean actuallyDraw)
+  public int drawLabels(Graphics g0, boolean clip, int width,
+          boolean actuallyDraw, boolean forGUI, FontMetrics fmetrics,
+          boolean includeHidden)
   {
-    int actualWidth = 0;
-    if (av.getFont().getSize() < 10)
+    if (clip)
     {
-      g.setFont(font);
+      clip = Cache.getDefault("MOVE_SEQUENCE_ID_WITH_VISIBLE_ANNOTATIONS",
+              true);
     }
-    else
+    Graphics g = null;
+    // create a dummy Graphics object if not drawing and one is supplied
+    if (g0 != null)
+    {
+      if (!actuallyDraw)
+      {
+        Graphics2D g2d = (Graphics2D) g0;
+        g = g2d.create();
+      }
+      else
+      {
+        g = g0;
+      }
+    }
+    int actualWidth = 0;
+    if (g != null)
     {
-      g.setFont(av.getFont());
+      if (av.getFont().getSize() < 10)
+      {
+        g.setFont(font);
+      }
+      else
+      {
+        g.setFont(av.getFont());
+      }
     }
 
-    FontMetrics fm = g.getFontMetrics(g.getFont());
+    FontMetrics fm = fmetrics == null ? g.getFontMetrics(g.getFont())
+            : fmetrics;
     if (actuallyDraw)
     {
       g.setColor(Color.white);
       g.fillRect(0, 0, getWidth(), getHeight());
+
+      if (!Cache.getDefault(RESIZE_MARGINS_MARK_PREF, false)
+              && !av.getWrapAlignment() && forGUI)
+      {
+        g.setColor(Color.LIGHT_GRAY);
+        g.drawLine(0, HEIGHT_ADJUSTER_HEIGHT / 4, HEIGHT_ADJUSTER_WIDTH / 4,
+                HEIGHT_ADJUSTER_HEIGHT / 4);
+        g.drawLine(0, 3 * HEIGHT_ADJUSTER_HEIGHT / 4,
+                HEIGHT_ADJUSTER_WIDTH / 4, 3 * HEIGHT_ADJUSTER_HEIGHT / 4);
+
+      }
     }
 
     if (actuallyDraw)
@@ -1265,12 +1349,13 @@ public class AnnotationLabels extends JPanel
     SequenceI lastSeqRef = null;
     String lastLabel = null;
     AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
-    int fontHeight = g.getFont().getSize();
+    int fontHeight = g != null ? g.getFont().getSize()
+            : fm.getFont().getSize();
     int y = 0;
     int x = 0;
     int graphExtras = 0;
     int offset = 0;
-    Font baseFont = g.getFont();
+    Font baseFont = g != null ? g.getFont() : fm.getFont();
     FontMetrics baseMetrics = fm;
     int ofontH = fontHeight;
     int sOffset = 0;
@@ -1292,7 +1377,7 @@ public class AnnotationLabels extends JPanel
       for (int i = 0; i < aa.length; i++)
       {
         visible = true;
-        if (!aa[i].visible)
+        if (!aa[i].visible && !includeHidden)
         {
           hasHiddenRows = true;
           continue;
@@ -1300,7 +1385,7 @@ public class AnnotationLabels extends JPanel
         olY = y;
         // look ahead to next annotation
         for (nexAA = i + 1; nexAA < aa.length
-                && !aa[nexAA].visible; nexAA++)
+                && (!aa[nexAA].visible && includeHidden); nexAA++)
           ;
         y += aa[i].height;
         if (clip)
@@ -1311,7 +1396,7 @@ public class AnnotationLabels extends JPanel
             {
               if (debugRedraw)
               {
-                System.out.println("before vis: " + i);
+                jalview.bin.Console.outPrintln("before vis: " + i);
               }
               before = true;
             }
@@ -1325,7 +1410,7 @@ public class AnnotationLabels extends JPanel
             {
               if (debugRedraw)
               {
-                System.out.println(
+                jalview.bin.Console.outPrintln(
                         "Scroll offset: " + sOffset + " after vis: " + i);
               }
               after = true;
@@ -1334,7 +1419,7 @@ public class AnnotationLabels extends JPanel
             continue;
           }
         }
-        if (actuallyDraw)
+        if (actuallyDraw && g != null)
         {
           g.setColor(Color.black);
         }
@@ -1417,10 +1502,15 @@ public class AnnotationLabels extends JPanel
               s = ((float) fontHeight) / (float) ofontH;
               Font f = baseFont
                       .deriveFont(AffineTransform.getScaleInstance(s, s));
-              g.setFont(f);
-              fm = g.getFontMetrics();
-              graphExtras = (aa[i].height - (groupSize * (fontHeight + 8)))
-                      / 2;
+              Canvas c = new Canvas();
+              fm = c.getFontMetrics(f);
+              if (actuallyDraw && g != null)
+              {
+                g.setFont(f);
+                // fm = g.getFontMetrics();
+                graphExtras = (aa[i].height
+                        - (groupSize * (fontHeight + 8))) / 2;
+              }
             }
           }
           if (visible)
@@ -1431,7 +1521,7 @@ public class AnnotationLabels extends JPanel
               {
                 labelWidth = fm.stringWidth(aa[gg].label) + 3;
                 x = width - labelWidth;
-                if (actuallyDraw)
+                if (actuallyDraw && g != null)
                 {
                   g.drawString(aa[gg].label, x, y - graphExtras);
 
@@ -1450,13 +1540,16 @@ public class AnnotationLabels extends JPanel
               }
             }
           }
-          g.setFont(baseFont);
+          if (actuallyDraw && g != null)
+          {
+            g.setFont(baseFont);
+          }
           fm = baseMetrics;
           fontHeight = ofontH;
         }
         else
         {
-          if (actuallyDraw)
+          if (actuallyDraw && g != null)
           {
             if (vertBar)
             {
@@ -1477,9 +1570,10 @@ public class AnnotationLabels extends JPanel
       }
     }
 
-    if (!resizePanel && dragEvent != null && aa != null)
+    if (!resizePanel && dragEvent != null && aa != null && selectedRow > -1
+            && selectedRow < aa.length)
     {
-      if (actuallyDraw)
+      if (actuallyDraw && g != null)
       {
         g.setColor(Color.lightGray);
         g.drawString(
@@ -1492,7 +1586,7 @@ public class AnnotationLabels extends JPanel
 
     if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1)))
     {
-      if (actuallyDraw)
+      if (actuallyDraw && g != null)
       {
         g.drawString(MessageManager.getString("label.right_click"), 2, 8);
         g.drawString(MessageManager.getString("label.to_add_annotation"), 2,
@@ -1512,4 +1606,9 @@ public class AnnotationLabels extends JPanel
   public void mouseEntered(MouseEvent e)
   {
   }
+
+  public void drawComponentNotGUI(Graphics idGraphics, int idWidth)
+  {
+    drawComponent(idGraphics, false, idWidth, false);
+  }
 }