package name.abuchen.portfolio.ui.views.dashboard; import java.time.LocalDate; import java.time.format.TextStyle; import java.util.Locale; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import name.abuchen.portfolio.model.Dashboard.Widget; import name.abuchen.portfolio.money.Values; import name.abuchen.portfolio.snapshot.PerformanceIndex; import name.abuchen.portfolio.snapshot.ReportingPeriod; import name.abuchen.portfolio.ui.Messages; import name.abuchen.portfolio.ui.util.InfoToolTip; import name.abuchen.portfolio.ui.views.dataseries.DataSeries; import name.abuchen.portfolio.util.Interval; public class PerformanceHeatmapWidget extends WidgetDelegate { private Composite table; private Label title; private DashboardResources resources; public PerformanceHeatmapWidget(Widget widget, DashboardData data) { super(widget, data); addConfig(new ReportingPeriodConfig(this)); addConfig(new DataSeriesConfig(this, true)); } @Override Composite createControl(Composite parent, DashboardResources resources) { this.resources = resources; Composite container = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5).applyTo(container); container.setBackground(parent.getBackground()); title = new Label(container, SWT.NONE); title.setText(getWidget().getLabel() != null ? getWidget().getLabel() : ""); //$NON-NLS-1$ GridDataFactory.fillDefaults().grab(true, false).applyTo(title); table = new Composite(container, SWT.NONE); // 13 columns, one for the legend and 12 for the months GridDataFactory.fillDefaults().grab(true, false).applyTo(table); GridLayoutFactory.fillDefaults().numColumns(13).spacing(1, 1).applyTo(table); table.setBackground(container.getBackground()); fillTable(); return container; } private Color getScaledColorForPerformance(double performance) { double max = 0.07; double p = Math.min(max, Math.abs(performance)); int colorValue = (int) (255 * (1 - p / max)); RGB color = performance > 0d ? new RGB(colorValue, 255, colorValue) : new RGB(255, colorValue, colorValue); return resources.getResourceManager().createColor(color); } private void fillTable() { // fill the table lines according to the supplied period // calculate the performance with a temporary reporting period // calculate the color interpolated between red and green with white as // the median Interval interval = get(ReportingPeriodConfig.class).getReportingPeriod().toInterval(); ReportingPeriod currPeriod; // Top Left is empty Label topLeft = new Label(table, SWT.NONE); topLeft.setText(""); //$NON-NLS-1$ // then the legend of the months // no harm in hardcoding the year as each year has the same months for (LocalDate legendMonth = LocalDate.of(2016, 1, 1); legendMonth.getYear() == 2016; legendMonth = legendMonth .plusMonths(1)) { Label currLabel = new Label(table, SWT.NONE); currLabel.setText(legendMonth.getMonth().getDisplayName(TextStyle.NARROW, Locale.GERMAN)); currLabel.setAlignment(SWT.CENTER); GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.FILL).applyTo(currLabel); } // now loop the years DataSeries dataSeries = get(DataSeriesConfig.class).getDataSeries(); for (Integer year : interval.iterYears()) { Label currLabel = new Label(table, SWT.NONE); currLabel.setText(year.toString()); GridDataFactory.fillDefaults().grab(true, false).applyTo(currLabel); for (LocalDate currMonth = LocalDate.of(year, 1, 1); currMonth.getYear() == year; currMonth = currMonth .plusMonths(1)) { currLabel = new Label(table, SWT.RIGHT); if (interval.contains(currMonth)) { currPeriod = new ReportingPeriod.FromXtoY(currMonth.minusDays(1), currMonth.withDayOfMonth(currMonth.lengthOfMonth())); PerformanceIndex performance = getDashboardData().calculate(dataSeries, currPeriod); currLabel.setFont(resources.getSmallFont()); currLabel.setAlignment(SWT.CENTER); currLabel.setText(Values.PercentShort.format(performance.getFinalAccumulatedPercentage())); currLabel.setBackground(getScaledColorForPerformance(performance.getFinalAccumulatedPercentage())); InfoToolTip.attach(currLabel, Messages.PerformanceHeatmapToolTip); } GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.FILL).applyTo(currLabel); } } table.layout(true); } @Override void update() { title.setText(getWidget().getLabel() != null ? getWidget().getLabel() : ""); //$NON-NLS-1$ for (Control child : table.getChildren()) child.dispose(); fillTable(); table.getParent().layout(true); table.getParent().getParent().layout(true); } @Override Control getTitleControl() { return title; } }