/******************************************************************************* * 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.widget; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; 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.Point; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import ch.gpb.elexis.cst.data.ValueSingleTimeline; import ch.gpb.elexis.cst.service.CstService; public class ValueSingleTimelineCanvas extends Canvas { Font fontSmall; Font fontBig; Color ORANGE; Color BRIGHTGREEN; Color WHITE; Color GREY; Color BLACK; Color BLUE; int iPixX = 700; // Anzeigebreite in pix int iPixY = 120; // Anzeigeh�he in pix int xoffBase = 4; // x offset int yoffBase = 140; // y offset //int werteBereich = 500; // Wertebereich der in iPixY/X angezeigt werden soll int werteBereich = 1200; // Wertebereich der in iPixY/X angezeigt werden soll String befundArt = new String(); String einheit = new String(); List<ValueSingleTimeline> findings = new ArrayList<ValueSingleTimeline>(); double valueRangeOfInput; double distBetweenLines; double nrOfScaleLines; int scaleStepWidth = 0; public ValueSingleTimelineCanvas(Composite parent, int style, String befundArt, String einheit) { super(parent, style); this.befundArt = befundArt; this.einheit = einheit; WHITE = new Color(null, 255, 255, 255); ORANGE = new Color(getDisplay(), 255, 104, 0); BRIGHTGREEN = new Color(getDisplay(), 104, 255, 0); BLACK = new Color(getDisplay(), 0, 0, 0); GREY = new Color(getDisplay(), 200, 200, 200); BLUE = new Color(getDisplay(), 30, 30, 255); fontSmall = createFontofSize(7); fontBig = createFontofSize(12); setBackground(WHITE); setSize(440, 500); addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { WHITE.dispose(); BLACK.dispose(); ORANGE.dispose(); BRIGHTGREEN.dispose(); BLUE.dispose(); GREY.dispose(); fontSmall.dispose(); } }); addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { ValueSingleTimelineCanvas.this.paintControl(e); } }); } private Font createFontofSize(int sizeOfFont) { Font initialFont = getDisplay().getSystemFont(); FontData[] fontData = initialFont.getFontData(); for (int i = 0; i < fontData.length; i++) { fontData[i].setHeight(sizeOfFont); } Font newFont = new Font(getDisplay(), fontData); return newFont; } void paintControl(PaintEvent e) { GC gc = e.gc; gc.setFont(fontSmall); gc.setBackground(ORANGE); // draw the x base line gc.setForeground(GREY); gc.drawRectangle(xoffBase, yoffBase, iPixX, 1); // draw a title gc.setFont(fontBig); gc.drawText(String.valueOf(befundArt), 2, 0, true); if (findings == null || findings.size() == 0) { gc.drawText("no Findings found", 20, 20); return; } // compute nr of days between lowest and highest date Date dStart = CstService.getDateFromCompact(findings.get(0).getDate()); Date dEnd = CstService.getDateFromCompact(findings.get(findings.size() - 1).getDate()); long totalSpan = CstService.getNrOfDaysBetween(dStart, dEnd); if (findings == null || findings.size() == 0) { return; } // y-axis: Display range is 0 - 160 double yFactor = new Double(iPixY) / new Double(werteBereich).doubleValue(); //System.out.println("yFactor: " + yFactor); // 20er Linie gc.setFont(fontSmall); gc.setForeground(BLUE); int lineValue = 0; gc.drawText(String.valueOf(einheit), iPixX + 25, yoffBase - new Double(lineValue * yFactor).intValue() - 6, true); gc.setForeground(GREY); for (int i = 1; i < nrOfScaleLines + 1; i++) { gc.drawLine(xoffBase, yoffBase - new Double((i * scaleStepWidth) * yFactor).intValue(), iPixX, yoffBase - new Double((i * scaleStepWidth) * yFactor).intValue()); gc.drawText(String.valueOf(i * scaleStepWidth), iPixX + 25, yoffBase - new Double((i * scaleStepWidth) * yFactor).intValue() - 6, true); } gc.setBackground(GREY); int xoff = 0; double xFactor = new Double(iPixX).doubleValue() / new Double(totalSpan).doubleValue(); gc.setForeground(BLACK); if (findings.size() == 1) { String date = CstService.getReadableFromCompact(findings.get(0).getDate()); gc.drawText(date, xoffBase + new Double(iPixX / 2).intValue(), yoffBase, true); gc.setForeground(BLUE); gc.drawLine(xoff, yoffBase - new Double(findings.get(0).getWeightKg() * yFactor).intValue(), xoff + iPixX, yoffBase - new Double(findings.get(0).getWeightKg() * yFactor).intValue()); gc.drawText(String.valueOf(findings.get(0).getWeightKg()), xoffBase + new Double(iPixX / 2).intValue(), yoffBase - new Double(findings.get(0).getWeightKg() * yFactor).intValue(), true); gc.setForeground(ORANGE); } else { for (int x = 0; x < findings.size(); x++) { ValueSingleTimeline finding = findings.get(x); int yoff = 0; if (x % 2 == 0) { yoff = 8; } String date = CstService.getReadableFromCompact(finding.getDate()); gc.drawText(date, xoffBase + new Double(xoff * xFactor).intValue(), yoffBase + yoff + 4, true); // je gr�sser corrY desto h�her wandert der Text int corrY = 10; // print syst gc.setForeground(BLUE); gc.drawText(String.valueOf(finding.getWeightKg()), xoffBase + new Double(xoff * xFactor).intValue(), yoffBase - new Double(finding.getWeightKg() * yFactor).intValue() - corrY, true); gc.setForeground(BLACK); if (x < findings.size() - 1) { long lSpan = CstService.getNrOfDaysBetween( CstService.getDateFromCompact(findings.get(0).getDate()), CstService.getDateFromCompact(findings.get(x + 1).getDate())); xoff = new Long(lSpan).intValue(); } } } gc.dispose(); } private double getHighestValueInFindings() { double highest = 0; try { highest = 0; } catch (Exception e) { return highest; } for (int x = 0; x < findings.size(); x++) { if (findings.get(x).getWeightKg() > highest) { highest = findings.get(x).getWeightKg(); } } return highest; } private double getLowestValueInFindings() { double lowest = 0; try { lowest = findings.get(0).getWeightKg(); } catch (Exception e) { return lowest; } for (int x = 1; x < findings.size(); x++) { if (findings.get(x).getWeightKg() < lowest) { lowest = findings.get(x).getWeightKg(); } } return lowest; } public Point computeSize(int wHint, int hHint, boolean changed) { return new Point(iPixX + 70, 30 + yoffBase); } public List<ValueSingleTimeline> getFindings() { return findings; } public void setFindings(List<ValueSingleTimeline> findings) { this.findings = findings; Collections.sort(this.findings, new FindingsComparable()); double lowest = getLowestValueInFindings(); double highest = getHighestValueInFindings(); valueRangeOfInput = highest - lowest; // 20 px is the distance between scale lines distBetweenLines = 20d; //nrOfScaleLines = iPixY / distBetweenLines; nrOfScaleLines = 10; int num = new Double(getHighestValueInFindings()).intValue(); int rounded = 0; if (highest > 0 && highest < 10) { rounded = ((num + 9) / 10) * 10; scaleStepWidth = 1; } else if (highest > 10 && highest < 100) { rounded = ((num + 99) / 100) * 100; scaleStepWidth = 10; } else if (highest > 100 && highest < 1000) { rounded = ((num + 990) / 1000) * 1000; scaleStepWidth = 100; } else if (highest > 1000 && highest < 10000) { rounded = ((num + 9999) / 10000) * 10000; scaleStepWidth = 1000; } this.werteBereich = rounded; } public class FindingsComparable implements Comparator<ValueSingleTimeline> { @Override public int compare(ValueSingleTimeline o1, ValueSingleTimeline o2) { return o1.getDate().compareTo(o2.getDate()); } } }