* 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, ...) * @param g * @param clipToPage * * @return */ public int printWrappedAlignment(int pageWidth, int pageHeight, int pageNumber, Graphics g, boolean clipToPage) { getSeqPanel().seqCanvas.calculateWrappedGeometry(getWidth(), getHeight()); int annotationHeight = 0; if (av.isShowAnnotation()) { annotationHeight = getAnnotationPanel().adjustPanelHeight(); } int hgap = av.getCharHeight(); if (av.getScaleAboveWrapped()) { hgap += av.getCharHeight(); } int cHeight = av.getAlignment().getHeight() * av.getCharHeight() + hgap + annotationHeight; int idWidth = getVisibleIdWidth(false); int maxwidth = av.getAlignment().getVisibleWidth(); int resWidth = getSeqPanel().seqCanvas .getWrappedCanvasWidth(pageWidth - idWidth); av.getRanges().setViewportStartAndWidth(0, resWidth); int totalHeight = cHeight * (maxwidth / resWidth + 1); g.setColor(Color.white); g.fillRect(0, 0, pageWidth, pageHeight); g.setFont(av.getFont()); g.setColor(Color.black); /* * 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 repeated processing in the * 'normal' case, when all pages are printed) */ g.translate(0, -pageNumber * pageHeight); if (clipToPage) { g.setClip(0, pageNumber * pageHeight, pageWidth, pageHeight); } /* * draw sequence ids and annotation labels (if shown) */ IdCanvas idCanvas = getIdPanel().getIdCanvas(); 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 Printable.PAGE_EXISTS; } else { return Printable.NO_SUCH_PAGE; } } /** * get current sequence ID panel width, or nominal value if panel were to be * displayed using default settings * * @return */ public int getVisibleIdWidth() { return getVisibleIdWidth(true); } /** * get current sequence ID panel width, or nominal value if panel were to be * displayed using default settings * * @param onscreen * indicate if the Id width for onscreen or offscreen display should * be returned * @return */ public int getVisibleIdWidth(boolean onscreen) { // see if rendering offscreen - check preferences and calc width accordingly if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false)) { return calculateIdWidth(-1).width + 4; } Integer idwidth = null; if (onscreen || (idwidth = Cache .getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null) { int w = getIdPanel().getWidth(); return (w > 0 ? w : calculateIdWidth().width + 4); } return idwidth.intValue() + 4; } /** * 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 borderBottomOffset = 5; long pSessionId = System.currentTimeMillis(); headless = (System.getProperty("java.awt.headless") != null && System.getProperty("java.awt.headless").equals("true")); if (alignFrame != null && !headless) { if (file != null) { alignFrame.setProgressBar(MessageManager .formatMessage("status.saving_file", new Object[] { type.getLabel() }), pSessionId); } } /* * cache preferences in case we need to fudge them for export of * split frame with 'protein scaled to codons' and 'auto id width' */ final String autoIdWidth = Cache.getProperty("FIGURE_AUTOIDWIDTH"); final Integer fixedIdWidth = Cache .getIntegerProperty("FIGURE_FIXEDIDWIDTH"); 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 * if 'protein scaled to codons' and 'auto id width', fudge * to a fixed width (and restore preferences afterwards) */ AlignmentPanel complement = null; AlignmentDimension dim1 = getAlignmentDimension(); AlignmentDimension dim2 = new AlignmentDimension(0, 0); if (forSplitFrame) { complement = ((AlignViewport) av.getCodingComplement()) .getAlignPanel(); dim2 = complement.getAlignmentDimension(); if (Boolean.valueOf(autoIdWidth) && av.isScaleProteinAsCdna()) { int w1 = this.getVisibleIdWidth(false); int w2 = complement.getVisibleIdWidth(false); Cache.setProperty("FIGURE_AUTOIDWIDTH", Boolean.FALSE.toString()); Cache.setProperty("FIGURE_FIXEDIDWIDTH", String.valueOf(Math.max(w1, w2))); } } 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 */ // to debug location of next write to Graphics: // graphics.drawString("Hello world", 0, 0); if (av.getCodingComplement().getWrapAlignment()) { complement.printWrappedAlignment(dim2.width, dim2.height + borderBottomOffset, 0, graphics, false); } else { complement.printUnwrapped(dim2.width, dim2.height, 0, graphics, graphics); } } 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(); } finally { /* * restore preference settings in case they were fudged */ if (autoIdWidth == null) { Cache.removeProperty("FIGURE_AUTOIDWIDTH"); } else { Cache.setProperty("FIGURE_AUTOIDWIDTH", autoIdWidth); } if (fixedIdWidth == null) { Cache.removeProperty("FIGURE_FIXEDIDWIDTH"); } else { Cache.setProperty("FIGURE_FIXEDIDWIDTH", String.valueOf(fixedIdWidth)); } } } /** * Computes and answers the width and height of the alignment in pixels, * including *