Merge branch 'develop' into feature/JAL-3364splitFrameImage
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 29 Jul 2019 10:49:20 +0000 (11:49 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 29 Jul 2019 10:49:20 +0000 (11:49 +0100)
1  2 
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/IdCanvas.java

   */
  package jalview.gui;
  
 +import static jalview.util.ImageMaker.TYPE.EPS;
 +import static jalview.util.ImageMaker.TYPE.PNG;
 +import static jalview.util.ImageMaker.TYPE.SVG;
 +
  import jalview.analysis.AnnotationSorter;
  import jalview.api.AlignViewportI;
  import jalview.api.AlignmentViewPanel;
@@@ -40,7 -36,6 +40,7 @@@ import jalview.math.AlignmentDimension
  import jalview.schemes.ResidueProperties;
  import jalview.structure.StructureSelectionManager;
  import jalview.util.Comparison;
 +import jalview.util.ImageMaker;
  import jalview.util.MessageManager;
  import jalview.viewmodel.ViewportListenerI;
  import jalview.viewmodel.ViewportRanges;
@@@ -876,18 -871,19 +876,18 @@@ public class AlignmentPanel extends GAl
    }
  
    /**
 -   * DOCUMENT ME!
 +   * Provides the implementation of Printable.print
     * 
     * @param pg
 -   *          DOCUMENT ME!
 +   *             DOCUMENT ME!
     * @param pf
 -   *          DOCUMENT ME!
 +   *             DOCUMENT ME!
     * @param pi
 -   *          DOCUMENT ME!
 +   *             DOCUMENT ME!
     * 
     * @return DOCUMENT ME!
     * 
     * @throws PrinterException
 -   *           DOCUMENT ME!
     */
    @Override
    public int print(Graphics pg, PageFormat pf, int pi)
  
      if (av.getWrapAlignment())
      {
 -      return printWrappedAlignment(pwidth, pheight, pi, pg);
 +      return printWrappedAlignment(pwidth, pheight, pi, pg, true);
      }
      else
      {
                alignmentDrawnHeight);
        getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
                alignmentGraphics, -1, startRes, endRes + 1);
 +
 +      /*
 +       * reset to left margin
 +       */
 +      alignmentGraphics.translate(-alignmentGraphicsOffset, 0);
      }
  
      return Printable.PAGE_EXISTS;
     * 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).
 +   * <p>
 +   * The method is to write the whole alignment, but set a clip region such that
 +   * only the specified page is written. This allows specified page(s) to be
 +   * printed from the print dialog. The whole image may be written simply by
 +   * making the page size match the image size. In this case, parameter
 +   * {@code clipToPage} should be set to {@code false}, so that more output (for
 +   * example the second panel of a split frame) can be written if wanted.
     * 
     * @param pageWidth
     * @param pageHeight
     * @param pageNumber
 -   *          (0, 1, ...)
 +   *                     (0, 1, ...)
     * @param g
 +   * @param clipToPage
     * 
     * @return
 -   * 
 -   * @throws PrinterException
     */
    public int printWrappedAlignment(int pageWidth, int pageHeight, int pageNumber,
 -          Graphics g) throws PrinterException
 +          Graphics g, boolean clipToPage)
    {
      int annotationHeight = 0;
      if (av.isShowAnnotation())
       */
      g.translate(0, -pageNumber * pageHeight);
  
 -    g.setClip(0, pageNumber * pageHeight, pageWidth, pageHeight);
 +    if (clipToPage)
 +    {
 +      g.setClip(0, pageNumber * pageHeight, pageWidth, pageHeight);
 +    }
  
      /*
       * draw sequence ids and annotation labels (if shown)
      idCanvas.drawIdsWrapped((Graphics2D) g, av, 0, totalHeight);
  
      g.translate(idWidth, 0);
 -
      getSeqPanel().seqCanvas.drawWrappedPanelForPrinting(g, pageWidth - idWidth,
              totalHeight, 0);
 +    g.translate(-idWidth, 0);
  
      if ((pageNumber * pageHeight) < totalHeight)
      {
      return idwidth.intValue() + 4;
    }
  
 -  void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file)
 +  /**
 +   * Generates an image of the alignment panel of the specified type. If
 +   * {@code type} is not null, the image is written to the file, otherwise the
 +   * user is prompted to specify the output file before writing to it.
 +   * 
 +   * @param type
 +   * @param file
 +   * @param forSplitFrame
 +   */
 +  void makeAlignmentImage(ImageMaker.TYPE type, File file,
 +          boolean forSplitFrame)
    {
 -    int boarderBottomOffset = 5;
 +    int borderBottomOffset = 5;
      long pSessionId = System.currentTimeMillis();
      headless = (System.getProperty("java.awt.headless") != null
              && System.getProperty("java.awt.headless").equals("true"));
      }
      try
      {
 -      AlignmentDimension aDimension = getAlignmentDimension();
 -      try
 +      /*
 +       * if exporting a split frame image, the graphics object has 
 +       * width: maximum of the top and bottom image widths
 +       * height: sum of the top and bottom image heights
 +       */
 +      AlignmentPanel comp = null;
 +      AlignmentDimension dim1 = getAlignmentDimension();
 +      AlignmentDimension dim2 = new AlignmentDimension(0, 0);
 +      if (forSplitFrame)
        {
 -        jalview.util.ImageMaker im;
 -        final String imageAction, imageTitle;
 -        if (type == jalview.util.ImageMaker.TYPE.PNG)
 -        {
 -          imageAction = "Create PNG image from alignment";
 -          imageTitle = null;
 -        }
 -        else if (type == jalview.util.ImageMaker.TYPE.EPS)
 -        {
 -          imageAction = "Create EPS file from alignment";
 -          imageTitle = alignFrame.getTitle();
 -        }
 -        else
 +        comp = ((AlignViewport) av.getCodingComplement())
 +                .getAlignPanel();
 +        dim2 = comp.getAlignmentDimension();
 +      }
 +      final int graphicsHeight = dim1.height + dim2.height
 +              + borderBottomOffset;
 +      final int graphicsWidth = Math.max(dim1.width, dim2.width);
 +
 +      final String dialogTitle = MessageManager
 +              .formatMessage("label.make_alignment_image", type.getName());
 +      String imageTitle = type == PNG ? null : alignFrame.getTitle();
 +
 +      ImageMaker im = new ImageMaker(this, type, dialogTitle,
 +              graphicsWidth, graphicsHeight, file,
 +              imageTitle, alignFrame, pSessionId, headless);
 +      Graphics graphics = im.getGraphics();
 +      if (graphics == null)
 +      {
 +        return;
 +      }
 +      graphics.setColor(Color.white);
 +      graphics.fillRect(0, 0, graphicsWidth, graphicsHeight);
 +      if (av.getWrapAlignment())
 +      {
 +        printWrappedAlignment(dim1.width, dim1.height + borderBottomOffset,
 +                0, graphics, false);
 +      }
 +      else
 +      {
 +        printUnwrapped(dim1.width, dim1.height, 0, graphics, graphics);
 +      }
 +
 +      if (forSplitFrame)
 +      {
 +        /*
 +         * append coding complement image
 +         */
 +        boolean test = true;
 +        if (test)
          {
 -          imageAction = "Create SVG file from alignment";
 -          imageTitle = alignFrame.getTitle();
 +          /*
 +           * debug location of next write to Graphics
 +           */
 +          graphics.setColor(Color.red);
 +          graphics.drawString("Hello world", 0, 0);
 +          graphics.setColor(Color.black);
          }
 -
 -        im = new jalview.util.ImageMaker(this, type, imageAction,
 -                aDimension.getWidth(),
 -                aDimension.getHeight() + boarderBottomOffset, file,
 -                imageTitle, alignFrame, pSessionId, headless);
 -        Graphics graphics = im.getGraphics();
 -        if (av.getWrapAlignment())
 +        if (av.getCodingComplement().getWrapAlignment())
          {
 -          if (graphics != null)
 -          {
 -            printWrappedAlignment(aDimension.getWidth(),
 -                    aDimension.getHeight() + boarderBottomOffset, 0,
 -                    graphics);
 -            im.writeImage();
 -          }
 +          comp.printWrappedAlignment(dim2.width,
 +                  dim2.height + borderBottomOffset, 0, graphics, false);
          }
          else
          {
 -          if (graphics != null)
 -          {
 -            printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
 -                    graphics, graphics);
 -            im.writeImage();
 -          }
 +          comp.printUnwrapped(dim2.width, dim2.height, 0, graphics,
 +                  graphics);
          }
 -
 -      } catch (OutOfMemoryError err)
 -      {
 -        // Be noisy here.
 -        System.out.println("########################\n" + "OUT OF MEMORY "
 -                + file + "\n" + "########################");
 -        new OOMWarning("Creating Image for " + file, err);
 -        // System.out.println("Create IMAGE: " + err);
 -      } catch (Exception ex)
 -      {
 -        ex.printStackTrace();
        }
 -    } finally
 -    {
  
 +      im.writeImage();
 +    } catch (OutOfMemoryError err)
 +    {
 +      // Be noisy here.
 +      System.out.println("########################\n" + "OUT OF MEMORY "
 +              + file + "\n" + "########################");
 +      new OOMWarning("Creating Image for " + file, err);
 +      // System.out.println("Create IMAGE: " + err);
 +    } catch (Exception ex)
 +    {
 +      ex.printStackTrace();
      }
    }
  
 +  /**
 +   * Computes and answers the width and height of the alignment in pixels,
 +   * including
 +   * <ul>
 +   * <li>sequence ids</li>
 +   * <li>scale above, left or right if shown</li>
 +   * <li>sequences</li>
 +   * <li>annotations, if shown</li>
 +   * </ul>
 +   * The alignment may be in wrapped or unwrapped mode.
 +   * <ul>
 +   * 
 +   * @return
 +   */
    public AlignmentDimension getAlignmentDimension()
    {
      int maxwidth = av.getAlignment().getVisibleWidth();
      {
        height += getAnnotationPanel().adjustPanelHeight() + 3;
      }
 -    return new AlignmentDimension(width, height);
  
 +    return new AlignmentDimension(width, height);
    }
  
    /**
 -   * DOCUMENT ME!
 +   * Creates and writes an EPS image of the alignment, to the given file if
 +   * specified, else after prompting for the output file
 +   * 
 +   * @param epsFile
 +   * @param forSplitFrame
     */
 -  public void makeEPS(File epsFile)
 +  public void makeEPS(File epsFile, boolean forSplitFrame)
    {
 -    makeAlignmentImage(jalview.util.ImageMaker.TYPE.EPS, epsFile);
 +    makeAlignmentImage(EPS, epsFile, forSplitFrame);
    }
  
    /**
 -   * DOCUMENT ME!
 +   * Creates and writes a PNG image of the alignment, to the given file if
 +   * specified, else after prompting for the output file
 +   * 
 +   * @param pngFile
 +   * @param forSplitFrame
     */
 -  public void makePNG(File pngFile)
 +  public void makePNG(File pngFile, boolean forSplitFrame)
    {
 -    makeAlignmentImage(jalview.util.ImageMaker.TYPE.PNG, pngFile);
 +    makeAlignmentImage(PNG, pngFile, forSplitFrame);
    }
  
 -  public void makeSVG(File svgFile)
 +  /**
 +   * Creates and writes an SVG image of the alignment, to the given file if
 +   * specified, else after prompting for the output file
 +   * 
 +   * @param svgFile
 +   * @param forSplitFrame
 +   */
 +  public void makeSVG(File svgFile, boolean forSplitFrame)
    {
 -    makeAlignmentImage(jalview.util.ImageMaker.TYPE.SVG, svgFile);
 +    makeAlignmentImage(SVG, svgFile, forSplitFrame);
    }
  
    public void makePNGImageMap(File imgMapFile, String imageName)
  
    }
  
+   /**
+    * Answers the height of the entire alignment in pixels, assuming it is in
+    * wrapped mode
+    * 
+    * @return
+    */
    int getWrappedHeight()
    {
      int seqPanelWidth = getSeqPanel().seqCanvas.getWidth();
@@@ -392,12 -392,12 +392,13 @@@ public class IdCanvas extends JPanel im
      AnnotationLabels labels = null;
      if (alignViewport.isShowAnnotation())
      {
 +      hgap += SeqCanvas.SEQS_ANNOTATION_GAP;
        if (ap == null)
        {
          ap = new AnnotationPanel(alignViewport);
        }
-       annotationHeight = ap.adjustPanelHeight();
+       annotationHeight = ap.adjustPanelHeight()
+               + SeqCanvas.SEQS_ANNOTATION_GAP;
        labels = new AnnotationLabels(alignViewport);
      }