/******************************************************************************* * Copyright (c) 2014, Pharmed Solutions GmbH * All rights reserved. *******************************************************************************/ package ch.pharmed.phmprescriber; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import ch.elexis.data.Artikel; import ch.elexis.data.Patient; import ch.elexis.data.Rezept; class Pagecounter implements Printable { //Fonts private static Font fnt = new Font("Helvetica",Font.PLAIN,8); private static Font fntBold = new Font("Helvetica",Font.BOLD,8); private static Font fntTitle = new Font("Helvetica",Font.BOLD,11); //Layout-Constants private final double LMARGINRATIO = 0.3; private final double SPACERATIO = 1.5; int Code128Width = 185; int Code128Height = 36; int QRCodeBorder = 118; //Objects to print private Physician ph; private Rezept rp; private Patient pat; //Indices for correctly rendering the page List<Integer> indices = new ArrayList<Integer>(); public List<Integer> getIndices() { return indices; } public void setIndices(List<Integer> indices) { this.indices = indices; } public Pagecounter(Physician ph, Rezept rp, String presID,String QRCode){ this.ph = ph; this.rp = rp; this.pat = rp.getPatient(); this.indices.add(-1); } public int print(Graphics g, PageFormat pageFormat, int page) throws PrinterException { //======================================================================================================// //This procedure will simply measure, how many we have to print and which products belong to which page //Algorithm: (1) Measure the header and the footer to determine the area where to print the products // (2) check, how many pages we need based on this area then productsnames with remarks //Info: This procedure is necessary, as java.awt.print needs to know the page number before showing the // print dialog... //======================================================================================================// //Define the origin of the printArea double printAreaX = pageFormat.getImageableX(); double printAreaY = pageFormat.getImageableY(); //Measures the size of strings FontMetrics metrics = g.getFontMetrics(fnt); //Parameters for the layout //Dynamic variable to measure the y-position of each line int intMeasureY = 0; //Others int intMarginLeft = Integer.valueOf((int) Math.round(printAreaX*LMARGINRATIO)); int intSpace= Integer.valueOf((int) Math.round(metrics.getHeight()*SPACERATIO)); int intDefaultHeight = metrics.getHeight(); int intPageWidth = Integer.valueOf((int) Math.round(pageFormat.getImageableWidth())); int pageHeight = Integer.valueOf((int) Math.round(pageFormat.getImageableHeight())); metrics = g.getFontMetrics(fntTitle); int intSpaceBig = metrics.getHeight(); //Graphics object to draw lines etc. Graphics2D g2d; //Set colour to black g.setColor(Color.black); //Validate the number of pages //Create a graphic2D object a set the default parameters g2d = (Graphics2D) g; g2d.setColor(Color.black); //Translate the origin to be (0,0) //Note: Imageable includes already margins for Headers and Footers g2d.translate(printAreaX, printAreaY); //-- (2) Print the physicians attributes g.setFont(fntBold); //Measure String height to start drawing at the right place metrics = g.getFontMetrics(fntBold); intMeasureY += metrics.getHeight(); //Set font to default g.setFont(fnt); //Measure the x-position (Page-Width - length of string) metrics = g.getFontMetrics(fnt); intMeasureY += metrics.getHeight(); if (ph.getSpecialty2().length() > 0) { intMeasureY +=intDefaultHeight; } intMeasureY +=intSpace; intMeasureY +=intDefaultHeight; intMeasureY += intSpace; if (ph.getFax().length() > 0 ) { intMeasureY +=intDefaultHeight; } intMeasureY += intSpace; if(ph.getGlnid().length() > 0) { intMeasureY +=intDefaultHeight; } intMeasureY += intSpaceBig; //-- (3) Print the line intMeasureY += intSpaceBig + intSpace; //-- (4) Title g.setFont(fntTitle); intMeasureY +=intSpaceBig + intDefaultHeight; //-- (5) Patient g.setFont(fntBold); metrics = g.getFontMetrics(fntBold); g.setFont(fnt); intMeasureY +=intSpaceBig + intSpace; //==================Area Height============= //Upper limit int upperlimit = intMeasureY; //Define the lower limit of the area for the products int lowerLimit = pageHeight - QRCodeBorder - intSpaceBig*2; //Area: int areaHeight = lowerLimit - upperlimit; //Set measurer to 0 intMeasureY = 0; //-- (6) Products LineBreakMeasurer lineBreakMeasurer; int intstart, intend; Hashtable hash = new Hashtable(); //Print all the items for(int i = 0; i < rp.getLines().size(); i = i+1) { ch.elexis.data.Prescription actualLine = rp.getLines().get(i); Artikel article = actualLine.getArtikel(); AttributedString attributedString = new AttributedString( "1x " + article.getLabel(), hash); attributedString.addAttribute(TextAttribute.FONT, fntBold); g2d.setFont(fntBold); FontRenderContext frc = g2d.getFontRenderContext(); AttributedCharacterIterator attributedCharacterIterator = attributedString.getIterator(); intstart = attributedCharacterIterator.getBeginIndex(); intend = attributedCharacterIterator.getEndIndex(); lineBreakMeasurer = new LineBreakMeasurer(attributedCharacterIterator,frc); float width = (float) intPageWidth-intMarginLeft; lineBreakMeasurer.setPosition(intstart); //Create TextLayout accordingly and draw it while (lineBreakMeasurer.getPosition() < intend) { TextLayout textLayout = lineBreakMeasurer.nextLayout(width); intMeasureY += textLayout.getAscent(); intMeasureY += textLayout.getDescent() + textLayout.getLeading(); } //Draw the label String label = actualLine.getBemerkung(); if (actualLine.getDosis().length() > 0 ){ label = actualLine.getDosis() + ", " + label; } //If there is no label specified, go to the next iterations if (label.length() == 0) { if (areaHeight < intMeasureY){ this.indices.add(i-1); //Do this run again and set the measurer to 0 again i = i-1; intMeasureY = 0; } else {intMeasureY += intSpaceBig*2;} continue; } attributedString = new AttributedString(label, hash); attributedString.addAttribute(TextAttribute.FONT, fnt); g2d.setFont(fnt); frc = g2d.getFontRenderContext(); attributedCharacterIterator = attributedString.getIterator(); intstart = attributedCharacterIterator.getBeginIndex(); intend = attributedCharacterIterator.getEndIndex(); lineBreakMeasurer = new LineBreakMeasurer(attributedCharacterIterator,frc); lineBreakMeasurer.setPosition(intstart); //Create TextLayout accordingly and draw it while (lineBreakMeasurer.getPosition() < intend) { //Extra code to determine line breaks in the string --> go on new line, if there is one int next = lineBreakMeasurer.nextOffset(width); int limit = next; if (limit <= label.length()) { for (int k = lineBreakMeasurer.getPosition(); k < next; ++k) { char c = label.charAt(k); if (c == '\n') { limit = k + 1; break; } } } TextLayout textLayout = lineBreakMeasurer.nextLayout(width,limit, false); intMeasureY += textLayout.getAscent(); intMeasureY += textLayout.getDescent() + textLayout.getLeading(); } //If the last item will touch the limit, assign the (real) last item to the indices, reset the measurer and run the current loop again if (areaHeight < intMeasureY){ this.indices.add(i-1); //Do this run again and set the measurer to 0 again i = i-1; intMeasureY = 0; } else {intMeasureY += intSpaceBig*2;} } //Add the last item this.indices.add(rp.getLines().size()-1); //(8) Return no such page to terminate return (NO_SUCH_PAGE); } }