From a796f3c716223d458a182e19865a08be230d6e04 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Wed, 10 Apr 2024 21:45:49 +0200 Subject: [PATCH 01/12] added widget for the dashboard and columns for the information of upcoming dividends and their amounts --- .../dashboard/DividendListWidgetTest.java | 251 ++++++++++++++ .../name/abuchen/portfolio/ui/Messages.java | 11 + .../abuchen/portfolio/ui/messages.properties | 20 ++ .../portfolio/ui/messages_de.properties | 20 ++ .../portfolio/ui/views/PortfolioListView.java | 10 + .../portfolio/ui/views/SecuritiesTable.java | 10 + .../ui/views/StatementOfAssetsViewer.java | 13 + .../views/columns/DividendPaymentColumn.java | 170 ++++++++++ .../dashboard/AbstractSecurityListWidget.java | 28 ++ .../views/dashboard/DividendListWidget.java | 310 ++++++++++++++++++ .../ui/views/dashboard/WidgetFactory.java | 4 +- 11 files changed, 846 insertions(+), 1 deletion(-) create mode 100644 name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java create mode 100644 name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java create mode 100644 name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java diff --git a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java new file mode 100644 index 0000000000..edef23b168 --- /dev/null +++ b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java @@ -0,0 +1,251 @@ +package name.abuchen.portfolio.ui.views.dashboard; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertEquals; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import name.abuchen.portfolio.model.Security; +import name.abuchen.portfolio.model.SecurityEvent; +import name.abuchen.portfolio.model.SecurityEvent.DividendEvent; +import name.abuchen.portfolio.money.Money; +import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DateEndRange; +import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DateStartRange; +import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DateType; +import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DividendItem; + +public class DividendListWidgetTest +{ + private Locale defaultLocale; + + private Security sec1; + private Security sec2; + private DividendEvent de1_1; + private DividendEvent de1_2; + private SecurityEvent de1_3; + private DividendEvent de1_4; + private DividendEvent de2_1; + private DividendEvent de2_2; + private SecurityEvent de2_3; + private DividendEvent de2_4; + + @Before + public void setupLocale() + { + defaultLocale = Locale.getDefault(); + Locale.setDefault(Locale.GERMANY); + } + + @After + public void resetLocale() + { + Locale.setDefault(defaultLocale); + } + + @Before + public void setupTestData() + { + sec1 = new Security("Security 1", "EUR"); + de1_1 = new DividendEvent(LocalDate.of(2024, 4, 9), LocalDate.of(2024, 4, 12), Money.of("EUR", 55), "source"); + de1_2 = new DividendEvent(LocalDate.of(2024, 7, 14), LocalDate.of(2024, 8, 11), Money.of("EUR", 22), "source"); + de1_3 = new SecurityEvent(LocalDate.of(2024, 2, 3), SecurityEvent.Type.NOTE, "some note"); + de1_4 = new DividendEvent(LocalDate.of(2024, 2, 4), LocalDate.of(2024, 3, 5), Money.of("EUR", 33), "source"); + sec1.addEvent(de1_1); + sec1.addEvent(de1_2); + sec1.addEvent(de1_3); + sec1.addEvent(de1_4); + + sec2 = new Security("Security 2", "EUR"); + de2_1 = new DividendEvent(LocalDate.of(2024, 4, 5), LocalDate.of(2024, 4, 9), Money.of("USD", 55), "source"); + de2_2 = new DividendEvent(LocalDate.of(2024, 7, 14), LocalDate.of(2024, 7, 15), Money.of("USD", 122), "source"); + de2_3 = new SecurityEvent(LocalDate.of(2024, 8, 25), SecurityEvent.Type.STOCK_SPLIT, "some stock split"); + de2_4 = new DividendEvent(LocalDate.of(2024, 2, 5), LocalDate.of(2024, 3, 5), Money.of("USD", 1333), "source"); + sec2.addEvent(de2_1); + sec2.addEvent(de2_2); + sec2.addEvent(de2_3); + sec2.addEvent(de2_4); + + } + + @Test + public void testDividendItemInstantiation() + { + DividendItem di; + + di = new DividendItem(DateType.EX_DIVIDEND_DATE, sec1, de1_1); + assertThat(di.getSecurity(), is(sec1)); + assertThat(di.type, is(DateType.EX_DIVIDEND_DATE)); + assertThat(di.div, is(de1_1)); + } + + @Test + public void testDateStartRange() + { + assertEquals("FROM_TODAY,FROM_ONE_WEEK,FROM_ONE_MONTH,FROM_YTD", // + Arrays.stream(DateStartRange.values()) + .map(DateStartRange::name).collect(Collectors.joining(","))); + + LocalDate now = LocalDate.of(2024, 4, 8); + assertThat(DateStartRange.FROM_TODAY.getDate(now), is(now)); + assertThat(DateStartRange.FROM_ONE_WEEK.getDate(now), is(LocalDate.of(2024, 4, 1))); + assertThat(DateStartRange.FROM_ONE_MONTH.getDate(now), is(LocalDate.of(2024, 3, 8))); + assertThat(DateStartRange.FROM_YTD.getDate(now), is(LocalDate.of(2024, 1, 1))); + } + + @Test + public void testDateEndRange() + { + assertEquals("UNTIL_EOY,UNTIL_ONE_MONTH,UNTIL_ONE_WEEK,UNTIL_TODAY", // + Arrays.stream(DateEndRange.values()).map(DateEndRange::name).collect(Collectors.joining(","))); + + LocalDate now = LocalDate.of(2024, 4, 8); + assertThat(DateEndRange.UNTIL_TODAY.getDate(now), is(now)); + assertThat(DateEndRange.UNTIL_ONE_WEEK.getDate(now), is(LocalDate.of(2024, 4, 15))); + assertThat(DateEndRange.UNTIL_ONE_MONTH.getDate(now), is(LocalDate.of(2024, 5, 8))); + assertThat(DateEndRange.UNTIL_EOY.getDate(now), is(LocalDate.of(2024, 12, 31))); + } + + @Test + public void testDateType() + { + assertEquals("ALL_DATES,EX_DIVIDEND_DATE,PAYMENT_DATE", // + Arrays.stream(DateType.values()).map(DateType::name).collect(Collectors.joining(","))); + + assertThat(DateType.ALL_DATES.getDate(de1_1), nullValue()); + assertThat(DateType.EX_DIVIDEND_DATE.getDate(de1_1), is(de1_1.getDate())); + assertThat(DateType.PAYMENT_DATE.getDate(de1_1), is(de1_1.getPaymentDate())); + } + + @Test + public void testGetUpdateTask() throws Exception + { + LocalDate testnow = LocalDate.now(); + @SuppressWarnings("deprecation") + AbstractSecurityListWidget widget = new DividendListWidget() + { + @Override + public Supplier> getUpdateTask(LocalDate now) + { + assertThat(now, is(testnow)); + return null; + } + }; + assertThat(widget.getUpdateTask(), nullValue()); + } + + @Test + public void testGetUpdateTaskNow() + { + List list; + AtomicReference dateStart = new AtomicReference<>(DateStartRange.FROM_TODAY); + AtomicReference dateEnd = new AtomicReference<>(DateEndRange.UNTIL_TODAY); + AtomicReference dateType = new AtomicReference<>(DateType.ALL_DATES); + + @SuppressWarnings("deprecation") + DividendListWidget widget = new DividendListWidget() + { + @Override + DateStartRange getStartRangeValue() + { + return dateStart.get(); + } + + @Override + DateEndRange getEndRangeValue() + { + return dateEnd.get(); + } + + @Override + DateType getDateTypeValue() + { + return dateType.get(); + } + + @Override + List getSecurities() + { + return Arrays.asList(sec1, sec2); + } + }; + + LocalDate now = LocalDate.of(2024, 4, 9); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-04-09 Security 1 EUR 0,55 Ex-Tag\r\n" // + + "Security 2 USD 0,55 Zahltag", getListAsString(list)); + + now = LocalDate.of(2024, 4, 8); + list = widget.getUpdateTask(now).get(); + assertEquals("", getListAsString(list)); + + dateStart.set(DateStartRange.FROM_YTD); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-02-04 Security 1 EUR 0,33 Ex-Tag\r\n" // + + "2024-02-05 Security 2 USD 13,33 Ex-Tag\r\n" // + + "2024-03-05 Security 1 EUR 0,33 Zahltag\r\n" // + + "Security 2 USD 13,33 Zahltag\r\n" // + + "2024-04-05 Security 2 USD 0,55 Ex-Tag", getListAsString(list)); + + dateEnd.set(DateEndRange.UNTIL_EOY); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-02-04 Security 1 EUR 0,33 Ex-Tag\r\n" // + + "2024-02-05 Security 2 USD 13,33 Ex-Tag\r\n" // + + "2024-03-05 Security 1 EUR 0,33 Zahltag\r\n" // + + "Security 2 USD 13,33 Zahltag\r\n" // + + "2024-04-05 Security 2 USD 0,55 Ex-Tag\r\n" // + + "2024-04-09 Security 1 EUR 0,55 Ex-Tag\r\n" // + + "Security 2 USD 0,55 Zahltag\r\n" // + + "2024-04-12 Security 1 EUR 0,55 Zahltag\r\n" // + + "2024-07-14 Security 1 EUR 0,22 Ex-Tag\r\n" // + + "Security 2 USD 1,22 Ex-Tag\r\n" // + + "2024-07-15 Security 2 USD 1,22 Zahltag\r\n" // + + "2024-08-11 Security 1 EUR 0,22 Zahltag", getListAsString(list)); + + dateType.set(DateType.EX_DIVIDEND_DATE); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-02-04 Security 1 EUR 0,33 Ex-Tag\r\n" // + + "2024-02-05 Security 2 USD 13,33 Ex-Tag\r\n" // + + "2024-04-05 Security 2 USD 0,55 Ex-Tag\r\n" // + + "2024-04-09 Security 1 EUR 0,55 Ex-Tag\r\n" // + + "2024-07-14 Security 1 EUR 0,22 Ex-Tag\r\n" // + + "Security 2 USD 1,22 Ex-Tag", getListAsString(list)); + + dateType.set(DateType.PAYMENT_DATE); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-03-05 Security 1 EUR 0,33 Zahltag\r\n" // + + "Security 2 USD 13,33 Zahltag\r\n" // + + "2024-04-09 Security 2 USD 0,55 Zahltag\r\n" // + + "2024-04-12 Security 1 EUR 0,55 Zahltag\r\n" // + + "2024-07-15 Security 2 USD 1,22 Zahltag\r\n" // + + "2024-08-11 Security 1 EUR 0,22 Zahltag", getListAsString(list)); + } + + private String getListAsString(List list) + { + return list.stream() // + .map(entry -> { + StringBuilder sb = new StringBuilder(); + if (entry.hasNewDate) + { + sb.append(entry.type.getDate(entry.div).toString() + " "); + } + sb.append(entry.getSecurity().getName() + " "); + sb.append(entry.div.getAmount() + " "); + sb.append(entry.type); + return sb.toString(); + }) // + .collect(Collectors.joining("\r\n")); + } +} diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java index 57482fdcd4..e0eac2f0f7 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java @@ -1320,6 +1320,17 @@ public class Messages extends NLS public static String OptionDateIsInTheFuture; public static String OptionDateIsInThePast; public static String YearlyPerformanceHeatmapToolTip; + + public static String LabelEarningsDividendList; + public static String LabelEarningsDividendPeriodFrom; + public static String LabelEarningsDividendPeriodUntil; + public static String LabelEarningsDividendDateType; + public static String ColumnDividendsNextExDate; + public static String ColumnDividendsNextExDate_MenuLabel; + public static String ColumnDividendsNextPaymentDate; + public static String ColumnDividendsNextPaymentDate_MenuLabel; + public static String ColumnDividendsNextPaymentAmount; + public static String ColumnDividendsNextPaymentAmount_MenuLabel; static { // initialize resource bundle diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties index d2386b5d85..33a1deb313 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties @@ -2631,3 +2631,23 @@ WatchlistRename = Rename Watchlist Website = Website YearlyPerformanceHeatmapToolTip = Yearly rate of return displayed as heatmap\n\nTo calculate the yearly rate of return, the true-time weighted rate of return (TTWROR) is used.\n\nThe rate of return is always calculated for the full year - even if the reporting interval ends or starts in the middle of a year. + +LabelEarningsDividendList = Upcoming dividends + +LabelEarningsDividendPeriodFrom = Period start + +LabelEarningsDividendPeriodUntil = Period end + +LabelEarningsDividendDateType = Type of date + +ColumnDividendsNextExDate = Next Ex-Date + +ColumnDividendsNextExDate_MenuLabel = Next Dividend Ex-Date + +ColumnDividendsNextPaymentDate = Next Paym. Date + +ColumnDividendsNextPaymentDate_MenuLabel = Next Dividend Payment Date + +ColumnDividendsNextPaymentAmount = Next Paym. Amt. + +ColumnDividendsNextPaymentAmount_MenuLabel = Next Divident Payment Amount diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties index 574c27fbdd..5cf086e4d4 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties @@ -2624,3 +2624,23 @@ WatchlistRename = Watchliste umbenennen Website = Website YearlyPerformanceHeatmapToolTip = Jahresrenditen in einer Heatmap\n\nZur Berechnung der Jahresrendite wird der True-Time Weighted Rate of Return (TTWROR) herangezogen.\n\nDie Rendite bezieht sich immer auf das gesamte Jahr - selbst wenn der Berichtszeitraum in der Mitte des Jahres beginnt bzw. endet. + +LabelEarningsDividendList = \u00DCbersicht anstehender Dividenden + +LabelEarningsDividendPeriodFrom = Zeitraum ab + +LabelEarningsDividendPeriodUntil = Zeitraum bis + +LabelEarningsDividendDateType = Datumsart + +ColumnDividendsNextExDate = Div Ex. Tag + +ColumnDividendsNextExDate_MenuLabel = Nächster Ex-Dividendentag + +ColumnDividendsNextPaymentDate = Div. Zahltag + +ColumnDividendsNextPaymentDate_MenuLabel = Nächster Dividenden Zahltag + +ColumnDividendsNextPaymentAmount = Div. Betrag + +ColumnDividendsNextPaymentAmount_MenuLabel = Nächster Dividendenbetrag diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java index 785b31614d..d90780e48c 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java @@ -49,6 +49,7 @@ import name.abuchen.portfolio.ui.util.viewers.ListEditingSupport; import name.abuchen.portfolio.ui.util.viewers.ShowHideColumnHelper; import name.abuchen.portfolio.ui.views.columns.AttributeColumn; +import name.abuchen.portfolio.ui.views.columns.DividendPaymentColumn; import name.abuchen.portfolio.ui.views.columns.NameColumn; import name.abuchen.portfolio.ui.views.columns.NameColumn.NameColumnLabelProvider; import name.abuchen.portfolio.ui.views.columns.NoteColumn; @@ -259,6 +260,7 @@ public String getText(Object element) portfolioColumns.addColumn(column); addAttributeColumns(portfolioColumns); + addDividendPaymentColumns(portfolioColumns); portfolioColumns.createColumns(true); @@ -278,6 +280,14 @@ public String getText(Object element) return container; } + private void addDividendPaymentColumns(ShowHideColumnHelper support) + { + DividendPaymentColumn.createFor() // + .forEach(column -> { + support.addColumn(column); + }); + } + private void addAttributeColumns(ShowHideColumnHelper support) { AttributeColumn.createFor(getClient(), Portfolio.class) // diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java index 3d1b475afc..82a122841b 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java @@ -98,6 +98,7 @@ import name.abuchen.portfolio.ui.views.columns.AttributeColumn; import name.abuchen.portfolio.ui.views.columns.DistanceFromAllTimeHighColumn; import name.abuchen.portfolio.ui.views.columns.DistanceFromMovingAverageColumn; +import name.abuchen.portfolio.ui.views.columns.DividendPaymentColumn; import name.abuchen.portfolio.ui.views.columns.IsinColumn; import name.abuchen.portfolio.ui.views.columns.NoteColumn; import name.abuchen.portfolio.ui.views.columns.SymbolColumn; @@ -219,6 +220,7 @@ public SecuritiesTable(Composite parent, AbstractFinanceView view) } addAttributeColumns(); + addDividendColumns(); addQuoteFeedColumns(); addDataQualityColumns(); @@ -240,6 +242,14 @@ public SecuritiesTable(Composite parent, AbstractFinanceView view) hookContextMenu(); } + private void addDividendColumns() + { + DividendPaymentColumn.createFor() // + .forEach(column -> { + support.addColumn(column); + }); + } + private void addMasterDataColumns() { Column column = new Column("0", Messages.ColumnName, SWT.LEFT, 400); //$NON-NLS-1$ diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java index c06dd0d6a1..6aa72bca9f 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java @@ -108,6 +108,7 @@ import name.abuchen.portfolio.ui.views.columns.AttributeColumn; import name.abuchen.portfolio.ui.views.columns.DistanceFromAllTimeHighColumn; import name.abuchen.portfolio.ui.views.columns.DistanceFromMovingAverageColumn; +import name.abuchen.portfolio.ui.views.columns.DividendPaymentColumn; import name.abuchen.portfolio.ui.views.columns.IsinColumn; import name.abuchen.portfolio.ui.views.columns.NameColumn; import name.abuchen.portfolio.ui.views.columns.NameColumn.NameColumnLabelProvider; @@ -749,6 +750,18 @@ private void addDividendColumns(List options) column.setSorter(ColumnViewerSorter.create(new ElementComparator(labelProvider))); column.setVisible(false); support.addColumn(column); + + addDividendPaymentColumns(); + } + + private void addDividendPaymentColumns() + { + DividendPaymentColumn.createFor() // + .forEach(column -> { + if (column.getSorter() != null) + column.getSorter().wrap(ElementComparator::new); + support.addColumn(column); + }); } private void addAttributeColumns() diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java new file mode 100644 index 0000000000..314f631386 --- /dev/null +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -0,0 +1,170 @@ +package name.abuchen.portfolio.ui.views.columns; + +import java.time.LocalDate; +import java.util.function.Function; +import java.util.stream.Stream; + +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; + +import name.abuchen.portfolio.model.Adaptor; +import name.abuchen.portfolio.model.Security; +import name.abuchen.portfolio.model.SecurityEvent.DividendEvent; +import name.abuchen.portfolio.money.Money; +import name.abuchen.portfolio.money.Values; +import name.abuchen.portfolio.ui.Messages; +import name.abuchen.portfolio.ui.util.Colors; +import name.abuchen.portfolio.ui.util.viewers.Column; +import name.abuchen.portfolio.ui.util.viewers.ColumnViewerSorter; +import name.abuchen.portfolio.ui.util.viewers.DateLabelProvider; + +public class DividendPaymentColumn +{ + + static Column createNextDividendExDateColumn() + { + Column column = new Column("nexdd", Messages.ColumnDividendsNextExDate, SWT.LEFT, 80); //$NON-NLS-1$ + column.setMenuLabel(Messages.ColumnDividendsNextExDate_MenuLabel); + column.setGroupLabel(Messages.GroupLabelDividends); + column.setVisible(false); + + LocalDate now = LocalDate.now(); + + Function dataProvider = element -> { + Security sec = Adaptor.adapt(Security.class, element); + if (sec == null) + { + return null; // + } + return sec.getEvents().stream() // + .filter(DividendEvent.class::isInstance) // + .map(e -> ((DividendEvent) e).getDate()) // + .sorted(Comparable::compareTo) // + .filter(d -> d.isAfter(now)) // + .findFirst().orElse(null); + }; + + column.setLabelProvider(new DateLabelProvider(dataProvider) + { + @Override + public Color getBackground(Object element) + { + LocalDate date = dataProvider.apply(element); + if (date == null) + { + return null; // + } + if (!date.equals(LocalDate.now())) + { + return null; // + } + return Colors.theme().greenBackground(); + } + }); + column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); + return column; + } + + static Column createNextDividendPaymentDateColumn() + { + Column column = new Column("nexpdd", Messages.ColumnDividendsNextPaymentDate, SWT.LEFT, 80); //$NON-NLS-1$ + column.setMenuLabel(Messages.ColumnDividendsNextPaymentDate_MenuLabel); + column.setGroupLabel(Messages.GroupLabelDividends); + column.setVisible(false); + + LocalDate now = LocalDate.now(); + + Function dataProvider = element -> { + Security sec = Adaptor.adapt(Security.class, element); + if (sec == null) + { + return null; // + } + return sec.getEvents().stream() // + .filter(DividendEvent.class::isInstance) // + .map(e -> ((DividendEvent) e).getPaymentDate()) // + .sorted(Comparable::compareTo) // + .filter(d -> d.isAfter(now)) // + .findFirst().orElse(null); + }; + + column.setLabelProvider(new DateLabelProvider(dataProvider) + { + @Override + public Color getBackground(Object element) + { + LocalDate date = dataProvider.apply(element); + if (date == null) + { + return null; // + } + if (!date.equals(LocalDate.now())) + { + return null; // + } + return Colors.theme().redBackground(); + } + }); + column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); + return column; + } + + static Column createNextDividendPaymentAmount() + { + Column column = new Column("nexdpa", Messages.ColumnDividendsNextPaymentAmount, SWT.RIGHT, 60); //$NON-NLS-1$ + column.setMenuLabel(Messages.ColumnDividendsNextPaymentAmount_MenuLabel); + column.setGroupLabel(Messages.GroupLabelDividends); + column.setVisible(false); + column.setLabelProvider(new ColumnLabelProvider() + { + @Override + public String getText(Object element) + { + Security sec = Adaptor.adapt(Security.class, element); + if (sec == null) + { + return null; // + } + LocalDate now = LocalDate.now(); + Money amount = getAmount(now, sec); + + if (amount == null) + { + return null; // + } + return Values.Money.format(amount); + } + }); + column.setSorter(ColumnViewerSorter.create((o1, o2) -> { + Money m1 = getAmount(LocalDate.now(), (Security) o1); + Money m2 = getAmount(LocalDate.now(), (Security) o2); + + if (m1 == null) + return m2 == null ? 0 : -1; + if (m2 == null) + return 1; + + return m1.compareTo(m2); + })); + return column; + } + + static Money getAmount(LocalDate now, Security sec) + { + return sec.getEvents().stream() // + .filter(e -> e instanceof DividendEvent) // + .map(e -> (DividendEvent) e) // + .sorted((e1, e2) -> e1.getPaymentDate().compareTo(e2.getPaymentDate())) // + .filter(d -> d.getPaymentDate().isAfter(now)) // + .map(DividendEvent::getAmount).findFirst().orElse(null); + } + + public static Stream createFor() + { + return Stream.of(createNextDividendExDateColumn(), // + createNextDividendPaymentDateColumn(), // + createNextDividendPaymentAmount()); + } + +} diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java index c1137d68d6..b9fa98ee6d 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java @@ -1,6 +1,7 @@ package name.abuchen.portfolio.ui.views.dashboard; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -11,10 +12,12 @@ import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.RowLayout; 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.model.Security; @@ -63,6 +66,17 @@ public Security getSecurity() view.setInformationPaneInput(((Item) item).getSecurity()); }); + protected void addListener(MouseListener listener, Control... controls) + { + for (Control ctr : controls) + { + if (ctr != null) + { + ctr.addMouseListener(listener); + } + } + } + public AbstractSecurityListWidget(Widget widget, DashboardData data) { super(widget, data); @@ -167,4 +181,18 @@ public Control getTitleControl() return title; } + protected Label createLabel(Composite composite, String text) + { + Label ret = new Label(composite, SWT.NONE); + ret.setText(Objects.toString(text).replace("&", "&&")); //$NON-NLS-1$ //$NON-NLS-2$ + return ret; + } + + protected Label createLabel(Composite composite, Image image) + { + Label ret = new Label(composite, SWT.NONE); + ret.setImage(image); + return ret; + } + } diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java new file mode 100644 index 0000000000..d29db8a683 --- /dev/null +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java @@ -0,0 +1,310 @@ +package name.abuchen.portfolio.ui.views.dashboard; + +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +import name.abuchen.portfolio.model.Dashboard; +import name.abuchen.portfolio.model.Dashboard.Widget; +import name.abuchen.portfolio.model.Security; +import name.abuchen.portfolio.model.SecurityEvent; +import name.abuchen.portfolio.model.SecurityEvent.DividendEvent; +import name.abuchen.portfolio.money.Values; +import name.abuchen.portfolio.ui.Messages; +import name.abuchen.portfolio.ui.util.FormDataFactory; +import name.abuchen.portfolio.ui.util.LogoManager; + +public class DividendListWidget extends AbstractSecurityListWidget +{ + public static class DividendItem extends AbstractSecurityListWidget.Item + { + boolean hasNewDate; + DateType type; + DividendEvent div; + + public DividendItem(DateType type, Security security, DividendEvent div) + { + super(security); + this.div = div; + this.type = type; + } + } + + public enum DateStartRange + { + FROM_TODAY(Messages.LabelToday, d -> d), // + FROM_ONE_WEEK(Messages.LabelReportingDialogWeek, d -> d.minus(1, ChronoUnit.WEEKS)), // + FROM_ONE_MONTH(Messages.LabelReportingDialogMonth, d -> d.minus(1, ChronoUnit.MONTHS)), // + FROM_YTD(Messages.LabelReportingDialogYearYTD, d -> LocalDate.of(d.getYear(), 1, 1)), // + ; + + private DateStartRange(String label, UnaryOperator dateStartProvider) + { + this.label = label; + this.dateStartProvider = dateStartProvider; + } + + private String label; + private UnaryOperator dateStartProvider; + + LocalDate getDate(LocalDate now) + { + return dateStartProvider.apply(now); + } + + @Override + public String toString() + { + return label; + } + } + + static class DateStartRangeConfig extends EnumBasedConfig + { + public DateStartRangeConfig(WidgetDelegate delegate) + { + super(delegate, Messages.LabelEarningsDividendPeriodFrom, DateStartRange.class, + Dashboard.Config.START_YEAR, Policy.EXACTLY_ONE); + } + } + + public enum DateEndRange + { + UNTIL_EOY(Messages.LabelReportingDialogYear, d -> LocalDate.of(d.getYear(), 12, 31)), // + UNTIL_ONE_MONTH(Messages.LabelReportingDialogMonth, d -> d.plus(1, ChronoUnit.MONTHS)), // + UNTIL_ONE_WEEK(Messages.LabelReportingDialogWeek, d -> d.plus(1, ChronoUnit.WEEKS)), // + UNTIL_TODAY(Messages.LabelToday, d -> d), // + ; + + private DateEndRange(String label, UnaryOperator dateStartProvider) + { + this.label = label; + this.dateEndProvider = dateStartProvider; + } + + private String label; + private UnaryOperator dateEndProvider; + + LocalDate getDate(LocalDate now) + { + return dateEndProvider.apply(now); + } + + @Override + public String toString() + { + return label; + } + } + + static class DateEndRangeConfig extends EnumBasedConfig + { + public DateEndRangeConfig(WidgetDelegate delegate) + { + super(delegate, Messages.LabelEarningsDividendPeriodUntil, DateEndRange.class, + Dashboard.Config.REPORTING_PERIOD, Policy.EXACTLY_ONE); + } + } + + public enum DateType + { + ALL_DATES(Messages.LabelAllAttributes, d -> null), // + EX_DIVIDEND_DATE(Messages.ColumnExDate, DividendEvent::getDate), // + PAYMENT_DATE(Messages.ColumnPaymentDate, DividendEvent::getPaymentDate), // + ; + + private DateType(String label, Function dateProvider) + { + this.label = label; + this.dateProvider = dateProvider; + } + + private String label; + private Function dateProvider; + + public LocalDate getDate(DividendEvent evt) + { + return dateProvider.apply(evt); + } + + @Override + public String toString() + { + return label; + } + } + + static class DateTypeConfig extends EnumBasedConfig + { + public DateTypeConfig(WidgetDelegate delegate) + { + super(delegate, Messages.LabelEarningsDividendDateType, DateType.class, Dashboard.Config.EARNING_TYPE, + Policy.EXACTLY_ONE); + } + } + + /** + * @deprecated This constructor is only used for testing, don't use it for + * anything else + */ + @Deprecated + DividendListWidget() // needed for testing + { + super(null, null); + } + + public DividendListWidget(Widget widget, DashboardData data) + { + super(widget, data); + + addConfig(new DateTypeConfig(this)); + addConfig(new DateStartRangeConfig(this)); + addConfig(new DateEndRangeConfig(this)); + addConfig(new ChartHeightConfig(this)); + } + + @Override + public Supplier> getUpdateTask() + { + return getUpdateTask(LocalDate.now()); + } + + Supplier> getUpdateTask(LocalDate now) + { + return () -> { + + DateType dateType = getDateTypeValue(); + + List items = new ArrayList<>(); + LocalDate fromDate = getStartRangeValue().getDate(now); + LocalDate untilDate = getEndRangeValue().getDate(now); + for (Security security : getSecurities()) + { + for (SecurityEvent se : security.getEvents()) + { + if (!(se instanceof DividendEvent de)) + { + continue; + } + checkAndAdd(items, security, de, dateType, DateType.EX_DIVIDEND_DATE, fromDate, untilDate); + checkAndAdd(items, security, de, dateType, DateType.PAYMENT_DATE, fromDate, untilDate); + } + } + + Collections.sort(items, (di1, di2) -> di1.type.getDate(di1.div).compareTo(di2.type.getDate(di2.div))); + LocalDate prevDate = null; + for (DividendItem item : items) + { + LocalDate currDate = item.type.getDate(item.div); + if (prevDate == null || !currDate.isEqual(prevDate)) + { + item.hasNewDate = true; + prevDate = currDate; + continue; + } + } + + return items; + }; + } + + DateStartRange getStartRangeValue() + { + return get(DateStartRangeConfig.class).getValue(); + } + + DateEndRange getEndRangeValue() + { + return get(DateEndRangeConfig.class).getValue(); + } + + DateType getDateTypeValue() + { + return get(DateTypeConfig.class).getValue(); + } + + List getSecurities() + { + return getClient().getSecurities(); + } + + DividendItem checkAndAdd(List items, Security sec, DividendEvent de, DateType configuredType, + DateType typeToAdd, LocalDate startRange, LocalDate endRange) + { + if (configuredType != typeToAdd && configuredType != DateType.ALL_DATES) + { + return null; + } + + LocalDate checkDate = typeToAdd.getDate(de); + if (checkDate.isBefore(startRange)) + { + return null; // + } + + if (checkDate.isAfter(endRange)) + { + return null; // + } + + DividendItem ret = new DividendItem(typeToAdd, sec, de); + items.add(ret); + return ret; + } + + @Override + protected Composite createItemControl(Composite parent, DividendItem item) + { + Security sec = item.getSecurity(); + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new FormLayout()); + + Image image = LogoManager.instance().getDefaultColumnImage(sec, getClient().getSettings()); + Label logo = createLabel(composite, image); + Label name = createLabel(composite, sec.getName()); + Label amtAndType = createLabel(composite, + " " + Values.Money.format(item.div.getAmount()) + " " + item.type.label); //$NON-NLS-1$ //$NON-NLS-2$ + + + Label date = null; + + if (item.hasNewDate) + { + date = createLabel(composite, Values.Date.format(item.type.getDate(item.div))); + } + + addListener(mouseUpAdapter, composite, name, date, amtAndType); + + FormDataFactory start; + if (date != null) + { + start = FormDataFactory.startingWith(date).thenBelow(logo); + } + else + { + start = FormDataFactory.startingWith(logo); + } + start.thenRight(name).right(new FormAttachment(100)).thenBelow(amtAndType); + + return composite; + } + + @Override + protected void createEmptyControl(Composite parent) + { + // nothing to do + } + +} diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java index a04b9ed046..25deedd407 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java @@ -25,9 +25,9 @@ import name.abuchen.portfolio.ui.views.dashboard.earnings.EarningsChartWidget; import name.abuchen.portfolio.ui.views.dashboard.earnings.EarningsHeatmapWidget; import name.abuchen.portfolio.ui.views.dashboard.earnings.EarningsListWidget; +import name.abuchen.portfolio.ui.views.dashboard.heatmap.CostHeatmapWidget; import name.abuchen.portfolio.ui.views.dashboard.heatmap.InvestmentHeatmapWidget; import name.abuchen.portfolio.ui.views.dashboard.heatmap.PerformanceHeatmapWidget; -import name.abuchen.portfolio.ui.views.dashboard.heatmap.CostHeatmapWidget; import name.abuchen.portfolio.ui.views.dashboard.heatmap.YearlyPerformanceHeatmapWidget; import name.abuchen.portfolio.ui.views.dataseries.DataSeries; import name.abuchen.portfolio.ui.views.payments.PaymentsViewModel; @@ -215,6 +215,8 @@ public enum WidgetFactory HEATMAP_EARNINGS(Messages.LabelHeatmapEarnings, Messages.LabelEarnings, EarningsHeatmapWidget::new), + EARNINGS_DIVIDEND_LIST(Messages.LabelEarningsDividendList, Messages.LabelEarnings, DividendListWidget::new), + EARNINGS_PER_YEAR_CHART(Messages.LabelEarningsPerYear, Messages.LabelEarnings, EarningsChartWidget::perYear), EARNINGS_PER_QUARTER_CHART(Messages.LabelEarningsPerQuarter, Messages.LabelEarnings, EarningsChartWidget::perQuarter), From 4e106948ebcadffca4552e8f32fc4f0d0a126835 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Wed, 10 Apr 2024 22:00:31 +0200 Subject: [PATCH 02/12] use BeforeClass and AfterClass to make sure we've "selected" German before the read of the language files takes place --- .../ui/views/dashboard/DividendListWidgetTest.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java index edef23b168..aa06047543 100644 --- a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java +++ b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java @@ -13,8 +13,9 @@ import java.util.function.Supplier; import java.util.stream.Collectors; -import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import name.abuchen.portfolio.model.Security; @@ -28,7 +29,7 @@ public class DividendListWidgetTest { - private Locale defaultLocale; + private static Locale defaultLocale; private Security sec1; private Security sec2; @@ -41,15 +42,15 @@ public class DividendListWidgetTest private SecurityEvent de2_3; private DividendEvent de2_4; - @Before - public void setupLocale() + @BeforeClass + public static void setupLocale() { defaultLocale = Locale.getDefault(); Locale.setDefault(Locale.GERMANY); } - @After - public void resetLocale() + @AfterClass + public static void resetLocale() { Locale.setDefault(defaultLocale); } From de457f1a29dcacc2d11451a4030d6d063f56ec72 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Wed, 10 Apr 2024 22:06:55 +0200 Subject: [PATCH 03/12] Previous change had no effect on the tests on the GitHub-Server, so using the actual localized values themselves --- .../dashboard/DividendListWidgetTest.java | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java index aa06047543..2f495464ef 100644 --- a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java +++ b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java @@ -22,6 +22,7 @@ import name.abuchen.portfolio.model.SecurityEvent; import name.abuchen.portfolio.model.SecurityEvent.DividendEvent; import name.abuchen.portfolio.money.Money; +import name.abuchen.portfolio.ui.Messages; import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DateEndRange; import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DateStartRange; import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DateType; @@ -184,7 +185,7 @@ List getSecurities() LocalDate now = LocalDate.of(2024, 4, 9); list = widget.getUpdateTask(now).get(); - assertEquals("2024-04-09 Security 1 EUR 0,55 Ex-Tag\r\n" // + assertEquals("2024-04-09 Security 1 EUR 0,55 " + Messages.ColumnExDate + "\r\n" // + "Security 2 USD 0,55 Zahltag", getListAsString(list)); now = LocalDate.of(2024, 4, 8); @@ -193,44 +194,44 @@ List getSecurities() dateStart.set(DateStartRange.FROM_YTD); list = widget.getUpdateTask(now).get(); - assertEquals("2024-02-04 Security 1 EUR 0,33 Ex-Tag\r\n" // - + "2024-02-05 Security 2 USD 13,33 Ex-Tag\r\n" // - + "2024-03-05 Security 1 EUR 0,33 Zahltag\r\n" // - + "Security 2 USD 13,33 Zahltag\r\n" // - + "2024-04-05 Security 2 USD 0,55 Ex-Tag", getListAsString(list)); + assertEquals("2024-02-04 Security 1 EUR 0,33 " + Messages.ColumnExDate + "\r\n" // + + "2024-02-05 Security 2 USD 13,33 " + Messages.ColumnExDate + "\r\n" // + + "2024-03-05 Security 1 EUR 0,33 " + Messages.ColumnPaymentDate + "\r\n" // + + "Security 2 USD 13,33 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-04-05 Security 2 USD 0,55 " + Messages.ColumnExDate, getListAsString(list)); dateEnd.set(DateEndRange.UNTIL_EOY); list = widget.getUpdateTask(now).get(); - assertEquals("2024-02-04 Security 1 EUR 0,33 Ex-Tag\r\n" // - + "2024-02-05 Security 2 USD 13,33 Ex-Tag\r\n" // - + "2024-03-05 Security 1 EUR 0,33 Zahltag\r\n" // - + "Security 2 USD 13,33 Zahltag\r\n" // - + "2024-04-05 Security 2 USD 0,55 Ex-Tag\r\n" // - + "2024-04-09 Security 1 EUR 0,55 Ex-Tag\r\n" // - + "Security 2 USD 0,55 Zahltag\r\n" // - + "2024-04-12 Security 1 EUR 0,55 Zahltag\r\n" // - + "2024-07-14 Security 1 EUR 0,22 Ex-Tag\r\n" // - + "Security 2 USD 1,22 Ex-Tag\r\n" // - + "2024-07-15 Security 2 USD 1,22 Zahltag\r\n" // - + "2024-08-11 Security 1 EUR 0,22 Zahltag", getListAsString(list)); + assertEquals("2024-02-04 Security 1 EUR 0,33 " + Messages.ColumnExDate + "\r\n" // + + "2024-02-05 Security 2 USD 13,33 " + Messages.ColumnExDate + "\r\n" // + + "2024-03-05 Security 1 EUR 0,33 " + Messages.ColumnPaymentDate + "\r\n" // + + "Security 2 USD 13,33 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-04-05 Security 2 USD 0,55 " + Messages.ColumnExDate + "\r\n" // + + "2024-04-09 Security 1 EUR 0,55 " + Messages.ColumnExDate + "\r\n" // + + "Security 2 USD 0,55 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-04-12 Security 1 EUR 0,55 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-07-14 Security 1 EUR 0,22 " + Messages.ColumnExDate + "\r\n" // + + "Security 2 USD 1,22 " + Messages.ColumnExDate + "\r\n" // + + "2024-07-15 Security 2 USD 1,22 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-08-11 Security 1 EUR 0,22 " + Messages.ColumnPaymentDate, getListAsString(list)); dateType.set(DateType.EX_DIVIDEND_DATE); list = widget.getUpdateTask(now).get(); - assertEquals("2024-02-04 Security 1 EUR 0,33 Ex-Tag\r\n" // - + "2024-02-05 Security 2 USD 13,33 Ex-Tag\r\n" // - + "2024-04-05 Security 2 USD 0,55 Ex-Tag\r\n" // - + "2024-04-09 Security 1 EUR 0,55 Ex-Tag\r\n" // - + "2024-07-14 Security 1 EUR 0,22 Ex-Tag\r\n" // - + "Security 2 USD 1,22 Ex-Tag", getListAsString(list)); + assertEquals("2024-02-04 Security 1 EUR 0,33 " + Messages.ColumnExDate + "\r\n" // + + "2024-02-05 Security 2 USD 13,33 " + Messages.ColumnExDate + "\r\n" // + + "2024-04-05 Security 2 USD 0,55 " + Messages.ColumnExDate + "\r\n" // + + "2024-04-09 Security 1 EUR 0,55 " + Messages.ColumnExDate + "\r\n" // + + "2024-07-14 Security 1 EUR 0,22 " + Messages.ColumnExDate + "\r\n" // + + "Security 2 USD 1,22 " + Messages.ColumnExDate, getListAsString(list)); dateType.set(DateType.PAYMENT_DATE); list = widget.getUpdateTask(now).get(); - assertEquals("2024-03-05 Security 1 EUR 0,33 Zahltag\r\n" // - + "Security 2 USD 13,33 Zahltag\r\n" // - + "2024-04-09 Security 2 USD 0,55 Zahltag\r\n" // - + "2024-04-12 Security 1 EUR 0,55 Zahltag\r\n" // - + "2024-07-15 Security 2 USD 1,22 Zahltag\r\n" // - + "2024-08-11 Security 1 EUR 0,22 Zahltag", getListAsString(list)); + assertEquals("2024-03-05 Security 1 EUR 0,33 " + Messages.ColumnPaymentDate + "\r\n" // + + "Security 2 USD 13,33 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-04-09 Security 2 USD 0,55 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-04-12 Security 1 EUR 0,55 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-07-15 Security 2 USD 1,22 " + Messages.ColumnPaymentDate + "\r\n" // + + "2024-08-11 Security 1 EUR 0,22 " + Messages.ColumnPaymentDate, getListAsString(list)); } private String getListAsString(List list) From 2cc9567b073058ccb6fc7300178328f0a4388466 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Wed, 10 Apr 2024 22:15:02 +0200 Subject: [PATCH 04/12] fixed missed test that still used the hard coded text --- .../portfolio/ui/views/dashboard/DividendListWidgetTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java index 2f495464ef..a4914d77d4 100644 --- a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java +++ b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java @@ -186,7 +186,7 @@ List getSecurities() LocalDate now = LocalDate.of(2024, 4, 9); list = widget.getUpdateTask(now).get(); assertEquals("2024-04-09 Security 1 EUR 0,55 " + Messages.ColumnExDate + "\r\n" // - + "Security 2 USD 0,55 Zahltag", getListAsString(list)); + + "Security 2 USD 0,55 " + Messages.ColumnPaymentDate, getListAsString(list)); now = LocalDate.of(2024, 4, 8); list = widget.getUpdateTask(now).get(); From 9f867ac6420aac9c07a66f16ddf9d89cfe81f967 Mon Sep 17 00:00:00 2001 From: Lothar Kimmeringer Date: Thu, 11 Apr 2024 10:07:26 +0200 Subject: [PATCH 05/12] Update name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java Co-authored-by: Alexander Ott <45203494+Nirus2000@users.noreply.github.com> --- .../ui/views/columns/DividendPaymentColumn.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java index 314f631386..629ffff9cd 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -51,15 +51,11 @@ static Column createNextDividendExDateColumn() public Color getBackground(Object element) { LocalDate date = dataProvider.apply(element); - if (date == null) - { - return null; // - } - if (!date.equals(LocalDate.now())) - { - return null; // - } - return Colors.theme().greenBackground(); +if (date == null || !date.equals(LocalDate.now())) { + return null; +} + +return Colors.theme().greenBackground(); } }); column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); From f7a570351701979142d3817e0dd3d82223f7d8d6 Mon Sep 17 00:00:00 2001 From: Lothar Kimmeringer Date: Thu, 11 Apr 2024 10:08:50 +0200 Subject: [PATCH 06/12] Update name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java Co-authored-by: Alexander Ott <45203494+Nirus2000@users.noreply.github.com> --- .../ui/views/columns/DividendPaymentColumn.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java index 629ffff9cd..5834afc4eb 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -90,16 +90,11 @@ static Column createNextDividendPaymentDateColumn() @Override public Color getBackground(Object element) { - LocalDate date = dataProvider.apply(element); - if (date == null) - { - return null; // - } - if (!date.equals(LocalDate.now())) - { - return null; // - } - return Colors.theme().redBackground(); +if (date == null || !date.equals(LocalDate.now())) { + return null; +} + +return Colors.theme().redBackground(); } }); column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); From 9aecbfce00c18214e9a5f831b18dc999d69912a5 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Thu, 11 Apr 2024 10:16:11 +0200 Subject: [PATCH 07/12] use more readable column-identifiers, reformatted source to make the CI happy --- .../views/columns/DividendPaymentColumn.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java index 5834afc4eb..a72e0a2af6 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -24,7 +24,7 @@ public class DividendPaymentColumn static Column createNextDividendExDateColumn() { - Column column = new Column("nexdd", Messages.ColumnDividendsNextExDate, SWT.LEFT, 80); //$NON-NLS-1$ + Column column = new Column("nextdivexdate", Messages.ColumnDividendsNextExDate, SWT.LEFT, 80); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextExDate_MenuLabel); column.setGroupLabel(Messages.GroupLabelDividends); column.setVisible(false); @@ -51,11 +51,12 @@ static Column createNextDividendExDateColumn() public Color getBackground(Object element) { LocalDate date = dataProvider.apply(element); -if (date == null || !date.equals(LocalDate.now())) { - return null; -} + if (date == null || !date.equals(LocalDate.now())) + { + return null; // + } -return Colors.theme().greenBackground(); + return Colors.theme().greenBackground(); } }); column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); @@ -64,7 +65,7 @@ public Color getBackground(Object element) static Column createNextDividendPaymentDateColumn() { - Column column = new Column("nexpdd", Messages.ColumnDividendsNextPaymentDate, SWT.LEFT, 80); //$NON-NLS-1$ + Column column = new Column("nextdivpmtdate", Messages.ColumnDividendsNextPaymentDate, SWT.LEFT, 80); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextPaymentDate_MenuLabel); column.setGroupLabel(Messages.GroupLabelDividends); column.setVisible(false); @@ -90,11 +91,13 @@ static Column createNextDividendPaymentDateColumn() @Override public Color getBackground(Object element) { -if (date == null || !date.equals(LocalDate.now())) { - return null; -} + LocalDate date = dataProvider.apply(element); + if (date == null || !date.equals(LocalDate.now())) + { + return null; // + } -return Colors.theme().redBackground(); + return Colors.theme().redBackground(); } }); column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); @@ -103,7 +106,7 @@ public Color getBackground(Object element) static Column createNextDividendPaymentAmount() { - Column column = new Column("nexdpa", Messages.ColumnDividendsNextPaymentAmount, SWT.RIGHT, 60); //$NON-NLS-1$ + Column column = new Column("nextdivpmtamt", Messages.ColumnDividendsNextPaymentAmount, SWT.RIGHT, 60); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextPaymentAmount_MenuLabel); column.setGroupLabel(Messages.GroupLabelDividends); column.setVisible(false); From 40e059d08bfca069a726ef27bedbdc43504a69b9 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Thu, 11 Apr 2024 21:01:32 +0200 Subject: [PATCH 08/12] added other languages, courtesy of deepl.com --- .../abuchen/portfolio/ui/messages.properties | 40 +++++++++---------- .../portfolio/ui/messages_cs.properties | 12 ++++++ .../portfolio/ui/messages_da.properties | 12 ++++++ .../portfolio/ui/messages_de.properties | 40 +++++++++---------- .../portfolio/ui/messages_es.properties | 12 ++++++ .../portfolio/ui/messages_fr.properties | 12 ++++++ .../portfolio/ui/messages_it.properties | 12 ++++++ .../portfolio/ui/messages_nl.properties | 12 ++++++ .../portfolio/ui/messages_pl.properties | 12 ++++++ .../portfolio/ui/messages_pt.properties | 12 ++++++ .../portfolio/ui/messages_pt_BR.properties | 12 ++++++ .../portfolio/ui/messages_ru.properties | 12 ++++++ .../portfolio/ui/messages_sk.properties | 12 ++++++ .../portfolio/ui/messages_zh.properties | 12 ++++++ .../portfolio/ui/messages_zh_TW.properties | 12 ++++++ 15 files changed, 196 insertions(+), 40 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties index 33a1deb313..43ff8254e0 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages.properties @@ -394,6 +394,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = dividend rate of return = sum of dividend payments / purchase value based on FIFO\n\nAttention: if shares are sold after a dividend payment then dividend payment is not reduced. Therefore the rate of return might be over estimated. +ColumnDividendsNextExDate = Next Ex-Date + +ColumnDividendsNextExDate_MenuLabel = Next Dividend Ex-Date + +ColumnDividendsNextPaymentAmount = Next Paym. Amt. + +ColumnDividendsNextPaymentAmount_MenuLabel = Next Dividend Payment Amount + +ColumnDividendsNextPaymentDate = Next Paym. Date + +ColumnDividendsNextPaymentDate_MenuLabel = Next Dividend Payment Date + ColumnEarnings = Earnings ColumnEarnings_Description = Dividends + Interest Payments @@ -1242,6 +1254,14 @@ LabelEarnings = Earnings LabelEarningsByTaxonomy = Earnings by taxonomy +LabelEarningsDividendDateType = Type of date + +LabelEarningsDividendList = Upcoming dividends + +LabelEarningsDividendPeriodFrom = Period start + +LabelEarningsDividendPeriodUntil = Period end + LabelEarningsPerMonth = Earnings per month LabelEarningsPerQuarter = Earnings per quarter @@ -2631,23 +2651,3 @@ WatchlistRename = Rename Watchlist Website = Website YearlyPerformanceHeatmapToolTip = Yearly rate of return displayed as heatmap\n\nTo calculate the yearly rate of return, the true-time weighted rate of return (TTWROR) is used.\n\nThe rate of return is always calculated for the full year - even if the reporting interval ends or starts in the middle of a year. - -LabelEarningsDividendList = Upcoming dividends - -LabelEarningsDividendPeriodFrom = Period start - -LabelEarningsDividendPeriodUntil = Period end - -LabelEarningsDividendDateType = Type of date - -ColumnDividendsNextExDate = Next Ex-Date - -ColumnDividendsNextExDate_MenuLabel = Next Dividend Ex-Date - -ColumnDividendsNextPaymentDate = Next Paym. Date - -ColumnDividendsNextPaymentDate_MenuLabel = Next Dividend Payment Date - -ColumnDividendsNextPaymentAmount = Next Paym. Amt. - -ColumnDividendsNextPaymentAmount_MenuLabel = Next Divident Payment Amount diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_cs.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_cs.properties index 0db8ba8194..197b40c4c2 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_cs.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_cs.properties @@ -390,6 +390,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = Dividendov\u00FD v\u00FDnos = sou\u010Det v\u00FDplat dividend / n\u00E1kupn\u00ED hodnota na z\u00E1klad\u011B FIFO\n\nPozor: pokud jsou akcie prod\u00E1ny po v\u00FDplat\u011B dividendy, pak se v\u00FDplata dividendy nesni\u017Euje. Proto m\u016F\u017Ee b\u00FDt m\u00EDra v\u00FDnosnosti nadhodnocena. +ColumnDividendsNextExDate = P\u0159\u00ED\u0161t\u00ED den ex-day + +ColumnDividendsNextExDate_MenuLabel = P\u0159\u00ED\u0161t\u00ED Den Ex-Dividend + +ColumnDividendsNextPaymentAmount = P\u0159\u00ED\u0161t\u00ED V\u00FD\u0161e Dividendy + +ColumnDividendsNextPaymentAmount_MenuLabel = P\u0159\u00ED\u0161t\u00ED V\u00FD\u0161e Dividendy + +ColumnDividendsNextPaymentDate = Datum P\u0159\u00ED\u0161t\u00ED V\u00FDplaty Dividend + +ColumnDividendsNextPaymentDate_MenuLabel = Datum P\u0159\u00ED\u0161t\u00ED V\u00FDplaty Dividend + ColumnEarnings = Zisk ColumnEarnings_Description = Dividendy + \u00FAroky diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_da.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_da.properties index e830f33f8e..5556ecbdc1 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_da.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_da.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Udb% ColumnDividendTotalRateOfReturn_Description = udbytteafkast = summen af \u200B\u200Budbyttebetalinger / k\u00F8bsv\u00E6rdi baseret p\u00E5 FIFO\n\nBem\u00E6rk: Hvis aktier s\u00E6lges efter en udbyttebetaling, reduceres udbyttebetalingen ikke. Derfor kan afkastet v\u00E6re overvurderet. +ColumnDividendsNextExDate = N\u00E6ste Ex-Dato + +ColumnDividendsNextExDate_MenuLabel = N\u00E6ste Ex-Udbyttedag + +ColumnDividendsNextPaymentAmount = N\u00E6ste Udbyttebel\u00F8b + +ColumnDividendsNextPaymentAmount_MenuLabel = N\u00E6ste Udbyttebel\u00F8b + +ColumnDividendsNextPaymentDate = Dato for N\u00E6ste Udbyttebetaling + +ColumnDividendsNextPaymentDate_MenuLabel = Dato for N\u00E6ste Udbyttebetaling + ColumnEarnings = Fortjenester ColumnEarnings_Description = Udbytter + Renteindt\u00E6gter diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties index 5cf086e4d4..efef76e360 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_de.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = Dividendenrendite = Summe der Dividendenzahlungen / Einstand nach FIFO\n\nAchtung: Wenn Verk\u00E4ufe nach einer Dividendenzahlung vorliegen, werden die momentan nicht abgezogen. D. h. die Rendite ist eventuell zu hoch. +ColumnDividendsNextExDate = N\u00E4chst. Ex-Tag + +ColumnDividendsNextExDate_MenuLabel = N\u00E4chster Ex-Dividendentag + +ColumnDividendsNextPaymentAmount = N\u00E4chst. Div. Betrag + +ColumnDividendsNextPaymentAmount_MenuLabel = N\u00E4chster Dividendenbetrag + +ColumnDividendsNextPaymentDate = N\u00E4chst. Div. Zahltag + +ColumnDividendsNextPaymentDate_MenuLabel = N\u00E4chster Dividenden Zahltag + ColumnEarnings = Ertr\u00E4ge ColumnEarnings_Description = Dividenden + Zinsen @@ -1235,6 +1247,14 @@ LabelEarnings = Ertr\u00E4ge LabelEarningsByTaxonomy = Ertr\u00E4ge nach Klassifikation +LabelEarningsDividendDateType = Datumsart + +LabelEarningsDividendList = \u00DCbersicht anstehender Dividenden + +LabelEarningsDividendPeriodFrom = Zeitraum ab + +LabelEarningsDividendPeriodUntil = Zeitraum bis + LabelEarningsPerMonth = Ertr\u00E4ge pro Monat LabelEarningsPerQuarter = Ertr\u00E4ge pro Quartal @@ -2624,23 +2644,3 @@ WatchlistRename = Watchliste umbenennen Website = Website YearlyPerformanceHeatmapToolTip = Jahresrenditen in einer Heatmap\n\nZur Berechnung der Jahresrendite wird der True-Time Weighted Rate of Return (TTWROR) herangezogen.\n\nDie Rendite bezieht sich immer auf das gesamte Jahr - selbst wenn der Berichtszeitraum in der Mitte des Jahres beginnt bzw. endet. - -LabelEarningsDividendList = \u00DCbersicht anstehender Dividenden - -LabelEarningsDividendPeriodFrom = Zeitraum ab - -LabelEarningsDividendPeriodUntil = Zeitraum bis - -LabelEarningsDividendDateType = Datumsart - -ColumnDividendsNextExDate = Div Ex. Tag - -ColumnDividendsNextExDate_MenuLabel = Nächster Ex-Dividendentag - -ColumnDividendsNextPaymentDate = Div. Zahltag - -ColumnDividendsNextPaymentDate_MenuLabel = Nächster Dividenden Zahltag - -ColumnDividendsNextPaymentAmount = Div. Betrag - -ColumnDividendsNextPaymentAmount_MenuLabel = Nächster Dividendenbetrag diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_es.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_es.properties index 90b4529661..e3dc432dd5 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_es.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_es.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = Ratio de Retorno de dividendo = Suma de ingresos por dividendo / valor de compra basado en FIFO\n\nAtenci\u00F3n: Si alguna accion se ha vendido tras el pago de dividendo, este pago no se reduce. El Ratio de Retorno puede sobreestimarse. +ColumnDividendsNextExDate = Siguiente ex-d\u00EDa + +ColumnDividendsNextExDate_MenuLabel = Pr\u00F3ximo D\u00EDa Ex-Dividendo + +ColumnDividendsNextPaymentAmount = Importe del Pr\u00F3ximo Dividendo + +ColumnDividendsNextPaymentAmount_MenuLabel = Importe del Pr\u00F3ximo Dividendo + +ColumnDividendsNextPaymentDate = Pr\u00F3xima Fecha de Pago de Dividendos + +ColumnDividendsNextPaymentDate_MenuLabel = Pr\u00F3xima Fecha de Pago de Dividendos + ColumnEarnings = Ganancias ColumnEarnings_Description = Dividendo + Intereses diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_fr.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_fr.properties index 7a44445add..cffec63029 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_fr.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_fr.properties @@ -388,6 +388,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = Taux de rendement du dividende = somme des dividendes per\u00E7us / valeur d'achat (FIFO)\n\nAttention : si des parts sont vendues apr\u00E8s versement d'un dividende, alors le dividende n'est pas r\u00E9duit. Dans ce cas, le taux de rendement peut \u00EAtre surestim\u00E9. +ColumnDividendsNextExDate = Prochaine Date Ex-Dividende (d\u00E9tachement) + +ColumnDividendsNextExDate_MenuLabel = Prochain Jour Ex-Dividende + +ColumnDividendsNextPaymentAmount = Montant du Prochain Dividende + +ColumnDividendsNextPaymentAmount_MenuLabel = Montant du Prochain Dividende + +ColumnDividendsNextPaymentDate = Prochaine Date de Paiement du Dividende + +ColumnDividendsNextPaymentDate_MenuLabel = Prochaine Date de Paiement du Dividende + ColumnEarnings = B\u00E9n\u00E9fices ColumnEarnings_Description = Dividendes + Int\u00E9r\u00EAts diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_it.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_it.properties index b050b4091c..8a14a1e898 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_it.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_it.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = tasso di rendimento dei dividendi (ROR) = somma dei pagamenti del dividendo / valore d'acquisto basato su FIFO\n\nAttenzione: se le azioni vengono vendute dopo il pagamento di un dividendo, il pagamento del dividendo non viene ridotto. Pertanto il tasso di rendimento potrebbe essere sovrastimato. +ColumnDividendsNextExDate = Prossima Ex-Date + +ColumnDividendsNextExDate_MenuLabel = Prossimo Giorno di Stacco del Dividendo + +ColumnDividendsNextPaymentAmount = Importo del Prossimo Dividendo + +ColumnDividendsNextPaymentAmount_MenuLabel = Importo del Prossimo Dividendo + +ColumnDividendsNextPaymentDate = Data di Pagamento del Prossimo Dividendo + +ColumnDividendsNextPaymentDate_MenuLabel = Data di Pagamento del Prossimo Dividendo + ColumnEarnings = Profitti ColumnEarnings_Description = Dividendi + pagamenti interessi diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_nl.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_nl.properties index 0c2039f020..c4d5797bd3 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_nl.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_nl.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = Het dividendrendement = (som van Dividend) / Aankoopwaarde op basis van FIFO.\n\nLet op: als aandelen na een dividenduitkering worden verkocht, wordt het dividend niet verlaagd. Daarom kan het rendement worden overschat. +ColumnDividendsNextExDate = Volgende Ex-datum + +ColumnDividendsNextExDate_MenuLabel = Volgende Ex-Dividenddag + +ColumnDividendsNextPaymentAmount = Volgende Dividendbedrag + +ColumnDividendsNextPaymentAmount_MenuLabel = Volgende Dividendbedrag + +ColumnDividendsNextPaymentDate = Volgende Dividend Betaaldatum + +ColumnDividendsNextPaymentDate_MenuLabel = Volgende Dividend Betaaldatum + ColumnEarnings = Opbrengsten ColumnEarnings_Description = Dividenduitkeringen en Interestbetalingen diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pl.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pl.properties index 54719d54cf..4696bab5da 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pl.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pl.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = stopa zwrotu dywidendy = suma wyp\u0142at dywidendy / warto\u015B\u0107 zakupu na podstawie FIFO\n\nUwaga: je\u015Bli akcje zostan\u0105 sprzedane po wyp\u0142acie dywidendy, wyp\u0142ata dywidendy nie zostanie zmniejszona. Dlatego stopa zwrotu mo\u017Ce by\u0107 przeszacowana. +ColumnDividendsNextExDate = Nast\u0119pne Ex-Date + +ColumnDividendsNextExDate_MenuLabel = Nast\u0119pny Dzie\u0144 Ustalenia Prawa do Dywidendy + +ColumnDividendsNextPaymentAmount = Nast\u0119pna Kwota Dywidendy + +ColumnDividendsNextPaymentAmount_MenuLabel = Nast\u0119pna Kwota Dywidendy + +ColumnDividendsNextPaymentDate = Nast\u0119pny Dzie\u0144 Wyp\u0142aty Dywidendy + +ColumnDividendsNextPaymentDate_MenuLabel = Nast\u0119pny Dzie\u0144 Wyp\u0142aty Dywidendy + ColumnEarnings = Zarobki ColumnEarnings_Description = Dywidendy + P\u0142atno\u015Bci odsetek diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt.properties index 4ff8e42771..ea0260a04b 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = taxa de retorno de dividendos = soma dos pagamentos de dividendos / valor da compra com base no FIFO\n\nAten\u00E7\u00E3o: se as a\u00E7\u00F5es forem vendidas ap\u00F3s o pagamento de dividendos, o pagamento de dividendos n\u00E3o ser\u00E1 reduzido. Portanto, a taxa de retorno pode estar superestimada. +ColumnDividendsNextExDate = Pr\u00F3xima Data EX + +ColumnDividendsNextExDate_MenuLabel = Pr\u00F3ximo Dia Ex-Dividendo + +ColumnDividendsNextPaymentAmount = Montante do Pr\u00F3ximo Dividendo + +ColumnDividendsNextPaymentAmount_MenuLabel = Montante do Pr\u00F3ximo Dividendo + +ColumnDividendsNextPaymentDate = Pr\u00F3xima Data de Pagamento de Dividendos + +ColumnDividendsNextPaymentDate_MenuLabel = Pr\u00F3xima Data de Pagamento de Dividendos + ColumnEarnings = Lucros ColumnEarnings_Description = Dividendos + Pagamento de Juros diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt_BR.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt_BR.properties index f853e50c29..74dfbb955d 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt_BR.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_pt_BR.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = taxa de retorno de dividendos = soma dos pagamentos de dividendos / valor da compra com base no FIFO\n\nAten\u00E7\u00E3o: se as posi\u00E7\u00F5es forem vendidas ap\u00F3s o pagamento de dividendos, o pagamento de dividendos n\u00E3o ser\u00E1 reduzido. Portanto, a taxa de retorno pode estar superestimada. +ColumnDividendsNextExDate = Pr\u00F3xima Data EX + +ColumnDividendsNextExDate_MenuLabel = Pr\u00F3ximo Dia Ex-Dividendo + +ColumnDividendsNextPaymentAmount = Valor do Pr\u00F3ximo Dividendo + +ColumnDividendsNextPaymentAmount_MenuLabel = Valor do Pr\u00F3ximo Dividendo + +ColumnDividendsNextPaymentDate = Pr\u00F3xima Data de Pagamento de Dividendos + +ColumnDividendsNextPaymentDate_MenuLabel = Pr\u00F3xima Data de Pagamento de Dividendos + ColumnEarnings = Lucros ColumnEarnings_Description = Dividendos + Pagamento de Juros diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_ru.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_ru.properties index 668e4c6403..82320f720c 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_ru.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_ru.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = \u0414\u0438\u0432% ColumnDividendTotalRateOfReturn_Description = \u0434\u043E\u0445\u043E\u0434\u043D\u043E\u0441\u0442\u044C \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u043E\u0432 = \u0441\u0443\u043C\u043C\u0430 \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u043D\u044B\u0445 \u0432\u044B\u043F\u043B\u0430\u0442 / \u043F\u043E\u043A\u0443\u043F\u043D\u0430\u044F \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C \u043D\u0430 \u043E\u0441\u043D\u043E\u0432\u0435 FIFO\n\n\u0412\u043D\u0438\u043C\u0430\u043D\u0438\u0435: \u0435\u0441\u043B\u0438 \u0430\u043A\u0446\u0438\u0438 \u043F\u0440\u043E\u0434\u0430\u044E\u0442\u0441\u044F \u043F\u043E\u0441\u043B\u0435 \u0432\u044B\u043F\u043B\u0430\u0442\u044B \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u043E\u0432, \u0442\u043E \u0440\u0430\u0437\u043C\u0435\u0440 \u0432\u044B\u043F\u043B\u0430\u0442\u044B \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u043E\u0432 \u043D\u0435 \u0443\u043C\u0435\u043D\u044C\u0448\u0430\u0435\u0442\u0441\u044F. \u0421\u043B\u0435\u0434\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u043D\u043E, \u043D\u043E\u0440\u043C\u0430 \u043F\u0440\u0438\u0431\u044B\u043B\u0438 \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u0437\u0430\u0432\u044B\u0448\u0435\u043D\u0430. +ColumnDividendsNextExDate = \u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0435 \u042D\u043A\u0441-\u0434\u0430\u0442\u0430 + +ColumnDividendsNextExDate_MenuLabel = \u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0434\u0435\u043D\u044C \u044D\u043A\u0441-\u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u043E\u0432 + +ColumnDividendsNextPaymentAmount = \u0421\u0443\u043C\u043C\u0430 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u0430 + +ColumnDividendsNextPaymentAmount_MenuLabel = \u0421\u0443\u043C\u043C\u0430 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u0430 + +ColumnDividendsNextPaymentDate = \u0414\u0430\u0442\u0430 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0439 \u0432\u044B\u043F\u043B\u0430\u0442\u044B \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u043E\u0432 + +ColumnDividendsNextPaymentDate_MenuLabel = \u0414\u0430\u0442\u0430 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0439 \u0432\u044B\u043F\u043B\u0430\u0442\u044B \u0434\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u043E\u0432 + ColumnEarnings = \u041F\u0440\u0438\u0431\u044B\u043B\u044C ColumnEarnings_Description = \u0414\u0438\u0432\u0438\u0434\u0435\u043D\u0434\u044B + \u043F\u0440\u043E\u0446\u0435\u043D\u0442\u043D\u044B\u0435 \u0432\u044B\u043F\u043B\u0430\u0442\u044B diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_sk.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_sk.properties index cbccdb24e1..c3cb73db1c 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_sk.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_sk.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = Div% ColumnDividendTotalRateOfReturn_Description = Miera v\u00FDnosnosti dividend = suma vyplaten\u00FDch dividend / n\u00E1kupn\u00E1 hodnota na z\u00E1klade FIFO\n\nPozor: ak sa akcie predaj\u00FA po v\u00FDplate dividend, v\u00FDplata dividend sa nezni\u017Euje. Preto m\u00F4\u017Ee by\u0165 miera v\u00FDnosnosti nadhodnoten\u00E1. +ColumnDividendsNextExDate = Nasleduj\u00FAci de\u0148 ex-day + +ColumnDividendsNextExDate_MenuLabel = Nasleduj\u00FAci de\u0148 Ex-Dividend + +ColumnDividendsNextPaymentAmount = Nasleduj\u00FAca Suma Dividend + +ColumnDividendsNextPaymentAmount_MenuLabel = Nasleduj\u00FAca Suma Dividend + +ColumnDividendsNextPaymentDate = D\u00E1tum Nasleduj\u00FAcej V\u00FDplaty Dividend + +ColumnDividendsNextPaymentDate_MenuLabel = D\u00E1tum Nasleduj\u00FAcej V\u00FDplaty Dividend + ColumnEarnings = V\u00FDnosy ColumnEarnings_Description = Dividendy + platby \u00FArokov diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh.properties index ab6454c793..c556889e71 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = \u80A1\u606F\u7387 % ColumnDividendTotalRateOfReturn_Description = \u80A1\u606F\u6536\u76CA\u7387 = \u603B\u80A1\u606F / \u5148\u8FDB\u5148\u51FA\u6210\u672C\n\n\u6CE8\u610F\uFF1A\u6D3E\u606F\u540E\u5356\u51FA\u7684\u80A1\u7968\u4E4B\u80A1\u606F\u4E0D\u4F1A\u88AB\u51CF\u53BB\u3002\u56E0\u6B64\uFF0C\u6B64\u6536\u76CA\u7387\u53EF\u80FD\u88AB\u9AD8\u4F30\u3002 +ColumnDividendsNextExDate = \u4E0B\u4E00\u500B\u9664\u606F\u65E5 + +ColumnDividendsNextExDate_MenuLabel = \u4E0B\u4E00\u4E2A\u9664\u606F\u65E5 + +ColumnDividendsNextPaymentAmount = \u4E0B\u4E00\u6B21\u5206\u7EA2\u91D1\u989D + +ColumnDividendsNextPaymentAmount_MenuLabel = \u4E0B\u4E00\u6B21\u5206\u7EA2\u91D1\u989D + +ColumnDividendsNextPaymentDate = \u4E0B\u4E00\u6B21\u80A1\u606F\u652F\u4ED8\u65E5\u671F + +ColumnDividendsNextPaymentDate_MenuLabel = \u4E0B\u4E00\u6B21\u80A1\u606F\u652F\u4ED8\u65E5\u671F + ColumnEarnings = \u6536\u5165 ColumnEarnings_Description = \u80A1\u606F + \u5229\u606F diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh_TW.properties b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh_TW.properties index 01c90c91c5..b2492a5ca2 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh_TW.properties +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/messages_zh_TW.properties @@ -387,6 +387,18 @@ ColumnDividendTotalRateOfReturn = \u80A1\u606F\u7387 ColumnDividendTotalRateOfReturn_Description = \u7D05\u5229\u56DE\u5831\u7387 = \u80A1\u606F\u652F\u4ED8\u4E4B\u548C / \u57FA\u65BCFIFO\u7684\u8CFC\u8CB7\u50F9\u503C\u4E4B\u548C\n\n\u6CE8\u610F\uFF1A\u5982\u679C\u5728\u80A1\u606F\u652F\u4ED8\u5F8C\u51FA\u552E\u80A1\u4EFD\uFF0C\u5247\u4E0D\u6703\u6E1B\u5C11\u80A1\u606F\u652F\u4ED8\u3002\u56E0\u6B64\uFF0C\u56DE\u5831\u7387\u53EF\u80FD\u88AB\u9AD8\u4F30\u3002 +ColumnDividendsNextExDate = \u4E0B\u4E00\u500B\u9664\u606F\u65E5 + +ColumnDividendsNextExDate_MenuLabel = \u4E0B\u4E00\u4E2A\u9664\u606F\u65E5 + +ColumnDividendsNextPaymentAmount = \u4E0B\u4E00\u6B21\u5206\u7EA2\u91D1\u989D + +ColumnDividendsNextPaymentAmount_MenuLabel = \u4E0B\u4E00\u6B21\u5206\u7EA2\u91D1\u989D + +ColumnDividendsNextPaymentDate = \u4E0B\u4E00\u6B21\u80A1\u606F\u652F\u4ED8\u65E5\u671F + +ColumnDividendsNextPaymentDate_MenuLabel = \u4E0B\u4E00\u6B21\u80A1\u606F\u652F\u4ED8\u65E5\u671F + ColumnEarnings = \u6536\u76CA ColumnEarnings_Description = \u80A1\u606F + \u5229\u606F\u652F\u4ED8 From f4e563d2f4ce8f86e2a0117e30bf3263def60081 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Mon, 15 Apr 2024 18:59:29 +0200 Subject: [PATCH 09/12] show list of date types instead of single entries if ex-date and payment date are the same. Fixed wrong coloring for ex-date (should be red) and payment date (should be green). --- .../dashboard/DividendListWidgetTest.java | 83 +++++++++++-------- .../views/columns/DividendPaymentColumn.java | 10 +-- .../views/dashboard/DividendListWidget.java | 64 +++++++++++--- 3 files changed, 108 insertions(+), 49 deletions(-) diff --git a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java index a4914d77d4..a41f3e6bc2 100644 --- a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java +++ b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java @@ -38,6 +38,7 @@ public class DividendListWidgetTest private DividendEvent de1_2; private SecurityEvent de1_3; private DividendEvent de1_4; + private DividendEvent de1_5; private DividendEvent de2_1; private DividendEvent de2_2; private SecurityEvent de2_3; @@ -64,6 +65,7 @@ public void setupTestData() de1_2 = new DividendEvent(LocalDate.of(2024, 7, 14), LocalDate.of(2024, 8, 11), Money.of("EUR", 22), "source"); de1_3 = new SecurityEvent(LocalDate.of(2024, 2, 3), SecurityEvent.Type.NOTE, "some note"); de1_4 = new DividendEvent(LocalDate.of(2024, 2, 4), LocalDate.of(2024, 3, 5), Money.of("EUR", 33), "source"); + de1_5 = new DividendEvent(LocalDate.of(2024, 8, 1), LocalDate.of(2024, 8, 1), Money.of("EUR", 33), "source"); sec1.addEvent(de1_1); sec1.addEvent(de1_2); sec1.addEvent(de1_3); @@ -88,7 +90,7 @@ public void testDividendItemInstantiation() di = new DividendItem(DateType.EX_DIVIDEND_DATE, sec1, de1_1); assertThat(di.getSecurity(), is(sec1)); - assertThat(di.type, is(DateType.EX_DIVIDEND_DATE)); + assertThat(di.getFirstType(), is(DateType.EX_DIVIDEND_DATE)); assertThat(di.div, is(de1_1)); } @@ -185,8 +187,8 @@ List getSecurities() LocalDate now = LocalDate.of(2024, 4, 9); list = widget.getUpdateTask(now).get(); - assertEquals("2024-04-09 Security 1 EUR 0,55 " + Messages.ColumnExDate + "\r\n" // - + "Security 2 USD 0,55 " + Messages.ColumnPaymentDate, getListAsString(list)); + assertEquals("2024-04-09 Security 1 EUR 0,55 [" + Messages.ColumnExDate + "]\r\n" // + + "Security 2 USD 0,55 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); now = LocalDate.of(2024, 4, 8); list = widget.getUpdateTask(now).get(); @@ -194,44 +196,57 @@ List getSecurities() dateStart.set(DateStartRange.FROM_YTD); list = widget.getUpdateTask(now).get(); - assertEquals("2024-02-04 Security 1 EUR 0,33 " + Messages.ColumnExDate + "\r\n" // - + "2024-02-05 Security 2 USD 13,33 " + Messages.ColumnExDate + "\r\n" // - + "2024-03-05 Security 1 EUR 0,33 " + Messages.ColumnPaymentDate + "\r\n" // - + "Security 2 USD 13,33 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-04-05 Security 2 USD 0,55 " + Messages.ColumnExDate, getListAsString(list)); + assertEquals("2024-02-04 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-02-05 Security 2 USD 13,33 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-03-05 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "Security 2 USD 13,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-04-05 Security 2 USD 0,55 [" + Messages.ColumnExDate + "]", getListAsString(list)); dateEnd.set(DateEndRange.UNTIL_EOY); list = widget.getUpdateTask(now).get(); - assertEquals("2024-02-04 Security 1 EUR 0,33 " + Messages.ColumnExDate + "\r\n" // - + "2024-02-05 Security 2 USD 13,33 " + Messages.ColumnExDate + "\r\n" // - + "2024-03-05 Security 1 EUR 0,33 " + Messages.ColumnPaymentDate + "\r\n" // - + "Security 2 USD 13,33 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-04-05 Security 2 USD 0,55 " + Messages.ColumnExDate + "\r\n" // - + "2024-04-09 Security 1 EUR 0,55 " + Messages.ColumnExDate + "\r\n" // - + "Security 2 USD 0,55 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-04-12 Security 1 EUR 0,55 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-07-14 Security 1 EUR 0,22 " + Messages.ColumnExDate + "\r\n" // - + "Security 2 USD 1,22 " + Messages.ColumnExDate + "\r\n" // - + "2024-07-15 Security 2 USD 1,22 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-08-11 Security 1 EUR 0,22 " + Messages.ColumnPaymentDate, getListAsString(list)); + assertEquals("2024-02-04 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-02-05 Security 2 USD 13,33 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-03-05 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "Security 2 USD 13,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-04-05 Security 2 USD 0,55 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-04-09 Security 1 EUR 0,55 [" + Messages.ColumnExDate + "]\r\n" // + + "Security 2 USD 0,55 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-04-12 Security 1 EUR 0,55 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-07-14 Security 1 EUR 0,22 [" + Messages.ColumnExDate + "]\r\n" // + + "Security 2 USD 1,22 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-07-15 Security 2 USD 1,22 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-08-11 Security 1 EUR 0,22 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); dateType.set(DateType.EX_DIVIDEND_DATE); list = widget.getUpdateTask(now).get(); - assertEquals("2024-02-04 Security 1 EUR 0,33 " + Messages.ColumnExDate + "\r\n" // - + "2024-02-05 Security 2 USD 13,33 " + Messages.ColumnExDate + "\r\n" // - + "2024-04-05 Security 2 USD 0,55 " + Messages.ColumnExDate + "\r\n" // - + "2024-04-09 Security 1 EUR 0,55 " + Messages.ColumnExDate + "\r\n" // - + "2024-07-14 Security 1 EUR 0,22 " + Messages.ColumnExDate + "\r\n" // - + "Security 2 USD 1,22 " + Messages.ColumnExDate, getListAsString(list)); + assertEquals("2024-02-04 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-02-05 Security 2 USD 13,33 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-04-05 Security 2 USD 0,55 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-04-09 Security 1 EUR 0,55 [" + Messages.ColumnExDate + "]\r\n" // + + "2024-07-14 Security 1 EUR 0,22 [" + Messages.ColumnExDate + "]\r\n" // + + "Security 2 USD 1,22 [" + Messages.ColumnExDate + "]", getListAsString(list)); dateType.set(DateType.PAYMENT_DATE); list = widget.getUpdateTask(now).get(); - assertEquals("2024-03-05 Security 1 EUR 0,33 " + Messages.ColumnPaymentDate + "\r\n" // - + "Security 2 USD 13,33 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-04-09 Security 2 USD 0,55 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-04-12 Security 1 EUR 0,55 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-07-15 Security 2 USD 1,22 " + Messages.ColumnPaymentDate + "\r\n" // - + "2024-08-11 Security 1 EUR 0,22 " + Messages.ColumnPaymentDate, getListAsString(list)); + assertEquals("2024-03-05 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "Security 2 USD 13,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-04-09 Security 2 USD 0,55 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-04-12 Security 1 EUR 0,55 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-07-15 Security 2 USD 1,22 [" + Messages.ColumnPaymentDate + "]\r\n" // + + "2024-08-11 Security 1 EUR 0,22 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); + + sec1.getEvents().clear(); + sec2.getEvents().clear(); + sec1.addEvent(de1_5); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-08-01 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); + dateType.set(DateType.EX_DIVIDEND_DATE); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-08-01 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]", getListAsString(list)); + dateType.set(DateType.ALL_DATES); + list = widget.getUpdateTask(now).get(); + assertEquals("2024-08-01 Security 1 EUR 0,33 [" + Messages.ColumnExDate + ", " + Messages.ColumnPaymentDate + + "]", getListAsString(list)); } private String getListAsString(List list) @@ -241,11 +256,11 @@ private String getListAsString(List list) StringBuilder sb = new StringBuilder(); if (entry.hasNewDate) { - sb.append(entry.type.getDate(entry.div).toString() + " "); + sb.append(entry.getFirstType().getDate(entry.div).toString() + " "); } sb.append(entry.getSecurity().getName() + " "); sb.append(entry.div.getAmount() + " "); - sb.append(entry.type); + sb.append(entry.types); return sb.toString(); }) // .collect(Collectors.joining("\r\n")); diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java index a72e0a2af6..bf2d8bbb62 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -41,7 +41,7 @@ static Column createNextDividendExDateColumn() .filter(DividendEvent.class::isInstance) // .map(e -> ((DividendEvent) e).getDate()) // .sorted(Comparable::compareTo) // - .filter(d -> d.isAfter(now)) // + .filter(d -> !now.isAfter(d)) // .findFirst().orElse(null); }; @@ -56,7 +56,7 @@ public Color getBackground(Object element) return null; // } - return Colors.theme().greenBackground(); + return Colors.theme().redBackground(); } }); column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); @@ -82,7 +82,7 @@ static Column createNextDividendPaymentDateColumn() .filter(DividendEvent.class::isInstance) // .map(e -> ((DividendEvent) e).getPaymentDate()) // .sorted(Comparable::compareTo) // - .filter(d -> d.isAfter(now)) // + .filter(d -> !now.isAfter(d)) // .findFirst().orElse(null); }; @@ -97,7 +97,7 @@ public Color getBackground(Object element) return null; // } - return Colors.theme().redBackground(); + return Colors.theme().greenBackground(); } }); column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); @@ -150,7 +150,7 @@ static Money getAmount(LocalDate now, Security sec) .filter(e -> e instanceof DividendEvent) // .map(e -> (DividendEvent) e) // .sorted((e1, e2) -> e1.getPaymentDate().compareTo(e2.getPaymentDate())) // - .filter(d -> d.getPaymentDate().isAfter(now)) // + .filter(d -> !now.isAfter(d.getPaymentDate())) // .map(DividendEvent::getAmount).findFirst().orElse(null); } diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java index d29db8a683..89c98c5094 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java @@ -4,10 +4,14 @@ import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; +import java.util.Deque; +import java.util.LinkedList; import java.util.List; import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; +import java.util.stream.Collectors; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; @@ -31,14 +35,19 @@ public class DividendListWidget extends AbstractSecurityListWidget types = new LinkedList<>(); DividendEvent div; public DividendItem(DateType type, Security security, DividendEvent div) { super(security); this.div = div; - this.type = type; + this.types.add(type); + } + + DateType getFirstType() + { + return types.peekFirst(); } } @@ -198,16 +207,19 @@ Supplier> getUpdateTask(LocalDate now) { continue; } - checkAndAdd(items, security, de, dateType, DateType.EX_DIVIDEND_DATE, fromDate, untilDate); - checkAndAdd(items, security, de, dateType, DateType.PAYMENT_DATE, fromDate, untilDate); + DividendItem added = checkAndAdd(items, security, de, dateType, DateType.EX_DIVIDEND_DATE, fromDate, + untilDate, null); + checkAndAdd(items, security, de, dateType, DateType.PAYMENT_DATE, fromDate, untilDate, added); } } - Collections.sort(items, (di1, di2) -> di1.type.getDate(di1.div).compareTo(di2.type.getDate(di2.div))); + Collections.sort(items, new DividendItemComparator()); LocalDate prevDate = null; + DividendItem prevItem = null; for (DividendItem item : items) { - LocalDate currDate = item.type.getDate(item.div); + prevItem = item; + LocalDate currDate = item.getFirstType().getDate(item.div); if (prevDate == null || !currDate.isEqual(prevDate)) { item.hasNewDate = true; @@ -220,6 +232,28 @@ Supplier> getUpdateTask(LocalDate now) }; } + static class DividendItemComparator implements Comparator + { + + @Override + public int compare(DividendItem di1, DividendItem di2) + { + DateType type1 = di1.getFirstType(); + DateType type2 = di2.getFirstType(); + int ret = type1.getDate(di1.div).compareTo(type2.getDate(di2.div)); + if (ret != 0) + { + return ret; // + } + ret = String.CASE_INSENSITIVE_ORDER.compare(di1.getSecurity().getName(), di2.getSecurity().getName()); + if (ret != 0) + { + return ret; // + } + return type1.compareTo(type2); + } + } + DateStartRange getStartRangeValue() { return get(DateStartRangeConfig.class).getValue(); @@ -241,7 +275,7 @@ List getSecurities() } DividendItem checkAndAdd(List items, Security sec, DividendEvent de, DateType configuredType, - DateType typeToAdd, LocalDate startRange, LocalDate endRange) + DateType typeToAdd, LocalDate startRange, LocalDate endRange, DividendItem prevAdded) { if (configuredType != typeToAdd && configuredType != DateType.ALL_DATES) { @@ -260,7 +294,14 @@ DividendItem checkAndAdd(List items, Security sec, DividendEvent d } DividendItem ret = new DividendItem(typeToAdd, sec, de); - items.add(ret); + if (prevAdded != null && checkDate.equals(prevAdded.types.peekLast().getDate(de))) + { + prevAdded.types.add(typeToAdd); + } + else + { + items.add(ret); + } return ret; } @@ -274,15 +315,18 @@ protected Composite createItemControl(Composite parent, DividendItem item) Image image = LogoManager.instance().getDefaultColumnImage(sec, getClient().getSettings()); Label logo = createLabel(composite, image); Label name = createLabel(composite, sec.getName()); + String typeStr = item.types.stream() // + .map(dt -> dt.label) // + .collect(Collectors.joining(", ")); Label amtAndType = createLabel(composite, - " " + Values.Money.format(item.div.getAmount()) + " " + item.type.label); //$NON-NLS-1$ //$NON-NLS-2$ + " " + Values.Money.format(item.div.getAmount()) + " " + typeStr); //$NON-NLS-1$ //$NON-NLS-2$ Label date = null; if (item.hasNewDate) { - date = createLabel(composite, Values.Date.format(item.type.getDate(item.div))); + date = createLabel(composite, Values.Date.format(item.getFirstType().getDate(item.div))); } addListener(mouseUpAdapter, composite, name, date, amtAndType); From ef358373780a6e86882bb04aaeaeb21a6d99a435 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Wed, 1 May 2024 14:50:29 +0200 Subject: [PATCH 10/12] Redesign of the widget to allow more entries to be shown. Show ellipses if the number of entries exceed the maximum number of "allowed" securities. Use color coding to show the different event types and make the date more prominent --- .../dashboard/DividendListWidgetTest.java | 64 ++++-- .../META-INF/MANIFEST.MF | 3 +- .../dashboard/AbstractSecurityListWidget.java | 95 ++++++--- .../views/dashboard/DividendListWidget.java | 197 ++++++++++++------ .../ui/views/dashboard/WidgetFactory.java | 2 +- 5 files changed, 253 insertions(+), 108 deletions(-) diff --git a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java index a41f3e6bc2..2d3edce6df 100644 --- a/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java +++ b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java @@ -7,10 +7,13 @@ import java.time.LocalDate; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.junit.AfterClass; @@ -28,6 +31,7 @@ import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DateType; import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DividendItem; +@SuppressWarnings("nls") public class DividendListWidgetTest { private static Locale defaultLocale; @@ -97,7 +101,7 @@ public void testDividendItemInstantiation() @Test public void testDateStartRange() { - assertEquals("FROM_TODAY,FROM_ONE_WEEK,FROM_ONE_MONTH,FROM_YTD", // + assertEquals("FROM_TODAY,FROM_ONE_WEEK,FROM_ONE_MONTH,FROM_QUARTER", // Arrays.stream(DateStartRange.values()) .map(DateStartRange::name).collect(Collectors.joining(","))); @@ -105,13 +109,13 @@ public void testDateStartRange() assertThat(DateStartRange.FROM_TODAY.getDate(now), is(now)); assertThat(DateStartRange.FROM_ONE_WEEK.getDate(now), is(LocalDate.of(2024, 4, 1))); assertThat(DateStartRange.FROM_ONE_MONTH.getDate(now), is(LocalDate.of(2024, 3, 8))); - assertThat(DateStartRange.FROM_YTD.getDate(now), is(LocalDate.of(2024, 1, 1))); + assertThat(DateStartRange.FROM_QUARTER.getDate(now), is(LocalDate.of(2024, 1, 8))); } @Test public void testDateEndRange() { - assertEquals("UNTIL_EOY,UNTIL_ONE_MONTH,UNTIL_ONE_WEEK,UNTIL_TODAY", // + assertEquals("UNTIL_ALL,UNTIL_EOY,UNTIL_ONE_MONTH,UNTIL_ONE_WEEK,UNTIL_TODAY", // Arrays.stream(DateEndRange.values()).map(DateEndRange::name).collect(Collectors.joining(","))); LocalDate now = LocalDate.of(2024, 4, 8); @@ -119,6 +123,7 @@ public void testDateEndRange() assertThat(DateEndRange.UNTIL_ONE_WEEK.getDate(now), is(LocalDate.of(2024, 4, 15))); assertThat(DateEndRange.UNTIL_ONE_MONTH.getDate(now), is(LocalDate.of(2024, 5, 8))); assertThat(DateEndRange.UNTIL_EOY.getDate(now), is(LocalDate.of(2024, 12, 31))); + assertThat(DateEndRange.UNTIL_ALL.getDate(now), nullValue()); } @Test @@ -136,17 +141,16 @@ public void testDateType() public void testGetUpdateTask() throws Exception { LocalDate testnow = LocalDate.now(); - @SuppressWarnings("deprecation") AbstractSecurityListWidget widget = new DividendListWidget() { @Override - public Supplier> getUpdateTask(LocalDate now) + public List getUpdateTask(LocalDate now) { assertThat(now, is(testnow)); return null; } }; - assertThat(widget.getUpdateTask(), nullValue()); + assertThat(widget.getUpdateTask().get(), nullValue()); } @Test @@ -156,8 +160,8 @@ public void testGetUpdateTaskNow() AtomicReference dateStart = new AtomicReference<>(DateStartRange.FROM_TODAY); AtomicReference dateEnd = new AtomicReference<>(DateEndRange.UNTIL_TODAY); AtomicReference dateType = new AtomicReference<>(DateType.ALL_DATES); + AtomicBoolean showSecurities = new AtomicBoolean(true); - @SuppressWarnings("deprecation") DividendListWidget widget = new DividendListWidget() { @Override @@ -183,19 +187,37 @@ List getSecurities() { return Arrays.asList(sec1, sec2); } - }; + @Override + ClientFilterConfig getClientFilterConfig() + { + return null; + } + + @Override + Set getSecuritiesToShow(ClientFilterConfig clientFilter) + { + if (showSecurities.get()) + { + HashSet ret = new HashSet<>(); + ret.addAll(getSecurities()); + return ret; + } + return Collections.emptySet(); + } + }; + LocalDate now = LocalDate.of(2024, 4, 9); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("2024-04-09 Security 1 EUR 0,55 [" + Messages.ColumnExDate + "]\r\n" // + "Security 2 USD 0,55 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); now = LocalDate.of(2024, 4, 8); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("", getListAsString(list)); - dateStart.set(DateStartRange.FROM_YTD); - list = widget.getUpdateTask(now).get(); + dateStart.set(DateStartRange.FROM_QUARTER); + list = widget.getUpdateTask(now); assertEquals("2024-02-04 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]\r\n" // + "2024-02-05 Security 2 USD 13,33 [" + Messages.ColumnExDate + "]\r\n" // + "2024-03-05 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]\r\n" // @@ -203,7 +225,7 @@ List getSecurities() + "2024-04-05 Security 2 USD 0,55 [" + Messages.ColumnExDate + "]", getListAsString(list)); dateEnd.set(DateEndRange.UNTIL_EOY); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("2024-02-04 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]\r\n" // + "2024-02-05 Security 2 USD 13,33 [" + Messages.ColumnExDate + "]\r\n" // + "2024-03-05 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]\r\n" // @@ -218,7 +240,7 @@ List getSecurities() + "2024-08-11 Security 1 EUR 0,22 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); dateType.set(DateType.EX_DIVIDEND_DATE); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("2024-02-04 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]\r\n" // + "2024-02-05 Security 2 USD 13,33 [" + Messages.ColumnExDate + "]\r\n" // + "2024-04-05 Security 2 USD 0,55 [" + Messages.ColumnExDate + "]\r\n" // @@ -227,7 +249,7 @@ List getSecurities() + "Security 2 USD 1,22 [" + Messages.ColumnExDate + "]", getListAsString(list)); dateType.set(DateType.PAYMENT_DATE); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("2024-03-05 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + "Security 2 USD 13,33 [" + Messages.ColumnPaymentDate + "]\r\n" // + "2024-04-09 Security 2 USD 0,55 [" + Messages.ColumnPaymentDate + "]\r\n" // @@ -238,15 +260,19 @@ List getSecurities() sec1.getEvents().clear(); sec2.getEvents().clear(); sec1.addEvent(de1_5); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("2024-08-01 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); dateType.set(DateType.EX_DIVIDEND_DATE); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("2024-08-01 Security 1 EUR 0,33 [" + Messages.ColumnExDate + "]", getListAsString(list)); dateType.set(DateType.ALL_DATES); - list = widget.getUpdateTask(now).get(); + list = widget.getUpdateTask(now); assertEquals("2024-08-01 Security 1 EUR 0,33 [" + Messages.ColumnExDate + ", " + Messages.ColumnPaymentDate + "]", getListAsString(list)); + + showSecurities.set(false); + list = widget.getUpdateTask(now); + assertEquals("", getListAsString(list)); } private String getListAsString(List list) diff --git a/name.abuchen.portfolio.ui/META-INF/MANIFEST.MF b/name.abuchen.portfolio.ui/META-INF/MANIFEST.MF index aefb6e5788..105ed20358 100644 --- a/name.abuchen.portfolio.ui/META-INF/MANIFEST.MF +++ b/name.abuchen.portfolio.ui/META-INF/MANIFEST.MF @@ -7,7 +7,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-Activator: name.abuchen.portfolio.ui.PortfolioPlugin Bundle-Vendor: Andreas Buchen -Import-Package: com.google.common.base, +Import-Package: com.google.common.annotations, + com.google.common.base, com.google.common.collect, com.google.common.primitives, com.google.gson, diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java index 65ea0c856f..568a70fb28 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/AbstractSecurityListWidget.java @@ -13,6 +13,7 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; @@ -90,6 +91,32 @@ public Composite createControl(Composite parent, DashboardResources resources) container.setBackground(parent.getBackground()); GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5).applyTo(container); + createTitleArea(container); + + list = new Composite(container, SWT.NONE); + RowLayout layout = new RowLayout(SWT.VERTICAL); + layout.marginLeft = 0; + layout.marginRight = 0; + layout.marginTop = 0; + layout.marginBottom = 0; + layout.spacing = 10; + layout.wrap = false; + layout.fill = true; + list.setLayout(layout); + + GridDataFactory lgdf = GridDataFactory.fillDefaults(); + if (hasHeightSetting()) + { + int yHint = get(ChartHeightConfig.class).getPixel(); + lgdf.hint(SWT.DEFAULT, yHint); + } + lgdf.grab(true, false).applyTo(list); + + return container; + } + + protected void createTitleArea(Composite container) + { title = new StyledLabel(container, SWT.NONE); title.setBackground(container.getBackground()); title.setText(TextUtil.tooltip(getWidget().getLabel())); @@ -106,36 +133,24 @@ public Composite createControl(Composite parent, DashboardResources resources) }); GridDataFactory.fillDefaults().grab(true, false).applyTo(title); - - list = new Composite(container, SWT.NONE); - RowLayout layout = new RowLayout(SWT.VERTICAL); - layout.marginLeft = 0; - layout.marginRight = 0; - layout.marginTop = 0; - layout.marginBottom = 0; - layout.spacing = 10; - layout.wrap = false; - layout.fill = true; - list.setLayout(layout); - int yHint = get(ChartHeightConfig.class).getPixel(); - GridDataFactory.fillDefaults().hint(SWT.DEFAULT, yHint).grab(true, false).applyTo(list); - - return container; } @Override public void update(List items) { - GridData data = (GridData) list.getLayoutData(); + if (hasHeightSetting()) + { + GridData data = (GridData) list.getLayoutData(); - int oldHeight = data.heightHint; - int newHeight = get(ChartHeightConfig.class).getPixel(); + int oldHeight = data.heightHint; + int newHeight = get(ChartHeightConfig.class).getPixel(); - if (oldHeight != newHeight) - { - data.heightHint = newHeight; - title.getParent().layout(true); - title.getParent().getParent().layout(true); + if (oldHeight != newHeight) + { + data.heightHint = newHeight; + title.getParent().layout(true); + title.getParent().getParent().layout(true); + } } if (items.isEmpty()) @@ -157,18 +172,41 @@ public void update(List items) int count = 0; for (T item : items) { - // limit the number of securities listed on the dashboard to 25 - if (count >= 25) + // limit the number of securities listed on the dashboard + if (count >= getMaxNumberOfSecurities()) break; Composite child = createItemControl(list, item); child.setData(item); count++; } + if (count < items.size()) + { + createMaxSecuritiesExceededControl(list); + } } list.setData(items); list.layout(true); + list.getParent().layout(true); + list.getParent().getParent().layout(); + } + + protected void createMaxSecuritiesExceededControl(Composite parent) + { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new FormLayout()); + createLabel(composite, "..."); //$NON-NLS-1$ + } + + protected int getMaxNumberOfSecurities() + { + return 25; + } + + protected boolean hasHeightSetting() + { + return true; } protected abstract void createEmptyControl(Composite parent); @@ -183,7 +221,12 @@ public Control getTitleControl() protected Label createLabel(Composite composite, String text) { - Label ret = new Label(composite, SWT.NONE); + return createLabel(composite, text, SWT.NONE); + } + + protected Label createLabel(Composite composite, String text, int style) + { + Label ret = new Label(composite, style); ret.setText(TextUtil.tooltip(Objects.toString(text, ""))); //$NON-NLS-1$ return ret; } diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java index 89c98c5094..9f010ac817 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java @@ -6,13 +6,16 @@ import java.util.Collections; import java.util.Comparator; import java.util.Deque; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; -import java.util.stream.Collectors; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FormAttachment; @@ -20,6 +23,9 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; +import com.google.common.annotations.VisibleForTesting; + +import name.abuchen.portfolio.model.Client; import name.abuchen.portfolio.model.Dashboard; import name.abuchen.portfolio.model.Dashboard.Widget; import name.abuchen.portfolio.model.Security; @@ -27,6 +33,8 @@ import name.abuchen.portfolio.model.SecurityEvent.DividendEvent; import name.abuchen.portfolio.money.Values; import name.abuchen.portfolio.ui.Messages; +import name.abuchen.portfolio.ui.UIConstants; +import name.abuchen.portfolio.ui.util.Colors; import name.abuchen.portfolio.ui.util.FormDataFactory; import name.abuchen.portfolio.ui.util.LogoManager; @@ -56,7 +64,7 @@ public enum DateStartRange FROM_TODAY(Messages.LabelToday, d -> d), // FROM_ONE_WEEK(Messages.LabelReportingDialogWeek, d -> d.minus(1, ChronoUnit.WEEKS)), // FROM_ONE_MONTH(Messages.LabelReportingDialogMonth, d -> d.minus(1, ChronoUnit.MONTHS)), // - FROM_YTD(Messages.LabelReportingDialogYearYTD, d -> LocalDate.of(d.getYear(), 1, 1)), // + FROM_QUARTER(Messages.LabelReportingDialogQuarter, d -> d.minus(3, ChronoUnit.MONTHS)), // ; private DateStartRange(String label, UnaryOperator dateStartProvider) @@ -91,6 +99,7 @@ public DateStartRangeConfig(WidgetDelegate delegate) public enum DateEndRange { + UNTIL_ALL(Messages.LabelAllAttributes, d -> null), // UNTIL_EOY(Messages.LabelReportingDialogYear, d -> LocalDate.of(d.getYear(), 12, 31)), // UNTIL_ONE_MONTH(Messages.LabelReportingDialogMonth, d -> d.plus(1, ChronoUnit.MONTHS)), // UNTIL_ONE_WEEK(Messages.LabelReportingDialogWeek, d -> d.plus(1, ChronoUnit.WEEKS)), // @@ -165,10 +174,10 @@ public DateTypeConfig(WidgetDelegate delegate) } /** - * @deprecated This constructor is only used for testing, don't use it for + * This constructor is only used for testing, don't use it for * anything else */ - @Deprecated + @VisibleForTesting DividendListWidget() // needed for testing { super(null, null); @@ -178,58 +187,76 @@ public DividendListWidget(Widget widget, DashboardData data) { super(widget, data); + addConfig(new ClientFilterConfig(this)); addConfig(new DateTypeConfig(this)); addConfig(new DateStartRangeConfig(this)); - addConfig(new DateEndRangeConfig(this)); - addConfig(new ChartHeightConfig(this)); } @Override public Supplier> getUpdateTask() { - return getUpdateTask(LocalDate.now()); + return () -> getUpdateTask(LocalDate.now()); } - Supplier> getUpdateTask(LocalDate now) + List getUpdateTask(LocalDate now) { - return () -> { + DateType dateType = getDateTypeValue(); + ClientFilterConfig clientFilter = getClientFilterConfig(); + LocalDate fromDate = getStartRangeValue().getDate(now); + LocalDate untilDate = getEndRangeValue().getDate(now); + + // get all securities to show and put them into a map to benefit + // from O(1) + Set secSet = getSecuritiesToShow(clientFilter); - DateType dateType = getDateTypeValue(); + List items = new ArrayList<>(); + getSecurities().forEach(security -> handleSecurity(security, items, dateType, fromDate, untilDate, secSet)); + groupListEntries(items); + + return items; + } - List items = new ArrayList<>(); - LocalDate fromDate = getStartRangeValue().getDate(now); - LocalDate untilDate = getEndRangeValue().getDate(now); - for (Security security : getSecurities()) + void groupListEntries(List items) + { + Collections.sort(items, new DividendItemComparator()); + LocalDate prevDate = null; + for (DividendItem item : items) + { + LocalDate currDate = item.getFirstType().getDate(item.div); + if (prevDate == null || !currDate.isEqual(prevDate)) { - for (SecurityEvent se : security.getEvents()) - { - if (!(se instanceof DividendEvent de)) - { - continue; - } - DividendItem added = checkAndAdd(items, security, de, dateType, DateType.EX_DIVIDEND_DATE, fromDate, - untilDate, null); - checkAndAdd(items, security, de, dateType, DateType.PAYMENT_DATE, fromDate, untilDate, added); - } + item.hasNewDate = true; + prevDate = currDate; } + } + } - Collections.sort(items, new DividendItemComparator()); - LocalDate prevDate = null; - DividendItem prevItem = null; - for (DividendItem item : items) + void handleSecurity(Security security, List items, DateType dateType, LocalDate fromDate, + LocalDate untilDate, Set activeSecurities) + { + if (!activeSecurities.contains(security)) + { + return; + } + + for (SecurityEvent se : security.getEvents()) + { + if (!(se instanceof DividendEvent de)) { - prevItem = item; - LocalDate currDate = item.getFirstType().getDate(item.div); - if (prevDate == null || !currDate.isEqual(prevDate)) - { - item.hasNewDate = true; - prevDate = currDate; - continue; - } + continue; } + DividendItem added = checkAndAdd(items, security, de, dateType, DateType.EX_DIVIDEND_DATE, fromDate, + untilDate, null); + checkAndAdd(items, security, de, dateType, DateType.PAYMENT_DATE, fromDate, untilDate, added); + } + } - return items; - }; + Set getSecuritiesToShow(ClientFilterConfig clientFilter) + { + Client filteredClient = clientFilter.getSelectedFilter().filter(getClient()); + HashSet secSet = new HashSet<>(); + secSet.addAll(filteredClient.getActiveSecurities()); + return secSet; } static class DividendItemComparator implements Comparator @@ -254,6 +281,11 @@ public int compare(DividendItem di1, DividendItem di2) } } + ClientFilterConfig getClientFilterConfig() + { + return get(ClientFilterConfig.class); + } + DateStartRange getStartRangeValue() { return get(DateStartRangeConfig.class).getValue(); @@ -261,7 +293,7 @@ DateStartRange getStartRangeValue() DateEndRange getEndRangeValue() { - return get(DateEndRangeConfig.class).getValue(); + return DateEndRange.UNTIL_ALL; } DateType getDateTypeValue() @@ -288,7 +320,7 @@ DividendItem checkAndAdd(List items, Security sec, DividendEvent d return null; // } - if (checkDate.isAfter(endRange)) + if (endRange != null && checkDate.isAfter(endRange)) { return null; // } @@ -305,44 +337,82 @@ DividendItem checkAndAdd(List items, Security sec, DividendEvent d return ret; } + @Override + public Composite createControl(Composite parent, DashboardResources resources) + { + Composite ret = super.createControl(parent, resources); + GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5).applyTo(ret); + GridLayoutFactory.fillDefaults().numColumns(1).spacing(0, 2).applyTo(list); + GridDataFactory.fillDefaults().grab(true, true).applyTo(list); + + return ret; + } + + @Override + protected void createTitleArea(Composite container) + { + super.createTitleArea(container); + + Composite cmp = new Composite(container, SWT.NONE); + cmp.setLayout(new FormLayout()); + Label exDate = createLabel(cmp, DateType.EX_DIVIDEND_DATE.label); + exDate.setForeground(Colors.DARK_RED); + Label paymDate = createLabel(cmp, DateType.PAYMENT_DATE.label); + paymDate.setForeground(Colors.DARK_GREEN); + Label exPaymDate = createLabel(cmp, DateType.EX_DIVIDEND_DATE.label + "," + DateType.PAYMENT_DATE.label); //$NON-NLS-1$ + exPaymDate.setForeground(container.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW)); + + FormDataFactory.startingWith(exDate).thenRight(paymDate, 10).thenRight(exPaymDate, 10); + + } + @Override protected Composite createItemControl(Composite parent, DividendItem item) { Security sec = item.getSecurity(); + + if (item.hasNewDate) + { + Composite dtCmp = new Composite(parent, SWT.NONE); + dtCmp.setLayout(new FormLayout()); + Label date = createLabel(dtCmp, Values.Date.format(item.getFirstType().getDate(item.div))); + date.setData(UIConstants.CSS.CLASS_NAME, UIConstants.CSS.HEADING2); + } + Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new FormLayout()); Image image = LogoManager.instance().getDefaultColumnImage(sec, getClient().getSettings()); Label logo = createLabel(composite, image); Label name = createLabel(composite, sec.getName()); - String typeStr = item.types.stream() // - .map(dt -> dt.label) // - .collect(Collectors.joining(", ")); - Label amtAndType = createLabel(composite, - " " + Values.Money.format(item.div.getAmount()) + " " + typeStr); //$NON-NLS-1$ //$NON-NLS-2$ - - - Label date = null; + Label amt = createLabel(composite, Values.Money.format(item.div.getAmount()), SWT.RIGHT); + setForegroundColor(item, amt); - if (item.hasNewDate) - { - date = createLabel(composite, Values.Date.format(item.getFirstType().getDate(item.div))); - } + addListener(mouseUpAdapter, composite, name, amt); - addListener(mouseUpAdapter, composite, name, date, amtAndType); + FormDataFactory.startingWith(logo).thenRight(name).right(new FormAttachment(amt, -5, SWT.LEFT)); + FormDataFactory.startingWith(amt).right(new FormAttachment(100)); + GridDataFactory.fillDefaults().grab(true, false).applyTo(composite); + return composite; + } - FormDataFactory start; - if (date != null) + void setForegroundColor(DividendItem item, Label label) + { + if (item.types.contains(DateType.EX_DIVIDEND_DATE)) { - start = FormDataFactory.startingWith(date).thenBelow(logo); + if (item.types.contains(DateType.PAYMENT_DATE)) + { + label.setForeground(label.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW)); + } + else + { + label.setForeground(Colors.DARK_RED); + } } - else + else if (item.types.contains(DateType.PAYMENT_DATE)) { - start = FormDataFactory.startingWith(logo); + label.setForeground(Colors.DARK_GREEN); } - start.thenRight(name).right(new FormAttachment(100)).thenBelow(amtAndType); - - return composite; } @Override @@ -351,4 +421,9 @@ protected void createEmptyControl(Composite parent) // nothing to do } + @Override + protected boolean hasHeightSetting() + { + return false; + } } diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java index ecb0fbf3eb..59862678d8 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/WidgetFactory.java @@ -215,7 +215,7 @@ public enum WidgetFactory HEATMAP_EARNINGS(Messages.LabelHeatmapEarnings, Messages.LabelEarnings, EarningsHeatmapWidget::new), - EARNINGS_DIVIDEND_LIST(Messages.LabelEarningsDividendList, Messages.LabelEarnings, DividendListWidget::new), + DIVIDEND_EVENT_LIST(Messages.LabelEarningsDividendList, Messages.LabelEarnings, DividendListWidget::new), EARNINGS_PER_YEAR_CHART(Messages.LabelEarningsPerYear, Messages.LabelEarnings, EarningsChartWidget::perYear), From 9eda5c0664614d0b8336ed73db1b37c522ffd499 Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Wed, 1 May 2024 18:23:39 +0200 Subject: [PATCH 11/12] don't hide monetary values (that are only the dividend per share and don't leak any personal info) if discreet mode is active. Rmove currency from value if it the same as the client's base currency --- .../portfolio/ui/views/PortfolioListView.java | 2 +- .../portfolio/ui/views/SecuritiesTable.java | 2 +- .../ui/views/StatementOfAssetsViewer.java | 2 +- .../views/columns/DividendPaymentColumn.java | 17 +++++++++-------- .../views/dashboard/DividendListWidget.java | 3 ++- .../ui/views/panes/SecurityEventsPane.java | 2 +- .../name/abuchen/portfolio/money/Values.java | 19 +++++++++++++++---- 7 files changed, 30 insertions(+), 17 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java index d90780e48c..c9805c4cb4 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java @@ -282,7 +282,7 @@ public String getText(Object element) private void addDividendPaymentColumns(ShowHideColumnHelper support) { - DividendPaymentColumn.createFor() // + DividendPaymentColumn.createFor(getClient()) // .forEach(column -> { support.addColumn(column); }); diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java index 82a122841b..603cebf146 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/SecuritiesTable.java @@ -244,7 +244,7 @@ public SecuritiesTable(Composite parent, AbstractFinanceView view) private void addDividendColumns() { - DividendPaymentColumn.createFor() // + DividendPaymentColumn.createFor(getClient()) // .forEach(column -> { support.addColumn(column); }); diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java index 6aa72bca9f..bfcac19286 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java @@ -756,7 +756,7 @@ private void addDividendColumns(List options) private void addDividendPaymentColumns() { - DividendPaymentColumn.createFor() // + DividendPaymentColumn.createFor(client) // .forEach(column -> { if (column.getSorter() != null) column.getSorter().wrap(ElementComparator::new); diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java index bf2d8bbb62..ab13f0cb69 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -9,6 +9,7 @@ import org.eclipse.swt.graphics.Color; import name.abuchen.portfolio.model.Adaptor; +import name.abuchen.portfolio.model.Client; import name.abuchen.portfolio.model.Security; import name.abuchen.portfolio.model.SecurityEvent.DividendEvent; import name.abuchen.portfolio.money.Money; @@ -22,7 +23,7 @@ public class DividendPaymentColumn { - static Column createNextDividendExDateColumn() + static Column createNextDividendExDateColumn(Client client) { Column column = new Column("nextdivexdate", Messages.ColumnDividendsNextExDate, SWT.LEFT, 80); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextExDate_MenuLabel); @@ -63,7 +64,7 @@ public Color getBackground(Object element) return column; } - static Column createNextDividendPaymentDateColumn() + static Column createNextDividendPaymentDateColumn(Client client) { Column column = new Column("nextdivpmtdate", Messages.ColumnDividendsNextPaymentDate, SWT.LEFT, 80); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextPaymentDate_MenuLabel); @@ -104,7 +105,7 @@ public Color getBackground(Object element) return column; } - static Column createNextDividendPaymentAmount() + static Column createNextDividendPaymentAmount(Client client) { Column column = new Column("nextdivpmtamt", Messages.ColumnDividendsNextPaymentAmount, SWT.RIGHT, 60); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextPaymentAmount_MenuLabel); @@ -127,7 +128,7 @@ public String getText(Object element) { return null; // } - return Values.Money.format(amount); + return Values.Money.format(amount, client.getBaseCurrency(), false); } }); column.setSorter(ColumnViewerSorter.create((o1, o2) -> { @@ -154,11 +155,11 @@ static Money getAmount(LocalDate now, Security sec) .map(DividendEvent::getAmount).findFirst().orElse(null); } - public static Stream createFor() + public static Stream createFor(Client client) { - return Stream.of(createNextDividendExDateColumn(), // - createNextDividendPaymentDateColumn(), // - createNextDividendPaymentAmount()); + return Stream.of(createNextDividendExDateColumn(client), // + createNextDividendPaymentDateColumn(client), // + createNextDividendPaymentAmount(client)); } } diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java index 9f010ac817..b631dd39c7 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java @@ -385,7 +385,8 @@ protected Composite createItemControl(Composite parent, DividendItem item) Image image = LogoManager.instance().getDefaultColumnImage(sec, getClient().getSettings()); Label logo = createLabel(composite, image); Label name = createLabel(composite, sec.getName()); - Label amt = createLabel(composite, Values.Money.format(item.div.getAmount()), SWT.RIGHT); + Label amt = createLabel(composite, + Values.Money.format(item.div.getAmount(), getClient().getBaseCurrency(), false), SWT.RIGHT); setForegroundColor(item, amt); addListener(mouseUpAdapter, composite, name, amt); diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/panes/SecurityEventsPane.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/panes/SecurityEventsPane.java index 718dd838e2..3a66dd446e 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/panes/SecurityEventsPane.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/panes/SecurityEventsPane.java @@ -142,7 +142,7 @@ public String getText(Object element) public String getText(Object element) { return element instanceof DividendEvent dividendEvent - ? Values.Money.format(dividendEvent.getAmount(), client.getBaseCurrency()) + ? Values.Money.format(dividendEvent.getAmount(), client.getBaseCurrency(), false) : null; } }); diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/money/Values.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/money/Values.java index 1262b2645f..06c9d33492 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/money/Values.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/money/Values.java @@ -28,7 +28,12 @@ private MoneyValues() @Override public String format(Money amount) { - if (DiscreetMode.isActive()) + return format(amount, true); + } + + public String format(Money amount, boolean checkDiscreetMode) + { + if (checkDiscreetMode && DiscreetMode.isActive()) return amount.getCurrencyCode() + " " + DiscreetMode.HIDDEN_AMOUNT; //$NON-NLS-1$ else return String.format("%s %,.2f", amount.getCurrencyCode(), amount.getAmount() / divider()); //$NON-NLS-1$ @@ -36,11 +41,17 @@ public String format(Money amount) public String format(Money amount, String skipCurrencyCode) { - if (!FormatHelper.alwaysDisplayCurrencyCode() && skipCurrencyCode.equals(amount.getCurrencyCode())) - return DiscreetMode.isActive() ? DiscreetMode.HIDDEN_AMOUNT + return format(amount, skipCurrencyCode, true); + } + + public String format(Money amount, String skipCurrencyCode, boolean checkDiscreetMode) + { + if (!FormatHelper.alwaysDisplayCurrencyCode() + && skipCurrencyCode.equals(amount.getCurrencyCode())) + return (checkDiscreetMode && DiscreetMode.isActive()) ? DiscreetMode.HIDDEN_AMOUNT : String.format("%,.2f", amount.getAmount() / divider()); //$NON-NLS-1$ else - return format(amount); + return format(amount, checkDiscreetMode); } @Override From 15400b2599d336d7f6c769cc62ca90633bcb922f Mon Sep 17 00:00:00 2001 From: "\"Lothar Kimmeringer\"" Date: Fri, 10 May 2024 21:54:03 +0200 Subject: [PATCH 12/12] removed unused parameter, use helper method for sorting. Portfolio view doesn't contain dividend columns anymore (made no sense there) --- .../portfolio/ui/views/PortfolioListView.java | 10 --------- .../views/columns/DividendPaymentColumn.java | 21 +++++++------------ 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java index c9805c4cb4..785b31614d 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PortfolioListView.java @@ -49,7 +49,6 @@ import name.abuchen.portfolio.ui.util.viewers.ListEditingSupport; import name.abuchen.portfolio.ui.util.viewers.ShowHideColumnHelper; import name.abuchen.portfolio.ui.views.columns.AttributeColumn; -import name.abuchen.portfolio.ui.views.columns.DividendPaymentColumn; import name.abuchen.portfolio.ui.views.columns.NameColumn; import name.abuchen.portfolio.ui.views.columns.NameColumn.NameColumnLabelProvider; import name.abuchen.portfolio.ui.views.columns.NoteColumn; @@ -260,7 +259,6 @@ public String getText(Object element) portfolioColumns.addColumn(column); addAttributeColumns(portfolioColumns); - addDividendPaymentColumns(portfolioColumns); portfolioColumns.createColumns(true); @@ -280,14 +278,6 @@ public String getText(Object element) return container; } - private void addDividendPaymentColumns(ShowHideColumnHelper support) - { - DividendPaymentColumn.createFor(getClient()) // - .forEach(column -> { - support.addColumn(column); - }); - } - private void addAttributeColumns(ShowHideColumnHelper support) { AttributeColumn.createFor(getClient(), Portfolio.class) // diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java index ab13f0cb69..9885907c5f 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -23,7 +23,7 @@ public class DividendPaymentColumn { - static Column createNextDividendExDateColumn(Client client) + static Column createNextDividendExDateColumn() { Column column = new Column("nextdivexdate", Messages.ColumnDividendsNextExDate, SWT.LEFT, 80); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextExDate_MenuLabel); @@ -64,7 +64,7 @@ public Color getBackground(Object element) return column; } - static Column createNextDividendPaymentDateColumn(Client client) + static Column createNextDividendPaymentDateColumn() { Column column = new Column("nextdivpmtdate", Messages.ColumnDividendsNextPaymentDate, SWT.LEFT, 80); //$NON-NLS-1$ column.setMenuLabel(Messages.ColumnDividendsNextPaymentDate_MenuLabel); @@ -131,16 +131,9 @@ public String getText(Object element) return Values.Money.format(amount, client.getBaseCurrency(), false); } }); - column.setSorter(ColumnViewerSorter.create((o1, o2) -> { - Money m1 = getAmount(LocalDate.now(), (Security) o1); - Money m2 = getAmount(LocalDate.now(), (Security) o2); - - if (m1 == null) - return m2 == null ? 0 : -1; - if (m2 == null) - return 1; - - return m1.compareTo(m2); + column.setSorter(ColumnViewerSorter.create(element -> { + Security security = Adaptor.adapt(Security.class, element); + return security != null ? getAmount(LocalDate.now(), security) : null; })); return column; } @@ -157,8 +150,8 @@ static Money getAmount(LocalDate now, Security sec) public static Stream createFor(Client client) { - return Stream.of(createNextDividendExDateColumn(client), // - createNextDividendPaymentDateColumn(client), // + return Stream.of(createNextDividendExDateColumn(), // + createNextDividendPaymentDateColumn(), // createNextDividendPaymentAmount(client)); }