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..2d3edce6df --- /dev/null +++ b/name.abuchen.portfolio.ui.tests/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidgetTest.java @@ -0,0 +1,294 @@ +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.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.stream.Collectors; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +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.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; +import name.abuchen.portfolio.ui.views.dashboard.DividendListWidget.DividendItem; + +@SuppressWarnings("nls") +public class DividendListWidgetTest +{ + private static 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 de1_5; + private DividendEvent de2_1; + private DividendEvent de2_2; + private SecurityEvent de2_3; + private DividendEvent de2_4; + + @BeforeClass + public static void setupLocale() + { + defaultLocale = Locale.getDefault(); + Locale.setDefault(Locale.GERMANY); + } + + @AfterClass + public static 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"); + 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); + 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.getFirstType(), 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_QUARTER", // + 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_QUARTER.getDate(now), is(LocalDate.of(2024, 1, 8))); + } + + @Test + public void testDateEndRange() + { + 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); + 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))); + assertThat(DateEndRange.UNTIL_ALL.getDate(now), nullValue()); + } + + @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(); + AbstractSecurityListWidget widget = new DividendListWidget() + { + @Override + public List getUpdateTask(LocalDate now) + { + assertThat(now, is(testnow)); + return null; + } + }; + assertThat(widget.getUpdateTask().get(), 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); + AtomicBoolean showSecurities = new AtomicBoolean(true); + + 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); + } + + @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); + 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); + assertEquals("", getListAsString(list)); + + 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" // + + "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); + 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); + 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); + 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); + assertEquals("2024-08-01 Security 1 EUR 0,33 [" + Messages.ColumnPaymentDate + "]", getListAsString(list)); + dateType.set(DateType.EX_DIVIDEND_DATE); + 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); + 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) + { + return list.stream() // + .map(entry -> { + StringBuilder sb = new StringBuilder(); + if (entry.hasNewDate) + { + sb.append(entry.getFirstType().getDate(entry.div).toString() + " "); + } + sb.append(entry.getSecurity().getName() + " "); + sb.append(entry.div.getAmount() + " "); + sb.append(entry.types); + return sb.toString(); + }) // + .collect(Collectors.joining("\r\n")); + } +} 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/Messages.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/Messages.java index 94fccbc259..5e26450345 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 @@ -1322,6 +1322,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 00272a2491..95d5d99622 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 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 1dab218c65..ed36d1157d 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 0384b323a5..12548e9980 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 e9f7bab8c0..654b7d1b9f 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 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 f8a757360e..656635310b 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 28ece5e00a..208f68cc42 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 d2f647de7d..8e6b1714bd 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 ee141214ab..afcd57f5cc 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 4d22a4c4c3..fec32bddf8 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 de3243a791..2c1085e7ea 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 7a6c45999f..dc2fc9d96c 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 cb3a4ce746..52803f9892 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 f25df8764c..2400ca6591 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 cf66ed5160..8c80c97747 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 920e99714c..fda7bd68a2 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 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..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 @@ -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(getClient()) // + .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..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 @@ -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(client) // + .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..9885907c5f --- /dev/null +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/columns/DividendPaymentColumn.java @@ -0,0 +1,158 @@ +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.Client; +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("nextdivexdate", 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 -> !now.isAfter(d)) // + .findFirst().orElse(null); + }; + + column.setLabelProvider(new DateLabelProvider(dataProvider) + { + @Override + public Color getBackground(Object element) + { + LocalDate date = dataProvider.apply(element); + if (date == null || !date.equals(LocalDate.now())) + { + return null; // + } + + return Colors.theme().redBackground(); + } + }); + column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); + return column; + } + + static Column createNextDividendPaymentDateColumn() + { + 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); + + 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 -> !now.isAfter(d)) // + .findFirst().orElse(null); + }; + + column.setLabelProvider(new DateLabelProvider(dataProvider) + { + @Override + public Color getBackground(Object element) + { + LocalDate date = dataProvider.apply(element); + if (date == null || !date.equals(LocalDate.now())) + { + return null; // + } + + return Colors.theme().greenBackground(); + } + }); + column.setSorter(ColumnViewerSorter.create(dataProvider::apply)); + return column; + } + + static Column createNextDividendPaymentAmount(Client client) + { + 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); + 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, client.getBaseCurrency(), false); + } + }); + column.setSorter(ColumnViewerSorter.create(element -> { + Security security = Adaptor.adapt(Security.class, element); + return security != null ? getAmount(LocalDate.now(), security) : null; + })); + 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 -> !now.isAfter(d.getPaymentDate())) // + .map(DividendEvent::getAmount).findFirst().orElse(null); + } + + public static Stream createFor(Client client) + { + return Stream.of(createNextDividendExDateColumn(), // + createNextDividendPaymentDateColumn(), // + createNextDividendPaymentAmount(client)); + } + +} 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 fb1a39974b..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; @@ -66,6 +67,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); @@ -79,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())); @@ -95,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()) @@ -146,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); @@ -172,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 new file mode 100644 index 0000000000..b631dd39c7 --- /dev/null +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/dashboard/DividendListWidget.java @@ -0,0 +1,430 @@ +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.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 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; +import org.eclipse.swt.layout.FormLayout; +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; +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.UIConstants; +import name.abuchen.portfolio.ui.util.Colors; +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; + Deque types = new LinkedList<>(); + DividendEvent div; + + public DividendItem(DateType type, Security security, DividendEvent div) + { + super(security); + this.div = div; + this.types.add(type); + } + + DateType getFirstType() + { + return types.peekFirst(); + } + } + + 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_QUARTER(Messages.LabelReportingDialogQuarter, d -> d.minus(3, ChronoUnit.MONTHS)), // + ; + + 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_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)), // + 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); + } + } + + /** + * This constructor is only used for testing, don't use it for + * anything else + */ + @VisibleForTesting + DividendListWidget() // needed for testing + { + super(null, null); + } + + public DividendListWidget(Widget widget, DashboardData data) + { + super(widget, data); + + addConfig(new ClientFilterConfig(this)); + addConfig(new DateTypeConfig(this)); + addConfig(new DateStartRangeConfig(this)); + } + + @Override + public Supplier> getUpdateTask() + { + return () -> getUpdateTask(LocalDate.now()); + } + + List getUpdateTask(LocalDate now) + { + 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); + + List items = new ArrayList<>(); + getSecurities().forEach(security -> handleSecurity(security, items, dateType, fromDate, untilDate, secSet)); + groupListEntries(items); + + return items; + } + + 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)) + { + item.hasNewDate = true; + prevDate = currDate; + } + } + } + + 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)) + { + 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); + } + } + + 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 + { + + @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); + } + } + + ClientFilterConfig getClientFilterConfig() + { + return get(ClientFilterConfig.class); + } + + DateStartRange getStartRangeValue() + { + return get(DateStartRangeConfig.class).getValue(); + } + + DateEndRange getEndRangeValue() + { + return DateEndRange.UNTIL_ALL; + } + + 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, DividendItem prevAdded) + { + if (configuredType != typeToAdd && configuredType != DateType.ALL_DATES) + { + return null; + } + + LocalDate checkDate = typeToAdd.getDate(de); + if (checkDate.isBefore(startRange)) + { + return null; // + } + + if (endRange != null && checkDate.isAfter(endRange)) + { + return null; // + } + + DividendItem ret = new DividendItem(typeToAdd, sec, de); + if (prevAdded != null && checkDate.equals(prevAdded.types.peekLast().getDate(de))) + { + prevAdded.types.add(typeToAdd); + } + else + { + items.add(ret); + } + 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()); + Label amt = createLabel(composite, + Values.Money.format(item.div.getAmount(), getClient().getBaseCurrency(), false), SWT.RIGHT); + setForegroundColor(item, amt); + + addListener(mouseUpAdapter, composite, name, amt); + + 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; + } + + void setForegroundColor(DividendItem item, Label label) + { + if (item.types.contains(DateType.EX_DIVIDEND_DATE)) + { + if (item.types.contains(DateType.PAYMENT_DATE)) + { + label.setForeground(label.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW)); + } + else + { + label.setForeground(Colors.DARK_RED); + } + } + else if (item.types.contains(DateType.PAYMENT_DATE)) + { + label.setForeground(Colors.DARK_GREEN); + } + } + + @Override + 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 7ecd374eca..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,6 +215,8 @@ public enum WidgetFactory HEATMAP_EARNINGS(Messages.LabelHeatmapEarnings, Messages.LabelEarnings, EarningsHeatmapWidget::new), + DIVIDEND_EVENT_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), 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