1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.moneywise.lethe.ui.controls;
18
19 import io.github.tonywasher.joceanus.oceanus.date.OceanusDatePeriod;
20 import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
21 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventManager;
22 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar;
23 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar.OceanusEventProvider;
24 import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
25 import io.github.tonywasher.joceanus.metis.ui.MetisIcon;
26 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysis;
27 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket;
28 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket.MoneyWiseAnalysisPortfolioBucketList;
29 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisSecurityBucket;
30 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisSecurityBucket.MoneyWiseAnalysisSecurityBucketList;
31 import io.github.tonywasher.joceanus.moneywise.lethe.reports.MoneyWiseReportType;
32 import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseUIResource;
33 import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
34 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIComponent;
35 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
36 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButton;
37 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButtonFactory;
38 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIDateRangeSelector;
39 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIScrollButtonManager;
40 import io.github.tonywasher.joceanus.tethys.api.control.TethysUILabel;
41 import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
42 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
43 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
44 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollSubMenu;
45 import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIBoxPaneManager;
46
47 import java.util.Iterator;
48
49
50
51
52 public class MoneyWiseReportSelect
53 implements OceanusEventProvider<PrometheusDataEvent>, TethysUIComponent {
54
55
56
57 private static final String NLS_REPORT = MoneyWiseUIResource.REPORT_PROMPT.getValue();
58
59
60
61
62 private static final String NLS_TITLE = MoneyWiseUIResource.REPORT_TITLE.getValue();
63
64
65
66
67 private final OceanusEventManager<PrometheusDataEvent> theEventManager;
68
69
70
71
72 private final TethysUIBoxPaneManager thePanel;
73
74
75
76
77 private final TethysUIScrollButtonManager<MoneyWiseReportType> theReportButton;
78
79
80
81
82 private final TethysUIScrollButtonManager<MoneyWiseAnalysisSecurityBucket> theHoldingButton;
83
84
85
86
87 private final TethysUIDateRangeSelector theRangeSelect;
88
89
90
91
92 private final TethysUIButton thePrintButton;
93
94
95
96
97 private final TethysUIButton theSaveButton;
98
99
100
101
102 private MoneyWiseReportState theState;
103
104
105
106
107 private MoneyWiseReportState theSavePoint;
108
109
110
111
112 private boolean isActive;
113
114
115
116
117
118
119 public MoneyWiseReportSelect(final TethysUIFactory<?> pFactory) {
120
121 final TethysUIButtonFactory<?> myButtons = pFactory.buttonFactory();
122 theReportButton = myButtons.newScrollButton(MoneyWiseReportType.class);
123 theHoldingButton = myButtons.newScrollButton(MoneyWiseAnalysisSecurityBucket.class);
124
125
126 theRangeSelect = myButtons.newDateRangeSelector();
127
128
129 final TethysUILabel myRepLabel = pFactory.controlFactory().newLabel(NLS_REPORT);
130
131
132 thePrintButton = myButtons.newButton();
133 MetisIcon.configurePrintIconButton(thePrintButton);
134
135
136 theSaveButton = myButtons.newButton();
137 MetisIcon.configureSaveIconButton(theSaveButton);
138
139
140 theState = new MoneyWiseReportState();
141 theState.setRange(theRangeSelect);
142 theState.setType(MoneyWiseReportType.getDefault());
143
144
145 theEventManager = new OceanusEventManager<>();
146
147
148 thePanel = pFactory.paneFactory().newHBoxPane();
149 thePanel.setBorderTitle(NLS_TITLE);
150
151
152 thePanel.addNode(myRepLabel);
153 thePanel.addNode(theReportButton);
154 thePanel.addSpacer();
155 thePanel.addNode(theHoldingButton);
156 thePanel.addSpacer();
157 thePanel.addNode(theRangeSelect);
158 thePanel.addSpacer();
159 thePanel.addNode(thePrintButton);
160 thePanel.addNode(theSaveButton);
161
162
163 theReportButton.getEventRegistrar().addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewReport());
164 theReportButton.setMenuConfigurator(e -> buildReportMenu());
165 theHoldingButton.getEventRegistrar().addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewSecurity());
166 theHoldingButton.setMenuConfigurator(e -> buildHoldingMenu());
167 thePrintButton.getEventRegistrar().addEventListener(e -> theEventManager.fireEvent(PrometheusDataEvent.PRINT));
168 theSaveButton.getEventRegistrar().addEventListener(e -> theEventManager.fireEvent(PrometheusDataEvent.SAVETOFILE));
169 theRangeSelect.getEventRegistrar().addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewRange());
170 }
171
172 @Override
173 public TethysUIComponent getUnderlying() {
174 return thePanel;
175 }
176
177 @Override
178 public OceanusEventRegistrar<PrometheusDataEvent> getEventRegistrar() {
179 return theEventManager.getEventRegistrar();
180 }
181
182
183
184
185
186
187 public MoneyWiseReportType getReportType() {
188 return theState.getType();
189 }
190
191
192
193
194
195
196 public OceanusDateRange getDateRange() {
197 return theState.getRange();
198 }
199
200
201
202
203
204
205 public MoneyWiseAnalysisSecurityBucket getSecurity() {
206 return theState.getSecurity();
207 }
208
209
210
211
212
213
214 public TethysUIDateRangeSelector getDateRangeSelector() {
215 return theRangeSelect;
216 }
217
218
219
220
221 private void buildReportMenu() {
222
223 final boolean hasSecurities = theState.hasSecurities();
224 final TethysUIScrollMenu<MoneyWiseReportType> myBuilder = theReportButton.getMenu();
225 myBuilder.removeAllItems();
226
227
228 for (MoneyWiseReportType myType : MoneyWiseReportType.values()) {
229
230 if (hasSecurities
231 || !myType.needSecurities()) {
232
233 myBuilder.addItem(myType);
234 }
235 }
236 }
237
238
239
240
241 private void buildHoldingMenu() {
242
243 final MoneyWiseAnalysis myAnalysis = theState.getAnalysis();
244 final MoneyWiseAnalysisSecurityBucket mySecurity = theState.getSecurity();
245 final MoneyWiseAnalysisPortfolioBucketList myPortfolios = myAnalysis.getPortfolios();
246
247
248 final TethysUIScrollMenu<MoneyWiseAnalysisSecurityBucket> myBuilder = theHoldingButton.getMenu();
249 myBuilder.removeAllItems();
250 TethysUIScrollItem<MoneyWiseAnalysisSecurityBucket> myActive = null;
251
252
253 final Iterator<MoneyWiseAnalysisPortfolioBucket> myPortIterator = myPortfolios.iterator();
254 while (myPortIterator.hasNext()) {
255 final MoneyWiseAnalysisPortfolioBucket myPortBucket = myPortIterator.next();
256
257
258 final String myName = myPortBucket.getName();
259 final TethysUIScrollSubMenu<MoneyWiseAnalysisSecurityBucket> myMenu = myBuilder.addSubMenu(myName);
260
261
262 final MoneyWiseAnalysisSecurityBucketList mySecurities = myPortBucket.getSecurities();
263 final Iterator<MoneyWiseAnalysisSecurityBucket> myIterator = mySecurities.iterator();
264 while (myIterator.hasNext()) {
265 final MoneyWiseAnalysisSecurityBucket myBucket = myIterator.next();
266
267
268 final TethysUIScrollItem<MoneyWiseAnalysisSecurityBucket> myItem = myMenu.getSubMenu().addItem(myBucket, myBucket.getSecurityName());
269
270
271 if (myBucket.equals(mySecurity)) {
272 myActive = myItem;
273 }
274 }
275 }
276
277
278 if (myActive != null) {
279 myActive.scrollToItem();
280 }
281 }
282
283
284
285
286
287
288 public final void setRange(final OceanusDateRange pRange) {
289
290 theRangeSelect.setOverallRange(pRange);
291 }
292
293
294
295
296
297
298 public void setSecurities(final boolean pSecurities) {
299 theState.setSecurities(pSecurities);
300 }
301
302
303
304
305
306
307 public void setAnalysis(final MoneyWiseAnalysis pAnalysis) {
308
309 theState.setAnalysis(pAnalysis);
310
311
312 final MoneyWiseAnalysisPortfolioBucketList myPortfolios = pAnalysis.getPortfolios();
313
314
315 MoneyWiseAnalysisSecurityBucket mySecurity = theState.getSecurity();
316
317
318 if (mySecurity != null) {
319
320 mySecurity = myPortfolios.getMatchingSecurityHolding(mySecurity.getSecurityHolding());
321 }
322
323
324 if (mySecurity == null) {
325
326 mySecurity = myPortfolios.getDefaultSecurityHolding();
327 }
328
329
330 theState.setSecurity(mySecurity);
331 }
332
333
334
335
336
337
338 public void setSecurity(final MoneyWiseAnalysisSecurityBucket pSecurity) {
339
340 theState.setSecurity(pSecurity);
341 theState.setType(MoneyWiseReportType.CAPITALGAINS);
342
343
344 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
345 }
346
347
348
349
350 public void createSavePoint() {
351
352 theSavePoint = new MoneyWiseReportState(theState);
353 }
354
355
356
357
358 public void restoreSavePoint() {
359
360 theState = new MoneyWiseReportState(theSavePoint);
361
362
363 theState.applyState();
364 }
365
366 @Override
367 public void setEnabled(final boolean bEnable) {
368 theRangeSelect.setEnabled(bEnable);
369 theReportButton.setEnabled(bEnable);
370 theHoldingButton.setEnabled(bEnable);
371 thePrintButton.setEnabled(bEnable);
372 theSaveButton.setEnabled(bEnable);
373 }
374
375 @Override
376 public void setVisible(final boolean pVisible) {
377 thePanel.setVisible(pVisible);
378 }
379
380
381
382
383 private void handleNewReport() {
384
385 isActive = true;
386
387
388 if (theState.setType(theReportButton.getValue())) {
389
390 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
391 }
392
393
394 isActive = false;
395 }
396
397
398
399
400 private void handleNewSecurity() {
401
402 isActive = true;
403
404
405 if (theState.setSecurity(theHoldingButton.getValue())) {
406
407 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
408 }
409
410
411 isActive = false;
412 }
413
414
415
416
417 private void handleNewRange() {
418
419 if (theState.setRange(theRangeSelect)
420 && !isActive) {
421
422 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
423 }
424 }
425
426
427
428
429 private final class MoneyWiseReportState {
430
431
432
433 private MoneyWiseAnalysis theAnalysis;
434
435
436
437
438 private OceanusDateRange theRange;
439
440
441
442
443 private boolean hasSecurities;
444
445
446
447
448 private MoneyWiseAnalysisSecurityBucket theSecurity;
449
450
451
452
453 private MoneyWiseReportType theType;
454
455
456
457
458 private MoneyWiseReportState() {
459 }
460
461
462
463
464
465
466 private MoneyWiseReportState(final MoneyWiseReportState pState) {
467 theAnalysis = pState.getAnalysis();
468 theRange = pState.getRange();
469 hasSecurities = pState.hasSecurities();
470 theSecurity = pState.getSecurity();
471 theType = pState.getType();
472 }
473
474
475
476
477
478
479 private MoneyWiseAnalysis getAnalysis() {
480 return theAnalysis;
481 }
482
483
484
485
486
487
488 private OceanusDateRange getRange() {
489 return theRange;
490 }
491
492
493
494
495
496
497 private boolean hasSecurities() {
498 return hasSecurities;
499 }
500
501
502
503
504
505
506 private MoneyWiseAnalysisSecurityBucket getSecurity() {
507 return theSecurity;
508 }
509
510
511
512
513
514
515 private MoneyWiseReportType getType() {
516 return theType;
517 }
518
519
520
521
522
523
524
525 private boolean setRange(final TethysUIDateRangeSelector pSelect) {
526
527 final OceanusDateRange myRange = pSelect.getRange();
528 if (!MetisDataDifference.isEqual(myRange, theRange)) {
529 theRange = new OceanusDateRange(myRange);
530 return true;
531 }
532 return false;
533 }
534
535
536
537
538
539
540 private void setSecurities(final boolean pSecurities) {
541
542 if (pSecurities != hasSecurities) {
543 hasSecurities = pSecurities;
544 if (!hasSecurities
545 && theType.needSecurities()) {
546 theType = MoneyWiseReportType.getDefault();
547 }
548 }
549 }
550
551
552
553
554
555
556 private void setAnalysis(final MoneyWiseAnalysis pAnalysis) {
557 theAnalysis = pAnalysis;
558 }
559
560
561
562
563
564
565
566 private boolean setSecurity(final MoneyWiseAnalysisSecurityBucket pSecurity) {
567 if (!pSecurity.equals(theSecurity)) {
568 theSecurity = pSecurity;
569 applyState();
570 return true;
571 }
572 return false;
573 }
574
575
576
577
578
579
580
581 private boolean setType(final MoneyWiseReportType pType) {
582 if (!pType.equals(theType)) {
583
584 final boolean isPointInTime = theType != null
585 && theType.isPointInTime();
586
587
588 theType = pType;
589
590
591 if (theType.isPointInTime() != isPointInTime) {
592
593 theRangeSelect.setPeriod(isPointInTime
594 ? OceanusDatePeriod.FISCALYEAR
595 : OceanusDatePeriod.DATESUPTO);
596 theRangeSelect.lockPeriod(!isPointInTime);
597
598
599 } else if (theType == MoneyWiseReportType.TAXCALC) {
600
601 theRangeSelect.setPeriod(OceanusDatePeriod.FISCALYEAR);
602 }
603
604
605 applyState();
606 return true;
607 }
608 return false;
609 }
610
611
612
613
614 private void applyState() {
615
616 setEnabled(true);
617 theReportButton.setFixedText(theType == null
618 ? null
619 : theType.toString());
620 theHoldingButton.setValue(theSecurity);
621 theHoldingButton.setVisible(MoneyWiseReportType.CAPITALGAINS.equals(theType));
622 }
623 }
624 }