/*******************************************************************************
* Copyright (c) 2015, Daniel Ludin
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Daniel Ludin (ludin@hispeed.ch) - initial implementation
*******************************************************************************/
package ch.gpb.elexis.cst.view;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.elexis.befunde.Messwert;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.events.ElexisEvent;
import ch.elexis.core.data.events.ElexisEventListener;
import ch.elexis.core.ui.UiDesk;
import ch.elexis.core.ui.actions.GlobalEventDispatcher;
import ch.elexis.core.ui.actions.IActivationListener;
import ch.elexis.core.ui.events.ElexisUiEventListenerImpl;
import ch.elexis.core.ui.util.Log;
import ch.elexis.core.ui.util.SWTHelper;
import ch.elexis.data.LabItem;
import ch.elexis.data.Patient;
import ch.elexis.data.Prescription;
import ch.elexis.data.Query;
import ch.gpb.elexis.cst.Activator;
import ch.gpb.elexis.cst.data.CstGastroColo;
import ch.gpb.elexis.cst.data.CstGroup;
import ch.gpb.elexis.cst.data.CstProfile;
import ch.gpb.elexis.cst.data.CstProimmun;
import ch.gpb.elexis.cst.data.LabItemWrapper;
import ch.gpb.elexis.cst.data.ValuePairTimeline;
import ch.gpb.elexis.cst.data.ValueSingleTimeline;
import ch.gpb.elexis.cst.dialog.PdfOptionsDialog;
import ch.gpb.elexis.cst.preferences.CstPreference;
import ch.gpb.elexis.cst.preferences.Messages;
import ch.gpb.elexis.cst.service.CstService;
import ch.gpb.elexis.cst.util.ImageUtils;
import ch.gpb.elexis.cst.widget.GastroColoCanvas;
import ch.gpb.elexis.cst.widget.ValuePairTimelineCanvas;
import ch.gpb.elexis.cst.widget.ValueSingleTimelineCanvas;
import ch.rgw.tools.TimeTool;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.FontFactory;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;
/**
*
* @author daniel created: 11.01.2015
*
* this is the super class for the custom result views.
* child classes must implement the layout method (createPartControl)
*
* 595 / 842
* 794 / 1123
*/
// TODO: the output mechanism with SWT widgets may seem clumsy at first sight,
// but an output via a generated and buffered image has the same limitations, that is,
// it simply stops being displayed at around 30'000 px heigth.
// There seems to be some inner limitation that has to be investigated.
public abstract class CstResultPart extends ViewPart implements IActivationListener {
/**
* We make a String constant for the ID to reference it from the perspective
*/
//public static final String ID = "ch.gpb.elexis.cst.cstresultview";
protected Logger log = LoggerFactory.getLogger(CstResultPart.class.getName());
Patient patient;
CstProfile profile;
Composite baseComposite;
Font fontSmall;
Font fontBig;
Font fontMedium;
Color RED;
Color YELLOW;
Color WHITE;
Color BROWN;
Color ORANGE;
Color GRAY;
Color LIGHTGRAY;
String[] flds = null;
private Action actionScreenshot;
private Action actionPdf;
public static int OUTPUTWIDTH = 794;
public static int OUTPUTHEIGTH = 1123;
boolean a4Quer = false;
/**
* This is a default implemetation of an ElexisEventListener. It listens for SelectionEVents and UnselectionEvents
* on Instances of the Patient class.
*/
@Override
public void init(IViewSite site) throws PartInitException {
super.init(site);
Font initialFont = site.getShell().getFont();
FontData[] fontDataSmall = initialFont.getFontData();
for (int i = 0; i < fontDataSmall.length; i++) {
fontDataSmall[i].setHeight(7);
}
fontSmall = new Font(site.getShell().getDisplay(), fontDataSmall);
FontData[] fontDataBig = initialFont.getFontData();
for (int i = 0; i < fontDataBig.length; i++) {
fontDataBig[i].setHeight(12);
}
fontBig = new Font(site.getShell().getDisplay(), fontDataBig);
FontData[] fontDataMedium = initialFont.getFontData();
for (int i = 0; i < fontDataMedium.length; i++) {
fontDataMedium[i].setHeight(10);
}
fontMedium = new Font(site.getShell().getDisplay(), fontDataMedium);
RED = UiDesk.getColorFromRGB("FF2222");
YELLOW = UiDesk.getColorFromRGB("FFEF46");
WHITE = UiDesk.getColorFromRGB("FFFFFF");
BROWN = UiDesk.getColorFromRGB("CC9900");
ORANGE = UiDesk.getColorFromRGB("FFCC66");
GRAY = UiDesk.getColorFromRGB("888888");
LIGHTGRAY = UiDesk.getColorFromRGB("DDDDDD");
;
}
/**
* On disposal,the IActivationListener MUST be unregistered. Also, our RestrictedAction must be unregistered from
* the AutoAdapt queue to prevent memory leaks.
*/
@Override
public void dispose() {
GlobalEventDispatcher.removeActivationListener(this, this);
fontSmall.dispose();
fontBig.dispose();
fontMedium.dispose();
/*
RED.dispose();
WHITE.dispose();
YELLOW.dispose();
BROWN.dispose();
ORANGE.dispose();
*/
super.dispose();
}
// TODO: do we need this listener yet?
private ElexisEventListener eeli_pat = new ElexisUiEventListenerImpl(Patient.class) {
public void runInUi(final ElexisEvent ev) {
if (ev.getType() == ElexisEvent.EVENT_SELECTED) {
if ((patient == null) || (!patient.getId().equals(((Patient) ev.getObject()).getId()))) {
patient = (Patient) ev.getObject();
if (patient != null) {
// CstProfile.get
// layoutDisplay();
} else {
}
}
} else if (ev.getType() == ElexisEvent.EVENT_DESELECTED) {
}
}
};
/**
* As the Elexis User changes, he or she has propably different righs to see and modify our data, than the previous
* user. So we catch the USER_CHANGED Event and react accordingly.
*/
/**
* This is the right place to create all UI elements. The parent composite already has a GridLayout.
*/
@Override
public void createPartControl(Composite parent) {
// TODO: Actually, ScrolledComposite requires a FillLayout to work properly
// but now, this needs some work because the width isn't correct anymore in PDF output.
//GridLayout parentLayout = new GridLayout(1, false);
FillLayout parentLayout = new FillLayout(SWT.VERTICAL);
parent.setLayout(parentLayout);
parent.setBackground(WHITE);
GridLayout baseLayout = new GridLayout(1, false);
baseLayout.numColumns = 1;
final ScrolledComposite sc1 = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
baseComposite = new Composite(sc1, SWT.NONE);
baseComposite.setLayout(baseLayout);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.grabExcessVerticalSpace = true;
baseComposite.setLayoutData(gd);
baseComposite.setBackground(RED);
//OUTPUTWIDTH = OUTPUTHEIGTH;
sc1.setContent(baseComposite);
sc1.setMinSize(OUTPUTWIDTH, 800);
sc1.setSize(OUTPUTWIDTH, 800);
sc1.setExpandHorizontal(true);
sc1.addListener(SWT.MouseWheel, new Listener() {
public void handleEvent(Event event) {
int wheelCount = event.count;
wheelCount = (int) Math.ceil(wheelCount / 3.0f);
while (wheelCount < 0) {
sc1.getVerticalBar().setIncrement(50);
wheelCount++;
}
while (wheelCount > 0) {
sc1.getVerticalBar().setIncrement(-50);
wheelCount--;
}
}
});
// TODO: no idea what this is doing, but it works - find out!
// probably the sc is not getting the focus but the parent without this
sc1.addListener(SWT.Activate, new Listener() {
public void handleEvent(Event e) {
sc1.setFocus();
sc1.getVerticalBar().setIncrement(40);
}
});
Point pBaseComp = baseComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
baseComposite.setSize(pBaseComp);
makeActions(baseComposite);
contributeToActionBars();
GlobalEventDispatcher.addActivationListener(this, this);
}
@Override
public void setFocus() {
// Don't mind
}
/**
* From IActivationListener: the view was activated or inactivated
*
* @param mode
*/
public void activation(boolean mode) {
// don't mind
}
/**
* inheriting class must implement this method
* @param aProfile
*/
public abstract void layoutDisplay(CstProfile aProfile);
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
}
private void fillLocalPullDown(IMenuManager manager) {
manager.add(actionScreenshot);
manager.add(actionPdf);
manager.add(new Separator());
}
protected String getHeader(Patient patient) {
String title = Messages.Cst_Text_Interpretation_Mitochondrienlabor + " (" + profile.getName() + ") "
+ Messages.Cst_Text_fuer + " " + patient.getName() + " " + patient.getVorname() + " "
+ patient.getGeburtsdatum();
return title;
}
protected String getSubTitle(Patient patient, CstProfile aProfile) {
String title = Messages.CstProfileEditor_Datum + ": "
+ CstService.getReadableDateAndTime() + " ("
+ Messages.Cst_Text_Auswertungstyp_effektiv + " "
+ Messages.Cst_Text_startdatum + " "
+ CstService.getGermanFromCompact(aProfile.getValidFrom()) + " "
+ Messages.CstProfileEditor_Crawlback + " " + aProfile.getCrawlBack() + ")";
return title;
}
protected void addLine(Composite comp, int indent) {
//baseComposite.pack();
comp.pack();
Label labelLine = new Label(comp, SWT.NONE);
//Image imgLine = UiDesk.getImage(Activator.IMG_LINE_NAME);
//labelLine.setImage(imgLine);
GridData gdLine = new GridData(SWT.None);
gdLine.verticalIndent = indent;
labelLine.setLayoutData(gdLine);
comp.pack();
}
/**
* Check the length of the composite and add a Label with a vertical indent
* that matches the remaining heigth.
* @param comp
*/
protected void checkPageBreak(Composite comp) {
//baseComposite.pack();
comp.pack();
int currentHeigth = comp.getSize().y;
int printHeigth = profile.getAusgabeRichtung() ? 794 : 1123;
int pageCnt = currentHeigth / printHeigth;
int rmn = ((pageCnt + 1) * printHeigth) - currentHeigth;
if (rmn < 250) {
addLine(comp, rmn);
}
}
protected void addNoValuesLabel(Composite composite) {
StringBuffer lblText = new StringBuffer(
Messages.CstResultEffektiv_hinweis_keine_werte);
Label lblNoValues = new Label(composite, SWT.NONE);
GridData gdNoValues = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
gdNoValues.grabExcessHorizontalSpace = true;
gdNoValues.horizontalAlignment = SWT.FILL;
if (profile.getAusgabeRichtung()) {
gdNoValues.widthHint = 858;
} else {
gdNoValues.widthHint = 530;
}
lblNoValues.setLayoutData(gdNoValues);
lblNoValues.setText(lblText.toString());
lblNoValues.setForeground(RED);
lblNoValues.setBackground(WHITE);
}
/**
* The findings display is always the same for all display modes,
* call this method to add them to your custom display class
* @param baseComposite
*/
protected void addBefunde(Composite baseComposite) {
baseComposite.pack();
checkPageBreak(baseComposite);
//
// Anzeige-Element Darmfunktion / Pro Immun
//
Composite compoDarmfunktion = new Composite(baseComposite, SWT.BORDER | SWT.FILL);
compoDarmfunktion.setBackground(WHITE);
compoDarmfunktion.setSize(780, 400);
GridLayout dlDarmfunktion = new GridLayout(2, false);
compoDarmfunktion.setLayout(dlDarmfunktion);
GridData gdDarmfunktion = new GridData();
gdDarmfunktion.verticalAlignment = GridData.FILL;
gdDarmfunktion.grabExcessHorizontalSpace = false;
gdDarmfunktion.widthHint = 780;
compoDarmfunktion.setLayoutData(gdDarmfunktion);
CstProimmun cstProimmun = CstProimmun.getByProfileId(profile.getId());
if (cstProimmun != null) {
String sLabeltxt = Messages.Cst_Text_Proimmun + "\r\n" + Messages.Cst_Text_IggAntikoerper + "\r\n"
+ "\r\n" + cstProimmun.getTested() + "\r\n" + "\r\n" + " von "
+ cstProimmun.getToBeTested() + " " + Messages.Cst_Text_getesteten
+ "\r\n" + Messages.Cst_Text_Lebensmittel
+ "\r\n\r\n" + CstService.getGermanFromCompact(cstProimmun.getDatum());
Label lblDarmfunktion = new Label(compoDarmfunktion, SWT.NONE);
lblDarmfunktion.setLayoutData(new GridData(GridData.FILL_VERTICAL));
lblDarmfunktion.setText(sLabeltxt);
lblDarmfunktion.setFont(fontSmall);
Composite compoRightHalf = new Composite(compoDarmfunktion, SWT.FILL);
compoRightHalf.setLayout(new GridLayout(2, false));
Label lblReaktion4 = new Label(compoRightHalf, SWT.NONE);
lblReaktion4.setForeground(BROWN);
lblReaktion4.setText(Messages.CstProfileEditor_Reaktionsstaerke4);
lblReaktion4.setLayoutData(new GridData(SWT.NONE));
lblReaktion4.setFont(fontSmall);
Text txtReaktion4 = new Text(compoRightHalf, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
GridData gdReaktion4 = new GridData(SWT.FILL, SWT.CENTER, true, false);
gdReaktion4.widthHint = 540;
gdReaktion4.heightHint = 55;
txtReaktion4.setLayoutData(gdReaktion4);
txtReaktion4.setText(cstProimmun.getText4());
txtReaktion4.setFont(fontSmall);
txtReaktion4.setEditable(false);
txtReaktion4.setBackground(WHITE);
Label lblReaktion3 = new Label(compoRightHalf, SWT.NONE);
lblReaktion3.setText(Messages.CstProfileEditor_Reaktionsstaerke3);
lblReaktion3.setForeground(RED);
lblReaktion3.setLayoutData(new GridData(SWT.NONE));
lblReaktion3.setFont(fontSmall);
Text txtReaktion3 = new Text(compoRightHalf, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
GridData gdReaktion3 = new GridData(SWT.FILL, SWT.CENTER, true, false);
gdReaktion3.widthHint = 540;
gdReaktion3.heightHint = 55;
txtReaktion3.setLayoutData(gdReaktion3);
txtReaktion3.setText(cstProimmun.getText3());
txtReaktion3.setFont(fontSmall);
txtReaktion3.setEditable(false);
txtReaktion3.setBackground(WHITE);
Label lblReaktion2 = new Label(compoRightHalf, SWT.NONE);
lblReaktion2.setText(Messages.CstProfileEditor_Reaktionsstaerke2);
lblReaktion2.setForeground(ORANGE);
lblReaktion2.setLayoutData(new GridData(SWT.NONE));
lblReaktion2.setFont(fontSmall);
Text txtReaktion2 = new Text(compoRightHalf, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
GridData gdReaktion2 = new GridData(SWT.FILL, SWT.CENTER, true, false);
gdReaktion2.heightHint = 55;
gdReaktion2.widthHint = 540;
txtReaktion2.setLayoutData(gdReaktion2);
txtReaktion2.setText(cstProimmun.getText2());
txtReaktion2.setFont(fontSmall);
txtReaktion2.setEditable(false);
txtReaktion2.setBackground(WHITE);
Label lblReaktion1 = new Label(compoRightHalf, SWT.NONE);
lblReaktion1.setText(Messages.CstProfileEditor_Reaktionsstaerke1);
lblReaktion1.setForeground(YELLOW);
lblReaktion1.setLayoutData(new GridData(SWT.NONE));
lblReaktion1.setFont(fontSmall);
Text txtReaktion1 = new Text(compoRightHalf, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
GridData gdReaktion1 = new GridData(SWT.FILL, SWT.CENTER, true, false);
gdReaktion1.widthHint = 540;
gdReaktion1.heightHint = 55;
txtReaktion1.setLayoutData(gdReaktion1);
txtReaktion1.setText(cstProimmun.getText1());
txtReaktion1.setFont(fontSmall);
txtReaktion1.setEditable(false);
txtReaktion1.setBackground(WHITE);
cstProimmun.getDatum();
}
baseComposite.pack();
checkPageBreak(baseComposite);
//
// Anzeige-Element Fixmedikation
//
if (patient.getFixmedikation().length > 0) {
Composite compoFixmedi = new Composite(baseComposite, SWT.BORDER | SWT.FILL);
//compoFixmedi.setSize(980, SWT.FILL);
compoFixmedi.setBackground(WHITE);
compoFixmedi.setLayout(new GridLayout(1, false));
GridData gdFixmedi = new GridData();
gdFixmedi.grabExcessHorizontalSpace = false;
gdFixmedi.horizontalAlignment = SWT.BEGINNING;
gdFixmedi.widthHint = 780;
compoFixmedi.setLayoutData(gdFixmedi);
Label lFixmediTitel = new Label(compoFixmedi, SWT.FILL);
GridData gdFixmediTitel = new GridData();
lFixmediTitel.setLayoutData(gdFixmediTitel);
lFixmediTitel.setText(profile.getTherapievorschlag());
lFixmediTitel.setSize(200, 40);
lFixmediTitel.setText(Messages.Cst_Text_Fixmedikation);
lFixmediTitel.setFont(fontBig);
lFixmediTitel.setBackground(WHITE);
Label lblFixmedi = new Label(compoFixmedi, SWT.FILL);
GridData gdFixText = new GridData(GridData.FILL);
gdFixText.grabExcessHorizontalSpace = true;
lblFixmedi.setLayoutData(gdFixText);
//log.info("Medikation: " + patient.getFixmedikation());
Prescription[] prescriptions = patient.getFixmedikation();
StringBuffer sb = new StringBuffer();
for (Prescription prescription : prescriptions) {
log.info("Prescription: " + prescription.getLabel() + "/" + prescription.getDosis());
sb.append(prescription.getLabel());
sb.append("\r\n");
}
lblFixmedi.setText(sb.toString());
lblFixmedi.setFont(fontSmall);
lblFixmedi.setBackground(WHITE);
}
baseComposite.pack();
checkPageBreak(baseComposite);
//
// Anzeige-Element Befunde
//
Map<Object, Object> mAuswahl = profile.getMap(CstProfile.KEY_AUSWAHLBEFUNDE);
List<String> befundFelder = CstService.getBefundArtenFields();
for (String befundFeld : befundFelder) {
if (CstService.isBefundSelected(mAuswahl, befundFeld)) {
Composite compoBefunde = new Composite(baseComposite, SWT.BORDER | SWT.FILL);
//compoBefunde.setSize(980, SWT.FILL);
compoBefunde.setBackground(WHITE);
//compoBefunde.setLayout(new GridLayout(2, false));
compoBefunde.setLayout(new GridLayout(1, false));
GridData gdBefunde = new GridData();
gdBefunde.horizontalAlignment = GridData.BEGINNING;
gdBefunde.grabExcessHorizontalSpace = false;
gdBefunde.widthHint = 780;
/*
if (profile.getAusgabeRichtung()) {
gdBefunde.widthHint = 1120;
}*/
compoBefunde.setLayoutData(gdBefunde);
// when the befund is selected for display, search for a separator
String befundParameter = CstService.getBefundArtOfField(profile, befundFeld);
String separator = CstService.getBefundArtSeparator(mAuswahl, befundFeld);
if (separator != null) {
// Get Values for ValuePair
List<ValuePairTimeline> values = getValuesForValuePairTimeline(patient, befundParameter,
befundFeld, separator);
Composite compoValuePair = new Composite(compoBefunde, SWT.FILL);
GridLayout gridLayoutBase = new GridLayout();
gridLayoutBase.numColumns = 1;
compoValuePair.setLayout(gridLayoutBase);
compoValuePair.setSize(490, 300);
GridData gdBlutdruck = new GridData();
gdBlutdruck.horizontalAlignment = SWT.CENTER;
compoValuePair.setLayoutData(gdBlutdruck);
String[] splits = befundFeld.split(Messwert.SETUP_CHECKSEPARATOR);
ValuePairTimelineCanvas bdCanvas = new ValuePairTimelineCanvas(compoValuePair, SWT.FILL,
befundParameter + " (" + splits[0] + ")", splits[0]);
bdCanvas.setLayoutData(new GridData(GridData.BEGINNING));
bdCanvas.setFindings(values);
} else {
// Get Values for SingleValue
List<ValueSingleTimeline> values = getValuesForSingleValueTimeline(patient,
befundParameter, befundFeld);
Composite compoValueSingle = new Composite(compoBefunde, SWT.FILL);
GridLayout gridLayoutBase = new GridLayout();
gridLayoutBase.numColumns = 1;
compoValueSingle.setLayout(gridLayoutBase);
compoValueSingle.setSize(490, 300);
GridData gdBlutdruck = new GridData();
gdBlutdruck.horizontalAlignment = SWT.CENTER;
compoValueSingle.setLayoutData(gdBlutdruck);
String[] splits = befundFeld.split(Messwert.SETUP_CHECKSEPARATOR);
ValueSingleTimelineCanvas bdGewicht = new ValueSingleTimelineCanvas(compoValueSingle,
SWT.FILL, befundParameter + " (" + splits[0] + ")", splits[0]);
bdGewicht.setLayoutData(new GridData(GridData.BEGINNING));
bdGewicht.setFindings(values);
}
baseComposite.pack();
checkPageBreak(baseComposite);
}
}
//
// Anzeige-Element Darmuntersuchungen / GastroDuodenoskopie - Coloskopie
//
CstGastroColo cstGastroColo = CstGastroColo.getByProfileId(profile.getId());
Composite compoDarm = new Composite(baseComposite, SWT.BORDER | SWT.FILL);
compoDarm.setBackground(WHITE);
compoDarm.setLayout(new GridLayout());
GridData gdDarm = new GridData();
gdDarm.horizontalAlignment = SWT.BEGINNING;
gdDarm.grabExcessHorizontalSpace = false;
gdDarm.widthHint = 780;
compoDarm.setLayoutData(gdDarm);
Label lDarm = new Label(compoDarm, SWT.FILL);
GridData gdDarm2 = new GridData();
lDarm.setLayoutData(gdDarm2);
lDarm.setSize(200, 40);
lDarm.setText(Messages.Cst_Text_Darmuntersuchungen);
lDarm.setFont(fontBig);
lDarm.setBackground(WHITE);
GastroColoCanvas gcCanvas = new GastroColoCanvas(compoDarm, SWT.NONE, cstGastroColo);
gcCanvas.setLayoutData(new GridData(SWT.FILL));
checkPageBreak(baseComposite);
//
// Anzeige-Element Therapievorschlag
//
Composite compoTherapie = new Composite(baseComposite, SWT.BORDER | SWT.FILL);
//compoTherapie.setSize(980, SWT.FILL);
compoTherapie.setBackground(WHITE);
compoTherapie.setLayout(new GridLayout());
GridData gdTherapie = new GridData();
gdTherapie.horizontalAlignment = GridData.BEGINNING;
gdTherapie.grabExcessHorizontalSpace = false;
gdTherapie.widthHint = 780;
compoTherapie.setLayoutData(gdTherapie);
Label lTherapie = new Label(compoTherapie, SWT.FILL);
GridData gdTherapie1 = new GridData();
lTherapie.setLayoutData(gdTherapie1);
lTherapie.setSize(200, 40);
lTherapie.setText(Messages.Cst_Text_Therapievorschlag);
lTherapie.setFont(fontBig);
lTherapie.setBackground(WHITE);
Text txtTherapie = new Text(compoTherapie, SWT.READ_ONLY | SWT.WRAP);
txtTherapie.setFont(fontSmall);
GridData gdTherapie2 = new GridData(GridData.FILL_VERTICAL);
gdTherapie2.verticalAlignment = SWT.TOP;
gdTherapie2.grabExcessVerticalSpace = true;
//gdTherapie2.widthHint = 980;
txtTherapie.setLayoutData(gdTherapie2);
txtTherapie.setBackground(WHITE);
txtTherapie.setText(profile.getTherapievorschlag());
checkPageBreak(baseComposite);
//
// Anzeige-Element Diagnose
//
Composite compoDiagnose = new Composite(baseComposite, SWT.BORDER | SWT.FILL);
// compoTherapie.setSize(980, SWT.FILL);
compoDiagnose.setBackground(WHITE);
compoDiagnose.setLayout(new GridLayout());
GridData gdDiagnose = new GridData();
gdDiagnose.horizontalAlignment = GridData.BEGINNING;
gdDiagnose.grabExcessHorizontalSpace = false;
gdDiagnose.widthHint = 780;
compoDiagnose.setLayoutData(gdDiagnose);
Label lDiagnose = new Label(compoDiagnose, SWT.FILL);
GridData gdDiagnose1 = new GridData();
lDiagnose.setLayoutData(gdDiagnose1);
lDiagnose.setText(profile.getTherapievorschlag());
lDiagnose.setSize(200, 40);
lDiagnose.setText(Messages.CstProfileEditor_Diagnose);
lDiagnose.setFont(fontBig);
lDiagnose.setBackground(WHITE);
Text txtDiagnose = new Text(compoDiagnose, SWT.READ_ONLY | SWT.WRAP);
txtDiagnose.setFont(fontSmall);
GridData gdDiagnose2 = new GridData(GridData.FILL_VERTICAL);
gdDiagnose2.verticalAlignment = SWT.TOP;
gdDiagnose2.grabExcessVerticalSpace = true;
//gdDiagnose2.widthHint = 980;
txtDiagnose.setLayoutData(gdDiagnose2);
txtDiagnose.setBackground(WHITE);
txtDiagnose.setText(profile.getDiagnose());
// Setting the final size of the base composite
//baseComposite.setSize(OUTPUTWIDTH, newHeigth + 400);
checkPageBreak(baseComposite);
}
private void makeActions(final Control viewer) {
actionScreenshot = new Action() {
public void run() {
if (profile == null) {
SWTHelper.alert("No profile", "Ohne Profil kann kein Resultat erzeugt werden");
return;
}
GC gc = null;
Image image = null;
try {
String latestPath = CoreHub.userCfg.get(CstPreference.CST_IDENTIFIER_LATESTPATH, null);
if (latestPath == null) {
latestPath = System.getProperty("user.home");
}
FileDialog fd = new FileDialog(baseComposite.getShell(), SWT.SAVE);
fd.setText("Save");
fd.setFilterPath(latestPath);
String[] filterExt = { "*.png", "*.*" };
fd.setFilterExtensions(filterExt);
fd.setFileName(CstService.generateFilename(patient));
String selected = fd.open();
if (selected == null) {
return;
}
File selFile = new File(selected);
CoreHub.userCfg.set(CstPreference.CST_IDENTIFIER_LATESTPATH, selFile.getParentFile()
.getAbsolutePath());
//if (profile.getAnzeigeTyp().toLowerCase().equals("effektiv")) {
if (profile.getAnzeigeTyp().toLowerCase().equals(CstProfile.ANZEIGETYP_EFFEKTIV)) {
if (profile.getAusgabeRichtung()) {
image = new Image(viewer.getDisplay(), 1123, viewer.getBounds().height);
} else {
image = new Image(viewer.getDisplay(), 794, viewer.getBounds().height);
}
} else {
image = new Image(viewer.getDisplay(), 794, viewer.getBounds().height);
}
ImageLoader loader = new ImageLoader();
gc = new GC(image);
viewer.print(gc);
gc.dispose();
loader.data = new ImageData[] { image.getImageData() };
loader.save(selected, SWT.IMAGE_PNG);
} catch (Exception e) {
log.error("Error saving png: " + e.toString());
showMessage("Error while saving PNG", e.getMessage());
} finally {
if (image != null) {
image.dispose();
}
if (gc != null) {
gc.dispose();
}
}
}
};
actionScreenshot.setText(Messages.Cst_Text_Save_as_png);
actionScreenshot.setToolTipText(Messages.Cst_Text_Save_as_png);
actionScreenshot.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
.getImageDescriptor(ISharedImages.IMG_OBJ_ELEMENT));
actionScreenshot.setImageDescriptor(Activator.getImageDescriptor(Activator.IMG_PNG_PATH));
// TODO: die pdf ausgabe ist eine ziemliche Baustelle - �berarbeiten
actionPdf = new Action() {
public void run() {
//////////////////////////
if (profile == null) {
SWTHelper.alert("No profile", "Ohne Profil kann kein Resultat erzeugt werden");
return;
}
GC gc = null;
Image image = null;
try {
String latestPath = CoreHub.userCfg.get(CstPreference.CST_IDENTIFIER_LATESTPATH, null);
if (latestPath == null) {
latestPath = System.getProperty("user.home");
}
FileDialog fd = new FileDialog(baseComposite.getShell(), SWT.SAVE);
fd.setText("Save");
fd.setFilterPath(latestPath);
String[] filterExt = { "*.pdf", "*.*" };
fd.setFilterExtensions(filterExt);
fd.setFileName(CstService.generateFilename(patient));
String selected = fd.open();
if (selected == null) {
return;
}
File selFile = new File(selected);
CoreHub.userCfg.set(CstPreference.CST_IDENTIFIER_LATESTPATH, selFile.getParentFile()
.getAbsolutePath());
int printHeigth = 1123;
int printWidth = 794;
if (profile.getAusgabeRichtung()) {
printHeigth = 794;
printWidth = 1123;
}
// get the image from the viewport
image = new Image(viewer.getDisplay(), printWidth, viewer.getBounds().height);
ImageLoader loader = new ImageLoader();
gc = new GC(image);
viewer.print(gc);
gc.dispose();
// prepare title data
//Date date = new Date();
//SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm");
Patient patient = Patient.load(profile.getKontaktId());
//String sTitle = "Gemeinschaftspraxis Brunnmatt Dr. Beat K�nzi ";
String sTitle;
sTitle = profile.getOutputHeader() == null ? "No header configured!" :
profile.getOutputHeader();
if (sTitle == null || sTitle.length() == 0) {
sTitle = "No header configured!";
}
sTitle = sTitle + " Datum: " + CstService.getReadableDateAndTime();
// get option (paging to A4/ in one piece)
int pdfOutputOption = 0;
boolean onePage = true;
PdfOptionsDialog dialog = new PdfOptionsDialog(baseComposite.getShell());
dialog.create();
if (dialog.open() == Window.OK) {
pdfOutputOption = dialog.getPdfOutputOption();
if (pdfOutputOption == PdfOptionsDialog.OPTION_ONE_PAGE) {
onePage = true;
} else {
onePage = false;
}
}
float docHeight = viewer.getBounds().height;
docHeight = docHeight / 7.5f;
float fontSize = 12f;
if (docHeight < 360f) {
docHeight = 360f;
}
BufferedImage bimage = ImageUtils.convertToAWT(image.getImageData());
// create an Itextt Image from AWT BufferedImage
com.lowagie.text.Image itextImage = null;
java.awt.Image awtImage = null;
try {
awtImage = Toolkit.getDefaultToolkit().createImage(bimage.getSource());
itextImage = com.lowagie.text.Image.getInstance(awtImage, null);
} catch (Exception e) {
log.error("Error on image loading: " + e.toString());
e.printStackTrace();
}
// only for debugging
//loader.data = new ImageData[] { image.getImageData() };
//loader.save("C:\\Users\\daniel\\tmp\\debug.png", SWT.IMAGE_PNG);
Rectangle pagesize = new Rectangle(595f, itextImage.getHeight() * 0.75f);
// is it a4 quer?
if (profile.getAusgabeRichtung()) {
pagesize = new Rectangle(842f, itextImage.getHeight() * 0.75f);
}
//System.out.println("pagesize: " + pagesize.toString());
Document document;
if (onePage) {
document = new Document(pagesize);
} else {
document = new Document(PageSize.A4);
if (profile.getAusgabeRichtung()) {
document = new Document(PageSize.A4.rotate());
}
}
document.addCreationDate();
try {
// creation of the different writers
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(selected));
// various fonts
BaseFont bf_helv = BaseFont.createFont(BaseFont.HELVETICA, "Cp1252", true);
BaseFont bf_times = BaseFont.createFont(BaseFont.TIMES_ROMAN, "Cp1252", true);
BaseFont bf_courier = BaseFont.createFont(BaseFont.COURIER, "Cp1252", true);
com.lowagie.text.Font fontHelv12 = new com.lowagie.text.Font(bf_helv, fontSize);
com.lowagie.text.Font fontTimes = new com.lowagie.text.Font(bf_times, fontSize);
fontTimes.setSize(fontSize);
fontTimes.setStyle(com.lowagie.text.Font.ITALIC);
Chunk chunkHeader = new Chunk(sTitle, FontFactory.getFont(FontFactory.HELVETICA, fontSize,
com.lowagie.text.Font.NORMAL, new java.awt.Color(255, 0, 0)));
com.lowagie.text.Phrase phraseHeader = new com.lowagie.text.Phrase(chunkHeader);
// headers and footers must be added before the document
// is opened
Chunk chunkFooter = new Chunk("Seite: ", FontFactory.getFont(FontFactory.HELVETICA, fontSize,
com.lowagie.text.Font.BOLD, new java.awt.Color(0, 0, 0)));
Phrase phraseFooter = new Phrase(chunkFooter);
phraseFooter.setFont(fontHelv12);
HeaderFooter footer = new HeaderFooter(phraseFooter, true);
footer.setBorder(Rectangle.NO_BORDER);
footer.setAlignment(Element.ALIGN_CENTER);
document.setFooter(footer);
Phrase headerPhrase = new Phrase(sTitle);
headerPhrase.setFont(fontTimes);
HeaderFooter header = new HeaderFooter(phraseHeader, false);
header.setBorder(Rectangle.BOTTOM);
header.setBorderWidth(0.5f);
header.setAlignment(Element.ALIGN_LEFT);
document.setHeader(header);
document.open();
//System.out.println("itext image w: " + itextImage.getWidth() + " h:" + itextImage.getHeight());
if (onePage) {
int scale = 66;
itextImage.scalePercent(scale);
document.add(itextImage);
} else {
BufferedImage[] imageChunks = ImageUtils.splitImageByHeigth(bimage, printHeigth);
for (int i = 0; i < imageChunks.length; i++) {
com.lowagie.text.Image itextImage2 = com.lowagie.text.Image.getInstance(Toolkit
.getDefaultToolkit().createImage(imageChunks[i].getSource()), null);
// width becomes typically 523 (595 - 72) for a4Hoch or 770 (842 - 72) for A4Quer
float imgWidth = document.getPageSize().getWidth() - document.leftMargin()
- document.rightMargin();
float imgHeigth = itextImage.getHeight() * 0.75f;
itextImage2.setAbsolutePosition(30, 20);
int scale = 66;
itextImage2.scalePercent(scale);
document.add(itextImage2);
document.newPage();
}
}
// we're done!
document.close();
///////////////////////////////
} catch (Exception ex) {
log.error(ex.getMessage());
showMessage("Error while generating PDF", ex.getMessage());
}
} finally {
if (image != null) {
image.dispose();
}
if (gc != null) {
gc.dispose();
}
/*
image.dispose();
gc.dispose();
*/
}
}
};
actionPdf.setText(Messages.Cst_Text_Save_as_pdf);
actionPdf.setToolTipText(Messages.Cst_Text_Save_as_pdf);
/*
* actionPdf.setImageDescriptor(PlatformUI.getWorkbench() .getSharedImages()
* .getImageDescriptor(ISharedImages.IMG_OBJ_FILE));
*/
actionPdf.setImageDescriptor(Activator.getImageDescriptor(Activator.IMG_PDF_PATH));
}
protected double[] extractRefValues(LabItem labItem) {
double[] result = new double[2];
String sRangeStart = "0";
if (patient.getGeschlecht().toLowerCase().equals("m")) {
if (labItem.getRefM() != null) {
sRangeStart = labItem.getRefM();
} else {
if (labItem.getRefW() != null) {
sRangeStart = labItem.getRefW();
}
}
} else {
if (labItem.getRefW() != null) {
sRangeStart = labItem.getRefW();
} else {
if (labItem.getRefM() != null) {
sRangeStart = labItem.getRefM();
}
}
}
sRangeStart = sRangeStart.trim();
double dRangeStart = 0;
double dRangeEnd = 0;
try {
if (sRangeStart.startsWith("-")) {
sRangeStart = sRangeStart.replace("-", "");
dRangeEnd = Double.parseDouble(sRangeStart);
dRangeStart = 0;
} else if (sRangeStart.startsWith("<")) {
sRangeStart = sRangeStart.replace("<", "");
dRangeEnd = Double.parseDouble(sRangeStart);
dRangeStart = 0;
} else if (sRangeStart.startsWith(">")) {
sRangeStart = sRangeStart.replace(">", "");
dRangeStart = Double.parseDouble(sRangeStart);
dRangeEnd = 0;
} // if there is only a single number, it's probably the End of range value.
else if (sRangeStart.matches("\\d*")) {
dRangeEnd = Double.parseDouble(sRangeStart);
dRangeStart = 0;
} else {
String[] values = sRangeStart.split("-");
dRangeStart = Double.parseDouble(values[0]);
dRangeEnd = Double.parseDouble(values[1]);
}
} catch (NumberFormatException e) {
log.error("NumberFormatException for start range of Pat ID:"/* + aProfile.getKontaktId()*/
+ ":" + labItem.getName() + ":" + "/" + sRangeStart + e.getMessage(), Log.ERRORS);
} catch (ArrayIndexOutOfBoundsException e) {
log.error("ArrayIndexOutOfBoundsException for start range of " + labItem.getName() + ":"
+ "/" + sRangeStart + e.getMessage(), Log.ERRORS);
}
log.debug("Formatting Reference Values of Labitem: " + labItem.getName() + ":\t" + sRangeStart
+ " => " + dRangeStart + "/" + dRangeEnd);
result[0] = dRangeStart;
result[1] = dRangeEnd;
return result;
}
private void showMessage(String title, String msg) {
MessageDialog.openInformation(UiDesk.getTopShell(), title, msg);
}
/**
* Holt die Werte der Befunde (so wie in den Anzeigeoptionen ausgew�hlt) f�r Einzelwerte
* @param pat
* @param parm
* @param fieldName
* @param separator
* @return a value object for single values
*/
List<ValuePairTimeline> getValuesForValuePairTimeline(
final Patient pat,
final String parm,
final String fieldName,
final String separator) {
List<ValuePairTimeline> resultList = new ArrayList<ValuePairTimeline>();
// row keys...
final String myparm = parm;
if (pat != null) {
// die Messwerte befinden sich in Elexisbefunde
Query<Messwert> qbe = new Query<Messwert>(Messwert.class);
qbe.add(Messwert.FLD_PATIENT_ID, Query.EQUALS, pat.getId());
qbe.add(Messwert.FLD_NAME, Query.EQUALS, myparm);
List<Messwert> list = qbe.execute();
Collections.sort(list, new Comparator<Messwert>() {
public int compare(final Messwert o1, final Messwert o2) {
TimeTool t1 = new TimeTool(o1.get(Messwert.FLD_DATE));
TimeTool t2 = new TimeTool(o2.get(Messwert.FLD_DATE));
return t1.compareTo(t2);
}
});
StringBuffer result = new StringBuffer();
for (Messwert m : list) {
result.append(m.get(Messwert.FLD_DATE)); //$NON-NLS-1$
result.append(m.toString());
@SuppressWarnings("unchecked")
Map<String, ?> hash = m.getMap(Messwert.FLD_BEFUNDE); //$NON-NLS-1$
SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyyy");
Date date1 = null;
DateFormat shortDf = DateFormat.getDateInstance(DateFormat.SHORT);
@SuppressWarnings("unused")
String da = new String();
try {
date1 = formatter.parse(m.get(Messwert.FLD_DATE));
da = shortDf.format(date1);
} catch (ParseException e) {
log.error(e.toString() + " " + m.get(Messwert.FLD_DATE));
}
Set<String> keys = hash.keySet();
for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
Object key = (Object) iterator.next();
if (fieldName.startsWith(key.toString())) {
String bd = hash.get(key).toString();
String[] sysdia = bd.split(separator);
// sometimes theres no slash in between the 2 values
if (sysdia.length < 2) {
// if there is only one value
sysdia[1] = hash.get(key).toString();
}
String diastol = sysdia[1];
if (diastol.contains(" ")) {
String[] korrD = diastol.split(" ");
sysdia[1] = korrD[0];
}
Double dSys = new Double(sysdia[0]);
Double dDia = new Double(sysdia[1]);
ValuePairTimeline bdValue = new ValuePairTimeline(CstService.getCompactFromDate(date1),
dSys.intValue(),
dDia.intValue());
resultList.add(bdValue);
}
}
}
}
return resultList;
}
/**
* Holt die Werte der Befunde (so wie in den Anzeigeoptionen ausgew�hlt) f�r Wertepaaare
*
* @param pat
* @param parm
* @param fieldName
* @return a value object for value pairs
*/
List<ValueSingleTimeline> getValuesForSingleValueTimeline(
final Patient pat,
final String parm,
final String fieldName) {
List<ValueSingleTimeline> resultList = new ArrayList<ValueSingleTimeline>();
// row keys...
final String myparm = parm;
if (pat != null) {
Query<Messwert> qbe = new Query<Messwert>(Messwert.class);
qbe.add(Messwert.FLD_PATIENT_ID, Query.EQUALS, pat.getId());
qbe.add(Messwert.FLD_NAME, Query.EQUALS, myparm);
List<Messwert> list = qbe.execute();
Collections.sort(list, new Comparator<Messwert>() {
public int compare(final Messwert o1, final Messwert o2) {
TimeTool t1 = new TimeTool(o1.get(Messwert.FLD_DATE));
TimeTool t2 = new TimeTool(o2.get(Messwert.FLD_DATE));
return t1.compareTo(t2);
}
});
StringBuffer result = new StringBuffer();
for (Messwert messwert : list) {
result.append(messwert.get(Messwert.FLD_DATE)); //$NON-NLS-1$
result.append(messwert.toString());
@SuppressWarnings("unchecked")
Map<String, ?> hash = messwert.getMap(Messwert.FLD_BEFUNDE); //$NON-NLS-1$
SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyyy");
Date date1 = null;
DateFormat shortDf = DateFormat.getDateInstance(DateFormat.SHORT);
@SuppressWarnings("unused")
String da = "";
try {
date1 = formatter.parse(messwert.get(Messwert.FLD_DATE));
da = shortDf.format(date1);
} catch (ParseException e) {
log.error(e.toString() + "/" + messwert.get(Messwert.FLD_DATE));
}
Set<String> keys = hash.keySet();
for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
Object key = (Object) iterator.next();
if (fieldName.startsWith(key.toString())) {
String bd = hash.get(key).toString();
// Strip non-digits, ignoring decimal point
String maxValue = CstService.getMaximumOfNumbersInString(bd);
// TODO: again there could be values like "77.4 mit Kleider und Schuhen"
ValueSingleTimeline wv = new ValueSingleTimeline(CstService.getCompactFromDate(date1),
new Double(maxValue).doubleValue());
resultList.add(wv);
}
}
}
}
return resultList;
}
class LabItemSorter implements Comparator<LabItemWrapper> {
Map<String, Integer> itemRanking;
public LabItemSorter(Map<String, Integer> itemRanking) {
super();
this.itemRanking = itemRanking;
}
@Override
public int compare(LabItemWrapper o1, LabItemWrapper o2) {
Integer r1 = (Integer) itemRanking.get(o1.getLabItem().getId());
Integer r2 = (Integer) itemRanking.get(o2.getLabItem().getId());
if (r1 == null || r2 == null) {
return 0;
}
return r1.compareTo(r2);
}
}
class GroupSorter implements Comparator<CstGroup> {
Map<String, Integer> itemRanking;
public GroupSorter(Map<String, Integer> itemRanking) {
super();
this.itemRanking = itemRanking;
}
@Override
public int compare(CstGroup o1, CstGroup o2) {
Integer r1 = (Integer) itemRanking.get(o1.getId());
Integer r2 = (Integer) itemRanking.get(o2.getId());
if (r1 == null || r2 == null) {
return 0;
}
return r1.compareTo(r2);
}
}
/**
* From IActivationListener: The View changes visibility Our listeners need only to be active,if gthe view is
* visible. So we untregister them if the view disappears to save resources. If the view becomes visible again, we
* must send an event, because the listeners don't know what happend, before the start listening
*
* @param mode
* true: the view becomes visible. false: the view becomes invisible
*/
@Override
public void visible(boolean mode) {
/*
if (mode) {
ElexisEventDispatcher.getInstance().addListeners(eeli_pat);
eeli_pat.catchElexisEvent(new ElexisEvent(ElexisEventDispatcher.getSelectedPatient(), null,
ElexisEvent.EVENT_SELECTED));
} else {
ElexisEventDispatcher.getInstance().removeListeners(eeli_pat);
}
if (profile == null) {
System.out.println("Profile is null");
} else {
System.out.println("Profile is: " + profile.getName());
layoutDisplay(profile);
}*/
}
public void setProfile(CstProfile profile) {
this.profile = profile;
patient = Patient.load(profile.getKontaktId());
log.info("Result for patient: " + patient.getId() + "/" + patient.getName());
layoutDisplay(profile);
}
public boolean isA4Quer() {
return a4Quer;
}
public void setA4Quer(boolean a4Quer) {
this.a4Quer = a4Quer;
}
}