package name.abuchen.portfolio.ui.views.dividends;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import javax.inject.Inject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.TableColumn;
import name.abuchen.portfolio.model.InvestmentVehicle;
import name.abuchen.portfolio.money.Values;
import name.abuchen.portfolio.ui.Images;
import name.abuchen.portfolio.ui.Messages;
import name.abuchen.portfolio.ui.util.TableViewerCSVExporter;
import name.abuchen.portfolio.ui.util.viewers.ColumnViewerSorter;
import name.abuchen.portfolio.ui.views.dividends.DividendsViewModel.Line;
import name.abuchen.portfolio.util.TextUtil;
public class DividendsMatrixTab implements DividendsTab
{
@Inject
private DividendsViewModel model;
private Font boldFont;
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM yy"); //$NON-NLS-1$
private TableViewer tableViewer;
@Override
public String getLabel()
{
return Messages.LabelDividendsByMonthAndVehicle;
}
@Override
public void addExportActions(IMenuManager manager)
{
manager.add(new Action(MessageFormat.format(Messages.LabelExport, Messages.LabelDividendsByMonthAndVehicle))
{
@Override
public void run()
{
new TableViewerCSVExporter(tableViewer).export(Messages.LabelDividendsByMonthAndVehicle + ".csv"); //$NON-NLS-1$
}
});
}
@Override
public Control createControl(Composite parent)
{
LocalResourceManager resources = new LocalResourceManager(JFaceResources.getResources(), parent);
boldFont = resources.createFont(FontDescriptor.createFrom(parent.getFont()).setStyle(SWT.BOLD));
Composite container = new Composite(parent, SWT.NONE);
TableColumnLayout layout = new TableColumnLayout();
container.setLayout(layout);
tableViewer = new TableViewer(container, SWT.FULL_SELECTION);
ColumnViewerToolTipSupport.enableFor(tableViewer, ToolTip.NO_RECREATE);
createColumns(tableViewer, layout);
tableViewer.getTable().setHeaderVisible(true);
tableViewer.getTable().setLinesVisible(true);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
tableViewer.setInput(model.getAllLines());
for (TableColumn c : tableViewer.getTable().getColumns())
c.pack();
model.addUpdateListener(() -> updateColumns(tableViewer, layout));
return container;
}
private void createColumns(TableViewer records, TableColumnLayout layout)
{
createSecurityColumn(records, layout, true);
// create monthly columns
LocalDate date = LocalDate.of(model.getStartYear(), Month.JANUARY, 1);
for (int index = 0; index < model.getNoOfMonths(); index++)
{
createMonthColumn(records, layout, date, index);
date = date.plusMonths(1);
}
createSumColumn(records, layout);
// add security name at the end of the matrix table again because the
// first column is most likely not visible anymore
createSecurityColumn(records, layout, false);
}
private void createSecurityColumn(TableViewer records, TableColumnLayout layout, boolean isSorted)
{
TableViewerColumn column = new TableViewerColumn(records, SWT.NONE);
column.getColumn().setText(Messages.ColumnSecurity);
column.setLabelProvider(new ColumnLabelProvider()
{
@Override
public Image getImage(Object element)
{
InvestmentVehicle vehicle = ((DividendsViewModel.Line) element).getVehicle();
return vehicle != null ? Images.SECURITY.image() : null;
}
@Override
public String getText(Object element)
{
InvestmentVehicle vehicle = ((DividendsViewModel.Line) element).getVehicle();
return vehicle != null ? vehicle.getName() : Messages.ColumnSum;
}
@Override
public Font getFont(Object element)
{
InvestmentVehicle vehicle = ((DividendsViewModel.Line) element).getVehicle();
return vehicle != null ? null : boldFont;
}
});
ColumnViewerSorter.create((o1, o2) -> {
int direction = ColumnViewerSorter.SortingContext.getSortDirection();
DividendsViewModel.Line line1 = (DividendsViewModel.Line) o1;
DividendsViewModel.Line line2 = (DividendsViewModel.Line) o2;
if (line1.getVehicle() == null)
return direction == SWT.DOWN ? 1 : -1;
if (line2.getVehicle() == null)
return direction == SWT.DOWN ? -1 : 1;
String n1 = line1.getVehicle().getName();
String n2 = line2.getVehicle().getName();
return n1.compareToIgnoreCase(n2);
}).attachTo(records, column, isSorted);
layout.setColumnData(column.getColumn(), new ColumnPixelData(200));
}
private void createMonthColumn(TableViewer records, TableColumnLayout layout, LocalDate start, int index)
{
TableViewerColumn column = new TableViewerColumn(records, SWT.RIGHT);
column.getColumn().setText(formatter.format(start));
column.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
Line line = (DividendsViewModel.Line) element;
return line.getVehicle() != null ? Values.Amount.formatNonZero(line.getValue(index))
: Values.Amount.format(line.getValue(index));
}
@Override
public String getToolTipText(Object element)
{
InvestmentVehicle vehicle = ((DividendsViewModel.Line) element).getVehicle();
return TextUtil.tooltip(vehicle != null ? vehicle.getName() : null);
}
@Override
public Font getFont(Object element)
{
InvestmentVehicle vehicle = ((DividendsViewModel.Line) element).getVehicle();
return vehicle != null ? null : boldFont;
}
});
layout.setColumnData(column.getColumn(), new ColumnPixelData(50));
}
private void createSumColumn(TableViewer records, TableColumnLayout layout)
{
TableViewerColumn column;
column = new TableViewerColumn(records, SWT.RIGHT);
column.getColumn().setText(Messages.ColumnSum);
column.setLabelProvider(new ColumnLabelProvider()
{
@Override
public String getText(Object element)
{
return Values.Amount.formatNonZero(((DividendsViewModel.Line) element).getSum());
}
@Override
public Font getFont(Object element)
{
return boldFont;
}
});
layout.setColumnData(column.getColumn(), new ColumnPixelData(200));
}
private void updateColumns(TableViewer records, TableColumnLayout layout)
{
try
{
// first add, then remove columns
// (otherwise rendering of first column is broken)
records.getTable().setRedraw(false);
int count = records.getTable().getColumnCount();
createColumns(records, layout);
for (int ii = 0; ii < count; ii++)
records.getTable().getColumn(0).dispose();
records.setInput(model.getAllLines());
for (TableColumn c : records.getTable().getColumns())
c.pack();
}
finally
{
records.refresh();
records.getTable().setRedraw(true);
}
}
}