/*******************************************************************************
* 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.geom.Line2D;
import java.awt.image.BufferedImage;
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.Hashtable;
import java.util.Locale;
import java.util.ResourceBundle;
import ch.elexis.data.Artikel;
import ch.elexis.data.Patient;
import ch.elexis.data.Rezept;
class Page implements Printable
{
//Fonts
private static Font fnt = new Font("Helvetica",Font.PLAIN,8); //$NON-NLS-1$
private static Font fntBold = new Font("Helvetica",Font.BOLD,8); //$NON-NLS-1$
private static Font fntItalic = new Font("Helvetica",Font.ITALIC,8); //$NON-NLS-1$
private static Font fntTitle = new Font("Helvetica",Font.BOLD,11); //$NON-NLS-1$
//Message-Constants
private String PHONE;
private String FAX;
private String EAN;
private String ZSR;
private String TITLE;
private String BORN;
private String REPETITION;
private static final String PROMO = "https://www.pharmedsolutions.ch"; //$NON-NLS-1$
//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 String presID;
private String QRCode;
private Patient pat;
//Barcodes
private BufferedImage imgQRCode;
private BufferedImage imgCode128;
//Indices for correctly rendering the page
private int firstProd = 0;
private int lastProd = 0;
private ResourceBundle messages;
public Page(Physician ph, Rezept rp, String presID,String QRCode, Integer firstProductIndex, Integer lastProductIndex){
this.ph = ph;
this.rp = rp;
this.pat = rp.getPatient();
this.presID = presID;
this.QRCode = QRCode;
this.firstProd = firstProductIndex;
this.lastProd = lastProductIndex;
this.messages = ResourceBundle.getBundle("ch.pharmed.phmprescriber.MessagesBundle", new Locale("de", "CH")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
this.PHONE = messages.getString("Page_4");
this.FAX = messages.getString("Page_5");
this.EAN = messages.getString("Page_6");
this.ZSR = messages.getString("Page_7");
this.TITLE = messages.getString("Page_8");
this.BORN = messages.getString("Page_9");
this.REPETITION = messages.getString("Page_10");
}
public int print(Graphics g, PageFormat pageFormat, int page) throws PrinterException
{
//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;
Line2D.Double line = new Line2D.Double();
//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);
//-- (1) Print the line on the left side
line.setLine(0, 0, 0, pageFormat.getHeight()+500);
g2d.draw(line);
//-- (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();
g.drawString(ph.getTitle() + " " + ph.getFirstname() + " " + ph.getLastname(),intMarginLeft,intMeasureY); //$NON-NLS-1$ //$NON-NLS-2$
//Set font to default
g.setFont(fnt);
//Measure the x-position (Page-Width - length of string)
metrics = g.getFontMetrics(fnt);
//Draw the date
g.drawString(rp.getDate(),intPageWidth - metrics.stringWidth(rp.getDate()),intMeasureY);
intMeasureY += metrics.getHeight();
//Draw strings of Address, Phone and insurance information
g.drawString(ph.getSpecialty1(),intMarginLeft,intMeasureY);
if (ph.getSpecialty2().length() > 0) {
intMeasureY +=intDefaultHeight;
g.drawString(ph.getSpecialty2(),intMarginLeft,intMeasureY);
}
intMeasureY +=intSpace;
g.drawString(ph.getStreet() + " " + ph.getPostbox(),intMarginLeft,intMeasureY); //$NON-NLS-1$
intMeasureY +=intDefaultHeight;
g.drawString(ph.getZip() + " " + ph.getCity(),intMarginLeft,intMeasureY); //$NON-NLS-1$
intMeasureY += intSpace;
//Measure the label strings to align the phone and fax numbers
int phoneWidth = metrics.stringWidth(PHONE);
if (metrics.stringWidth(PHONE) < metrics.stringWidth(FAX) && ph.getFax().length() > 0)
phoneWidth = metrics.stringWidth(FAX);
g.drawString(PHONE,intMarginLeft,intMeasureY);
g.drawString(ph.getPhone(),intMarginLeft+phoneWidth,intMeasureY);
if (ph.getFax().length() > 0 ) {
intMeasureY +=intDefaultHeight;
g.drawString(FAX,intMarginLeft,intMeasureY);
g.drawString(ph.getFax(),intMarginLeft+phoneWidth,intMeasureY);
}
intMeasureY += intSpace;
//Measure the label strings to align the ZSR and EAN identifiers
int EANWidth = metrics.stringWidth(ZSR);
if (metrics.stringWidth(ZSR) < metrics.stringWidth(EAN) && ph.getGlnid().length() > 0)
EANWidth = metrics.stringWidth(EAN);
g.drawString(ZSR,intMarginLeft,intMeasureY);
g.drawString(ph.getZsrid(),intMarginLeft+EANWidth,intMeasureY);
if(ph.getGlnid().length() > 0) {
intMeasureY +=intDefaultHeight;
g.drawString(EAN,intMarginLeft,intMeasureY);
g.drawString(ph.getGlnid(),intMarginLeft+EANWidth,intMeasureY);
}
intMeasureY += intSpaceBig;
//-- (3) Print the line
line.setLine(intMarginLeft, intMeasureY, pageFormat.getWidth(),intMeasureY);
g2d.draw(line);
intMeasureY += intSpaceBig + intSpace;
//-- (4) Title
g.setFont(fntTitle);
g.drawString(TITLE, intMarginLeft, intMeasureY);
intMeasureY +=intSpaceBig + intDefaultHeight;
//-- (5) Patient
g.setFont(fntBold);
g.drawString(pat.getName() + " " + pat.getVorname(), intMarginLeft, intMeasureY); //$NON-NLS-1$
metrics = g.getFontMetrics(fntBold);
int xPat = intMarginLeft + metrics.stringWidth(pat.getName() + " " + pat.getVorname()); //$NON-NLS-1$
g.setFont(fnt);
g.drawString(", " + BORN + pat.getGeburtsdatum(), xPat, intMeasureY); //$NON-NLS-1$
intMeasureY +=intSpaceBig + intSpace;
//-- (6) Products
LineBreakMeasurer lineBreakMeasurer;
int intstart, intend;
Hashtable hash = new Hashtable();
//Print all the items
for(int i = this.firstProd; i <= lastProd; i = i+1) {
ch.elexis.data.Prescription actualLine = rp.getLines().get(i);
Artikel article = actualLine.getArtikel();
AttributedString attributedString = new AttributedString(
"1x " + article.getLabel(), hash); //$NON-NLS-1$
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;
int X = intMarginLeft;
lineBreakMeasurer.setPosition(intstart);
//Create TextLayout accordingly and draw it
while (lineBreakMeasurer.getPosition() < intend) {
TextLayout textLayout = lineBreakMeasurer.nextLayout(width);
intMeasureY += textLayout.getAscent();
X = intMarginLeft;
textLayout.draw(g2d, X, intMeasureY);
intMeasureY += textLayout.getDescent() + textLayout.getLeading();
}
//Draw the label
String label = actualLine.getBemerkung();
if (actualLine.getDosis().length() > 0 ){
label = actualLine.getDosis() + ", " + label; //$NON-NLS-1$
}
//If there is no label specified, go to the next iterations
if (label.length() == 0) {
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();
X = intMarginLeft;
textLayout.draw(g2d, X, intMeasureY);
intMeasureY += textLayout.getDescent() + textLayout.getLeading();
}
intMeasureY += intSpaceBig*2;
}
//(7) Draw now the Footer:
//Create the barcodes
Barcode bc = new Barcode();
this.imgCode128 = bc.getCode128(presID);
this.imgQRCode = bc.getQRCode(QRCode);
//(a) Code 128 with decoded String
g.setFont(fntBold);
metrics = g.getFontMetrics(fntBold);
int xPrescId = intPageWidth-Code128Width + Integer.valueOf((int) Math.round((Code128Width-metrics.stringWidth(this.presID))/2));
g.drawString(this.presID, xPrescId, pageHeight);
g.drawImage(imgCode128, intPageWidth-Code128Width,pageHeight -Code128Height -intDefaultHeight ,Code128Width,Code128Height, null);
//(b) QR-Code
g.drawImage(imgQRCode, intMarginLeft,pageHeight - QRCodeBorder ,QRCodeBorder,QRCodeBorder, null);
//(c) Promotion-String
g.setColor(Color.gray);
metrics = g.getFontMetrics(fntItalic);
g.setFont(fntItalic);
g.drawString(PROMO, Integer.valueOf((int) Math.round((intMarginLeft+(QRCodeBorder -metrics.stringWidth(PROMO))/2))), pageHeight);
//set to default
g.setColor(Color.black);
g.setFont(fnt);
//(8) Return, that this page exists and thus will be rendered and printed
return (PAGE_EXISTS);
}
}