JAL-3116 parse EMBL XML with JAXB (todo: update unit tests)
[jalview.git] / src / jalview / gui / AlignmentPanel.java
index 6491c22..c03b56d 100644 (file)
@@ -37,7 +37,6 @@ import jalview.schemes.ResidueProperties;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.Comparison;
 import jalview.util.MessageManager;
-import jalview.util.Platform;
 import jalview.viewmodel.ViewportListenerI;
 import jalview.viewmodel.ViewportRanges;
 
@@ -48,7 +47,7 @@ import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics;
-import java.awt.Insets;
+import java.awt.Graphics2D;
 import java.awt.event.AdjustmentEvent;
 import java.awt.event.AdjustmentListener;
 import java.awt.event.ComponentAdapter;
@@ -419,8 +418,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
     if (av.hasHiddenColumns())
     {
       HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-      start = hidden.findColumnPosition(start);
-      end = hidden.findColumnPosition(end);
+      start = hidden.absoluteToVisibleColumn(start);
+      end = hidden.absoluteToVisibleColumn(end);
       if (start == end)
       {
         if (!hidden.isVisible(r[0]))
@@ -547,40 +546,10 @@ public class AlignmentPanel extends GAlignmentPanel implements
   protected void validateAnnotationDimensions(boolean adjustPanelHeight)
   {
     int annotationHeight = getAnnotationPanel().adjustPanelHeight();
+    annotationHeight = getAnnotationPanel()
+            .adjustForAlignFrame(adjustPanelHeight, annotationHeight);
 
-    if (adjustPanelHeight)
-    {
-      int rowHeight = av.getCharHeight();
-      int alignmentHeight = rowHeight * av.getAlignment().getHeight();
-
-      /*
-       * Estimate available height in the AlignFrame for alignment +
-       * annotations. Deduct an estimate for title bar, menu bar, scale panel,
-       * hscroll, status bar (as these are not laid out we can't inspect their
-       * actual heights). Insets gives frame borders.
-       */
-      int stuff = Platform.isAMac() ? 80 : 100;
-      Insets insets = alignFrame.getInsets();
-      int availableHeight = alignFrame.getHeight() - stuff - insets.top
-              - insets.bottom;
-
-      /*
-       * If not enough vertical space, maximize annotation height while keeping
-       * at least two rows of alignment visible
-       */
-      if (annotationHeight + alignmentHeight > availableHeight)
-      {
-        annotationHeight = Math.min(annotationHeight,
-                availableHeight - 2 * rowHeight);
-      }
-    }
-    else
-    {
-      // maintain same window layout whilst updating sliders
-      annotationHeight = annotationScroller.getSize().height;
-    }
     hscroll.addNotify();
-
     annotationScroller.setPreferredSize(
             new Dimension(annotationScroller.getWidth(), annotationHeight));
 
@@ -619,6 +588,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     {
       annotationScroller.setVisible(true);
       annotationSpaceFillerHolder.setVisible(true);
+      validateAnnotationDimensions(false);
     }
 
     int canvasWidth = getSeqPanel().seqCanvas.getWidth();
@@ -678,7 +648,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
       {
         // reset the width to exclude hidden columns
         width = av.getAlignment().getHiddenColumns()
-                .findColumnPosition(width);
+                .absoluteToVisibleColumn(width);
       }
 
       hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
@@ -874,15 +844,17 @@ public class AlignmentPanel extends GAlignmentPanel implements
   @Override
   public void paintComponent(Graphics g)
   {
-    invalidate();
+    invalidate(); // needed so that the id width adjuster works correctly
 
     Dimension d = getIdPanel().getIdCanvas().getPreferredSize();
     idPanelHolder.setPreferredSize(d);
     hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
-    validate();
+
+    validate(); // needed so that the id width adjuster works correctly
 
     /*
-     * set scroll bar positions
+     * set scroll bar positions - tried to remove but necessary for split panel to resize correctly
+     * though I still think this call should be elsewhere.
      */
     ViewportRanges ranges = av.getRanges();
     setScrollValues(ranges.getStartRes(), ranges.getStartSeq());
@@ -944,30 +916,16 @@ public class AlignmentPanel extends GAlignmentPanel implements
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param pg
-   *          DOCUMENT ME!
-   * @param pwidth
-   *          DOCUMENT ME!
-   * @param pheight
-   *          DOCUMENT ME!
-   * @param pi
-   *          DOCUMENT ME!
-   * 
-   * @return DOCUMENT ME!
-   * 
-   * @throws PrinterException
-   *           DOCUMENT ME!
-   */
-  /**
    * Draws the alignment image, including sequence ids, sequences, and
    * annotation labels and annotations if shown, on either one or two Graphics
-   * context.
+   * contexts.
    * 
    * @param pageWidth
+   *          in pixels
    * @param pageHeight
-   * @param pi
+   *          in pixels
+   * @param pageIndex
+   *          (0, 1, ...)
    * @param idGraphics
    *          the graphics context for sequence ids and annotation labels
    * @param alignmentGraphics
@@ -976,7 +934,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @return
    * @throws PrinterException
    */
-  public int printUnwrapped(int pageWidth, int pageHeight, int pi,
+  public int printUnwrapped(int pageWidth, int pageHeight, int pageIndex,
           Graphics idGraphics, Graphics alignmentGraphics)
           throws PrinterException
   {
@@ -990,8 +948,8 @@ public class AlignmentPanel extends GAlignmentPanel implements
             : idWidth;
 
     FontMetrics fm = getFontMetrics(av.getFont());
-    int charHeight = av.getCharHeight();
-    int scaleHeight = charHeight + fm.getDescent();
+    final int charHeight = av.getCharHeight();
+    final int scaleHeight = charHeight + fm.getDescent();
 
     idGraphics.setColor(Color.white);
     idGraphics.fillRect(0, 0, pageWidth, pageHeight);
@@ -1000,29 +958,20 @@ public class AlignmentPanel extends GAlignmentPanel implements
     /*
      * How many sequences and residues can we fit on a printable page?
      */
-    int totalRes = (pageWidth - idWidth) / av.getCharWidth();
+    final int totalRes = (pageWidth - idWidth) / av.getCharWidth();
 
-    int totalSeq = (pageHeight - scaleHeight) / charHeight - 1;
+    final int totalSeq = (pageHeight - scaleHeight) / charHeight - 1;
 
-    int alignmentWidth = av.getAlignment().getWidth();
-    int pagesWide = (alignmentWidth / totalRes) + 1;
+    final int alignmentWidth = av.getAlignment().getWidth();
+    final int pagesWide = (alignmentWidth / totalRes) + 1;
 
-    final int startRes = (pi % pagesWide) * totalRes;
-    int endRes = (startRes + totalRes) - 1;
+    final int startRes = (pageIndex % pagesWide) * totalRes;
+    final int endRes = Math.min(startRes + totalRes - 1,
+            alignmentWidth - 1);
 
-    if (endRes > (alignmentWidth - 1))
-    {
-      endRes = alignmentWidth - 1;
-    }
-
-    final int startSeq = (pi / pagesWide) * totalSeq;
-    int endSeq = startSeq + totalSeq;
-
-    int alignmentHeight = av.getAlignment().getHeight();
-    if (endSeq > alignmentHeight)
-    {
-      endSeq = alignmentHeight;
-    }
+    final int startSeq = (pageIndex / pagesWide) * totalSeq;
+    final int alignmentHeight = av.getAlignment().getHeight();
+    final int endSeq = Math.min(startSeq + totalSeq, alignmentHeight);
 
     int pagesHigh = ((alignmentHeight / totalSeq) + 1) * pageHeight;
 
@@ -1033,7 +982,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
     pagesHigh /= pageHeight;
 
-    if (pi >= (pagesWide * pagesHigh))
+    if (pageIndex >= (pagesWide * pagesHigh))
     {
       return Printable.NO_SUCH_PAGE;
     }
@@ -1052,47 +1001,12 @@ public class AlignmentPanel extends GAlignmentPanel implements
      * then reset to top left (0, 0)
      */
     idGraphics.translate(0, scaleHeight);
-    idGraphics.setFont(getIdPanel().getIdCanvas().getIdfont());
-    Color currentColor = null;
-    Color currentTextColor = null;
+    IdCanvas idCanvas = getIdPanel().getIdCanvas();
+    List<SequenceI> selection = av.getSelectionGroup() == null ? null
+            : av.getSelectionGroup().getSequences(null);
+    idCanvas.drawIds((Graphics2D) idGraphics, av, startSeq, endSeq - 1,
+            selection);
 
-    SequenceI seq;
-    for (int i = startSeq; i < endSeq; i++)
-    {
-      seq = av.getAlignment().getSequenceAt(i);
-      if ((av.getSelectionGroup() != null)
-              && av.getSelectionGroup().getSequences(null).contains(seq))
-      {
-        /*
-         * gray out ids of sequences in selection group (if any)
-         */
-        currentColor = Color.gray;
-        currentTextColor = Color.black;
-      }
-      else
-      {
-        currentColor = av.getSequenceColour(seq);
-        currentTextColor = Color.black;
-      }
-
-      idGraphics.setColor(currentColor);
-      idGraphics.fillRect(0, (i - startSeq) * charHeight, idWidth,
-              charHeight);
-
-      idGraphics.setColor(currentTextColor);
-
-      int xPos = 0;
-      String displayId = seq.getDisplayId(av.getShowJVSuffix());
-      if (av.isRightAlignIds())
-      {
-        fm = idGraphics.getFontMetrics();
-        xPos = idWidth - fm.stringWidth(displayId) - 4;
-      }
-
-      idGraphics.drawString(displayId, xPos,
-              (((i - startSeq) * charHeight) + charHeight)
-                      - (charHeight / 5));
-    }
     idGraphics.setFont(av.getFont());
     idGraphics.translate(0, -scaleHeight);
 
@@ -1102,7 +1016,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
      */
     alignmentGraphics.translate(alignmentGraphicsOffset, scaleHeight);
     getSeqPanel().seqCanvas.drawPanelForPrinting(alignmentGraphics, startRes,
-            endRes, startSeq, endSeq);
+            endRes, startSeq, endSeq - 1);
     alignmentGraphics.translate(-alignmentGraphicsOffset, 0);
 
     if (av.isShowAnnotation() && (endSeq == alignmentHeight))
@@ -1132,31 +1046,27 @@ public class AlignmentPanel extends GAlignmentPanel implements
   }
 
   /**
-   * DOCUMENT ME!
+   * Prints one page of an alignment in wrapped mode. Returns
+   * Printable.PAGE_EXISTS (0) if a page was drawn, or Printable.NO_SUCH_PAGE if
+   * no page could be drawn (page number out of range).
    * 
-   * @param pg
-   *          DOCUMENT ME!
-   * @param pwidth
-   *          DOCUMENT ME!
-   * @param pheight
-   *          DOCUMENT ME!
-   * @param pi
-   *          DOCUMENT ME!
+   * @param pageWidth
+   * @param pageHeight
+   * @param pageNumber
+   *          (0, 1, ...)
+   * @param g
    * 
-   * @return DOCUMENT ME!
+   * @return
    * 
    * @throws PrinterException
-   *           DOCUMENT ME!
    */
-  public int printWrappedAlignment(int pwidth, int pheight, int pi,
-          Graphics pg) throws PrinterException
+  public int printWrappedAlignment(int pageWidth, int pageHeight, int pageNumber,
+          Graphics g) throws PrinterException
   {
     int annotationHeight = 0;
-    AnnotationLabels labels = null;
     if (av.isShowAnnotation())
     {
       annotationHeight = getAnnotationPanel().adjustPanelHeight();
-      labels = new AnnotationLabels(av);
     }
 
     int hgap = av.getCharHeight();
@@ -1174,68 +1084,43 @@ public class AlignmentPanel extends GAlignmentPanel implements
     if (av.hasHiddenColumns())
     {
       maxwidth = av.getAlignment().getHiddenColumns()
-              .findColumnPosition(maxwidth) - 1;
+              .absoluteToVisibleColumn(maxwidth) - 1;
     }
 
     int resWidth = getSeqPanel().seqCanvas
-            .getWrappedCanvasWidth(pwidth - idWidth);
+            .getWrappedCanvasWidth(pageWidth - idWidth);
 
     int totalHeight = cHeight * (maxwidth / resWidth + 1);
 
-    pg.setColor(Color.white);
-    pg.fillRect(0, 0, pwidth, pheight);
-    pg.setFont(av.getFont());
-
-    // //////////////
-    // Draw the ids
-    pg.setColor(Color.black);
+    g.setColor(Color.white);
+    g.fillRect(0, 0, pageWidth, pageHeight);
+    g.setFont(av.getFont());
+    g.setColor(Color.black);
 
-    pg.translate(0, -pi * pheight);
-
-    pg.setClip(0, pi * pheight, pwidth, pheight);
-
-    int ypos = hgap;
-
-    do
-    {
-      for (int i = 0; i < av.getAlignment().getHeight(); i++)
-      {
-        pg.setFont(getIdPanel().getIdCanvas().getIdfont());
-        SequenceI s = av.getAlignment().getSequenceAt(i);
-        String string = s.getDisplayId(av.getShowJVSuffix());
-        int xPos = 0;
-        if (av.isRightAlignIds())
-        {
-          FontMetrics fm = pg.getFontMetrics();
-          xPos = idWidth - fm.stringWidth(string) - 4;
-        }
-        pg.drawString(string, xPos,
-                ((i * av.getCharHeight()) + ypos + av.getCharHeight())
-                        - (av.getCharHeight() / 5));
-      }
-      if (labels != null)
-      {
-        pg.translate(-3, ypos
-                + (av.getAlignment().getHeight() * av.getCharHeight()));
+    /*
+     * method: print the whole wrapped alignment, but with a clip region that
+     * is restricted to the requested page; this supports selective print of 
+     * single  pages or ranges, (at the cost of some repeated processing in 
+     * the 'normal' case, when all pages are printed)
+     */
+    g.translate(0, -pageNumber * pageHeight);
 
-        pg.setFont(av.getFont());
-        labels.drawComponent(pg, idWidth);
-        pg.translate(+3, -ypos
-                - (av.getAlignment().getHeight() * av.getCharHeight()));
-      }
+    g.setClip(0, pageNumber * pageHeight, pageWidth, pageHeight);
 
-      ypos += cHeight;
-    } while (ypos < totalHeight);
+    /*
+     * draw sequence ids and annotation labels (if shown)
+     */
+    IdCanvas idCanvas = getIdPanel().getIdCanvas();
+    idCanvas.drawIdsWrapped((Graphics2D) g, av, 0, totalHeight);
 
-    pg.translate(idWidth, 0);
+    g.translate(idWidth, 0);
 
-    getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(pg, pwidth - idWidth,
+    getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(g, pageWidth - idWidth,
             totalHeight, 0);
 
-    if ((pi * pheight) < totalHeight)
+    if ((pageNumber * pageHeight) < totalHeight)
     {
       return Printable.PAGE_EXISTS;
-
     }
     else
     {
@@ -1366,7 +1251,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     if (av.hasHiddenColumns())
     {
       maxwidth = av.getAlignment().getHiddenColumns()
-              .findColumnPosition(maxwidth);
+              .absoluteToVisibleColumn(maxwidth);
     }
 
     int height = ((av.getAlignment().getHeight() + 1) * av.getCharHeight())
@@ -1584,7 +1469,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     if (av.hasHiddenColumns())
     {
       maxwidth = av.getAlignment().getHiddenColumns()
-              .findColumnPosition(maxwidth) - 1;
+              .absoluteToVisibleColumn(maxwidth) - 1;
     }
 
     int height = ((maxwidth / chunkWidth) + 1) * cHeight;
@@ -1682,7 +1567,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
   @Override
   public String getViewName()
   {
-    return av.viewName;
+    return av.getViewName();
   }
 
   /**