/******************************************************************************* * 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; } }