1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.moneywise.ui.dialog;
18
19 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
21 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
22 import io.github.tonywasher.joceanus.metis.field.MetisFieldRequired;
23 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
24 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicResource;
25 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee;
26 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee.MoneyWisePayeeList;
27 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseRegion;
28 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseRegion.MoneyWiseRegionList;
29 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity;
30 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity.MoneyWiseSecurityList;
31 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoClass;
32 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAssetCategory;
33 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCurrency;
34 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCurrency.MoneyWiseCurrencyList;
35 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityClass;
36 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityType;
37 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityType.MoneyWiseSecurityTypeList;
38 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
39 import io.github.tonywasher.joceanus.moneywise.data.validate.MoneyWiseValidateSecurity;
40 import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseIcon;
41 import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseUIResource;
42 import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseAssetTable;
43 import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseView;
44 import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
45 import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSet;
46 import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSetEvent;
47 import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
48 import io.github.tonywasher.joceanus.tethys.api.control.TethysUIControl.TethysUIIconMapSet;
49 import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
50 import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUICharArrayTextAreaField;
51 import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIIconButtonField;
52 import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIPriceEditField;
53 import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIScrollButtonField;
54 import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIStringEditField;
55 import io.github.tonywasher.joceanus.tethys.api.field.TethysUIFieldFactory;
56 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
57 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
58
59 import java.util.Iterator;
60 import java.util.Map;
61
62
63
64
65 public class MoneyWiseSecurityDialog
66 extends MoneyWiseAssetDialog<MoneyWiseSecurity> {
67
68
69
70 private static final String TAB_PRICES = MoneyWiseUIResource.SECURITYPANEL_TAB_PRICES.getValue();
71
72
73
74
75 private final PrometheusFieldSet<MoneyWiseSecurity> theFieldSet;
76
77
78
79
80 private final MoneyWiseSecurityPriceTable thePrices;
81
82
83
84
85 private Boolean theClosedState = Boolean.FALSE;
86
87
88
89
90
91
92
93
94
95 public MoneyWiseSecurityDialog(final TethysUIFactory<?> pFactory,
96 final MoneyWiseView pView,
97 final PrometheusEditSet pEditSet,
98 final MoneyWiseAssetTable<MoneyWiseSecurity> pOwner) {
99
100 super(pFactory, pEditSet, pOwner);
101
102
103 theFieldSet = getFieldSet();
104 theFieldSet.setReporter(pOwner::showValidateError);
105
106
107 buildMainPanel(pFactory);
108
109
110 buildDetailsPanel(pFactory);
111
112
113 buildNotesPanel(pFactory);
114
115
116 thePrices = new MoneyWiseSecurityPriceTable(pView, getEditSet(), pOwner.getErrorPanel());
117 theFieldSet.newTable(TAB_PRICES, thePrices);
118
119
120 thePrices.getEventRegistrar().addEventListener(e -> {
121 updateActions();
122 fireStateChanged();
123 });
124 }
125
126
127
128
129
130
131 private void buildMainPanel(final TethysUIFactory<?> pFactory) {
132
133 final TethysUIFieldFactory myFields = pFactory.fieldFactory();
134 final TethysUIStringEditField myName = myFields.newStringField();
135 final TethysUIStringEditField myDesc = myFields.newStringField();
136
137
138 final TethysUIScrollButtonField<MoneyWiseAssetCategory> myTypeButton = myFields.newScrollField(MoneyWiseAssetCategory.class);
139 final TethysUIScrollButtonField<MoneyWisePayee> myParentButton = myFields.newScrollField(MoneyWisePayee.class);
140 final TethysUIScrollButtonField<MoneyWiseCurrency> myCurrencyButton = myFields.newScrollField(MoneyWiseCurrency.class);
141 final TethysUIIconButtonField<Boolean> myClosedButton = myFields.newIconField(Boolean.class);
142
143
144 theFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_NAME, myName, MoneyWiseSecurity::getName);
145 theFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_DESC, myDesc, MoneyWiseSecurity::getDesc);
146 theFieldSet.addField(MoneyWiseBasicResource.CATEGORY_NAME, myTypeButton, MoneyWiseSecurity::getCategory);
147 theFieldSet.addField(MoneyWiseBasicResource.ASSET_PARENT, myParentButton, MoneyWiseSecurity::getParent);
148 theFieldSet.addField(MoneyWiseStaticDataType.CURRENCY, myCurrencyButton, MoneyWiseSecurity::getAssetCurrency);
149 theFieldSet.addField(MoneyWiseBasicResource.ASSET_CLOSED, myClosedButton, MoneyWiseSecurity::isClosed);
150
151
152 myTypeButton.setMenuConfigurator(c -> buildSecTypeMenu(c, getItem()));
153 myParentButton.setMenuConfigurator(c -> buildParentMenu(c, getItem()));
154 myCurrencyButton.setMenuConfigurator(c -> buildCurrencyMenu(c, getItem()));
155 final Map<Boolean, TethysUIIconMapSet<Boolean>> myMapSets = MoneyWiseIcon.configureLockedIconButton(pFactory);
156 myClosedButton.setIconMapSet(() -> myMapSets.get(theClosedState));
157
158
159 myName.setValidator(this::isValidName);
160 myDesc.setValidator(this::isValidDesc);
161 }
162
163
164
165
166
167
168 private void buildDetailsPanel(final TethysUIFactory<?> pFactory) {
169
170 theFieldSet.newPanel(TAB_DETAILS);
171
172
173 final TethysUIFieldFactory myFields = pFactory.fieldFactory();
174 final TethysUIStringEditField mySymbol = myFields.newStringField();
175 final TethysUIPriceEditField myPrice = myFields.newPriceField();
176
177
178 final TethysUIScrollButtonField<MoneyWiseRegion> myRegionButton = myFields.newScrollField(MoneyWiseRegion.class);
179 final TethysUIScrollButtonField<MoneyWiseSecurity> myStockButton = myFields.newScrollField(MoneyWiseSecurity.class);
180
181
182 theFieldSet.addField(MoneyWiseAccountInfoClass.SYMBOL, mySymbol, MoneyWiseSecurity::getSymbol);
183 theFieldSet.addField(MoneyWiseAccountInfoClass.REGION, myRegionButton, MoneyWiseSecurity::getRegion);
184 theFieldSet.addField(MoneyWiseAccountInfoClass.UNDERLYINGSTOCK, myStockButton, MoneyWiseSecurity::getUnderlyingStock);
185 theFieldSet.addField(MoneyWiseAccountInfoClass.OPTIONPRICE, myPrice, MoneyWiseSecurity::getOptionPrice);
186
187
188 myRegionButton.setMenuConfigurator(c -> buildRegionMenu(c, getItem()));
189 myStockButton.setMenuConfigurator(c -> buildStockMenu(c, getItem()));
190 myPrice.setDeemedCurrency(() -> getItem().getCurrency());
191
192
193 mySymbol.setValidator(this::isValidSymbol);
194 }
195
196
197
198
199
200
201 private void buildNotesPanel(final TethysUIFactory<?> pFactory) {
202
203 final TethysUIFieldFactory myFields = pFactory.fieldFactory();
204 final TethysUICharArrayTextAreaField myNotes = myFields.newCharArrayAreaField();
205
206
207 theFieldSet.newTextArea(TAB_NOTES, MoneyWiseAccountInfoClass.NOTES, myNotes, MoneyWiseSecurity::getNotes);
208
209
210 myNotes.setValidator(this::isValidNotes);
211 }
212
213 @Override
214 public void refreshData() {
215
216 final MoneyWiseSecurity myItem = getItem();
217 if (myItem != null) {
218 final MoneyWiseSecurityList mySecurities = getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class);
219 setItem(mySecurities.findItemById(myItem.getIndexedId()));
220 }
221
222
223 thePrices.refreshData();
224
225
226 setEditable(false);
227 }
228
229 @Override
230 protected void adjustFields(final boolean isEditable) {
231
232 final MoneyWiseSecurity mySecurity = getItem();
233 final boolean bIsClosed = mySecurity.isClosed();
234 final boolean bIsActive = mySecurity.isActive();
235 final boolean bIsRelevant = mySecurity.isRelevant();
236
237
238 final boolean bShowClosed = bIsClosed || (bIsActive && !bIsRelevant);
239 theFieldSet.setFieldVisible(MoneyWiseBasicResource.ASSET_CLOSED, bShowClosed);
240
241
242 final boolean bEditClosed = bIsClosed
243 ? !mySecurity.getParent().isClosed()
244 : !bIsRelevant;
245 theFieldSet.setFieldEditable(MoneyWiseBasicResource.ASSET_CLOSED, isEditable && bEditClosed);
246 theClosedState = bEditClosed;
247
248
249 final boolean bShowDesc = isEditable || mySecurity.getDesc() != null;
250 theFieldSet.setFieldVisible(PrometheusDataResource.DATAITEM_FIELD_DESC, bShowDesc);
251
252
253 final boolean bShowNotes = isEditable || mySecurity.getNotes() != null;
254 theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.NOTES, bShowNotes);
255
256
257 boolean bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.SYMBOL);
258 boolean bShowField = bEditField || mySecurity.getSymbol() != null;
259 theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.SYMBOL, bShowField);
260 theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.SYMBOL, bEditField);
261
262
263 bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.REGION);
264 bShowField = bEditField || mySecurity.getRegion() != null;
265 theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.REGION, bShowField);
266 theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.REGION, bEditField);
267
268
269 bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.UNDERLYINGSTOCK);
270 bShowField = bEditField || mySecurity.getRegion() != null;
271 theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.UNDERLYINGSTOCK, bShowField);
272 theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.UNDERLYINGSTOCK, bEditField);
273
274
275 bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.OPTIONPRICE);
276 bShowField = bEditField || mySecurity.getRegion() != null;
277 theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.OPTIONPRICE, bShowField);
278 theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.OPTIONPRICE, bEditField);
279
280
281 theFieldSet.setFieldEditable(MoneyWiseBasicResource.CATEGORY_NAME, isEditable && !bIsActive);
282 theFieldSet.setFieldEditable(MoneyWiseStaticDataType.CURRENCY, isEditable && !bIsActive);
283
284
285 theFieldSet.setFieldEditable(MoneyWiseBasicResource.ASSET_PARENT, isEditable && !bIsClosed);
286 }
287
288
289
290
291
292
293
294
295 public static boolean isEditableField(final MoneyWiseSecurity pSecurity,
296 final MoneyWiseAccountInfoClass pField) {
297
298 final MoneyWiseValidateSecurity myValidator = (MoneyWiseValidateSecurity) pSecurity.getList().getValidator();
299 final MetisFieldRequired isRequired = myValidator.isClassRequired(pField);
300 return !isRequired.equals(MetisFieldRequired.NOTALLOWED);
301 }
302
303 @Override
304 protected void updateField(final PrometheusFieldSetEvent pUpdate) throws OceanusException {
305
306 final MetisDataFieldId myField = pUpdate.getFieldId();
307 final MoneyWiseSecurity mySecurity = getItem();
308
309
310 if (PrometheusDataResource.DATAITEM_FIELD_NAME.equals(myField)) {
311
312 mySecurity.setName(pUpdate.getValue(String.class));
313 } else if (PrometheusDataResource.DATAITEM_FIELD_DESC.equals(myField)) {
314
315 mySecurity.setDescription(pUpdate.getValue(String.class));
316 } else if (MoneyWiseBasicResource.CATEGORY_NAME.equals(myField)) {
317
318 mySecurity.setCategory(pUpdate.getValue(MoneyWiseSecurityType.class));
319 mySecurity.autoCorrect();
320 } else if (MoneyWiseBasicResource.ASSET_PARENT.equals(myField)) {
321
322 mySecurity.setParent(pUpdate.getValue(MoneyWisePayee.class));
323 } else if (MoneyWiseStaticDataType.CURRENCY.equals(myField)) {
324
325 mySecurity.setAssetCurrency(pUpdate.getValue(MoneyWiseCurrency.class));
326 } else if (MoneyWiseBasicResource.ASSET_CLOSED.equals(myField)) {
327
328 mySecurity.setClosed(pUpdate.getValue(Boolean.class));
329 } else if (MoneyWiseAccountInfoClass.SYMBOL.equals(myField)) {
330
331 mySecurity.setSymbol(pUpdate.getValue(String.class));
332 } else if (MoneyWiseAccountInfoClass.REGION.equals(myField)) {
333
334 mySecurity.setRegion(pUpdate.getValue(MoneyWiseRegion.class));
335 } else if (MoneyWiseAccountInfoClass.UNDERLYINGSTOCK.equals(myField)) {
336
337 mySecurity.setUnderlyingStock(pUpdate.getValue(MoneyWiseSecurity.class));
338 } else if (MoneyWiseAccountInfoClass.OPTIONPRICE.equals(myField)) {
339
340 mySecurity.setOptionPrice(pUpdate.getValue(OceanusPrice.class));
341 } else if (MoneyWiseAccountInfoClass.NOTES.equals(myField)) {
342
343 mySecurity.setNotes(pUpdate.getValue(char[].class));
344 }
345 }
346
347 @Override
348 protected void declareGoToItems(final boolean pUpdates) {
349 final MoneyWiseSecurity myItem = getItem();
350 final MoneyWisePayee myParent = myItem.getParent();
351 if (!pUpdates) {
352 final MoneyWiseSecurityType myType = myItem.getCategory();
353 final MoneyWiseCurrency myCurrency = myItem.getAssetCurrency();
354 final MoneyWiseRegion myRegion = myItem.getRegion();
355 declareGoToItem(myType);
356 declareGoToItem(myRegion);
357 declareGoToItem(myCurrency);
358 }
359 declareGoToItem(myParent);
360 }
361
362
363
364
365
366
367
368 public void addNewPrice(final MoneyWiseSecurity pSecurity) throws OceanusException {
369
370 thePrices.addNewPrice(pSecurity);
371 }
372
373 @Override
374 public void setEditable(final boolean isEditable) {
375
376 thePrices.setEditable(isEditable);
377
378
379 super.setEditable(isEditable);
380 }
381
382 @Override
383 protected void refreshAfterUpdate() {
384
385 super.refreshAfterUpdate();
386
387
388 thePrices.refreshAfterUpdate();
389 }
390
391
392
393
394
395
396
397 public void buildSecTypeMenu(final TethysUIScrollMenu<MoneyWiseAssetCategory> pMenu,
398 final MoneyWiseSecurity pSecurity) {
399
400 pMenu.removeAllItems();
401
402
403 final MoneyWiseSecurityType myCurr = pSecurity.getCategory();
404 TethysUIScrollItem<MoneyWiseAssetCategory> myActive = null;
405
406
407 final MoneyWiseSecurityTypeList myTypes = getDataList(MoneyWiseStaticDataType.SECURITYTYPE, MoneyWiseSecurityTypeList.class);
408
409
410 final Iterator<MoneyWiseSecurityType> myIterator = myTypes.iterator();
411 while (myIterator.hasNext()) {
412 final MoneyWiseSecurityType myType = myIterator.next();
413
414
415 final boolean bIgnore = myType.isDeleted() || !myType.getEnabled();
416 if (bIgnore) {
417 continue;
418 }
419
420
421 final TethysUIScrollItem<MoneyWiseAssetCategory> myItem = pMenu.addItem(myType);
422
423
424 if (myType.equals(myCurr)) {
425
426 myActive = myItem;
427 }
428 }
429
430
431 if (myActive != null) {
432 myActive.scrollToItem();
433 }
434 }
435
436
437
438
439
440
441
442 public void buildParentMenu(final TethysUIScrollMenu<MoneyWisePayee> pMenu,
443 final MoneyWiseSecurity pSecurity) {
444
445 pMenu.removeAllItems();
446
447
448 final MoneyWiseSecurityClass myType = pSecurity.getCategoryClass();
449 final MoneyWisePayee myCurr = pSecurity.getParent();
450 TethysUIScrollItem<MoneyWisePayee> myActive = null;
451
452
453 final MoneyWisePayeeList myPayees = getDataList(MoneyWiseBasicDataType.PAYEE, MoneyWisePayeeList.class);
454
455
456 final Iterator<MoneyWisePayee> myIterator = myPayees.iterator();
457 while (myIterator.hasNext()) {
458 final MoneyWisePayee myPayee = myIterator.next();
459
460
461 boolean bIgnore = myPayee.isDeleted() || !myPayee.getCategoryClass().canParentSecurity(myType);
462 bIgnore |= myPayee.isClosed();
463 if (bIgnore) {
464 continue;
465 }
466
467
468 final TethysUIScrollItem<MoneyWisePayee> myItem = pMenu.addItem(myPayee);
469
470
471 if (myPayee.equals(myCurr)) {
472
473 myActive = myItem;
474 }
475 }
476
477
478 if (myActive != null) {
479 myActive.scrollToItem();
480 }
481 }
482
483
484
485
486
487
488
489 public void buildRegionMenu(final TethysUIScrollMenu<MoneyWiseRegion> pMenu,
490 final MoneyWiseSecurity pSecurity) {
491
492 pMenu.removeAllItems();
493
494
495 final MoneyWiseRegion myCurr = pSecurity.getRegion();
496 TethysUIScrollItem<MoneyWiseRegion> myActive = null;
497
498
499 final MoneyWiseRegionList myRegions = getDataList(MoneyWiseBasicDataType.REGION, MoneyWiseRegionList.class);
500
501
502 final Iterator<MoneyWiseRegion> myIterator = myRegions.iterator();
503 while (myIterator.hasNext()) {
504 final MoneyWiseRegion myRegion = myIterator.next();
505
506
507 final boolean bIgnore = myRegion.isDeleted();
508 if (bIgnore) {
509 continue;
510 }
511
512
513 final TethysUIScrollItem<MoneyWiseRegion> myItem = pMenu.addItem(myRegion);
514
515
516 if (myRegion.equals(myCurr)) {
517
518 myActive = myItem;
519 }
520 }
521
522
523 if (myActive != null) {
524 myActive.scrollToItem();
525 }
526 }
527
528
529
530
531
532
533
534 public void buildStockMenu(final TethysUIScrollMenu<MoneyWiseSecurity> pMenu,
535 final MoneyWiseSecurity pSecurity) {
536
537 pMenu.removeAllItems();
538
539
540 final MoneyWiseSecurity myCurr = pSecurity.getUnderlyingStock();
541 TethysUIScrollItem<MoneyWiseSecurity> myActive = null;
542
543
544 final MoneyWiseSecurityList mySecurities = getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class);
545
546
547 final Iterator<MoneyWiseSecurity> myIterator = mySecurities.iterator();
548 while (myIterator.hasNext()) {
549 final MoneyWiseSecurity mySecurity = myIterator.next();
550
551
552 boolean bIgnore = mySecurity.isDeleted();
553 bIgnore |= !mySecurity.getCategoryClass().isShares();
554 if (bIgnore) {
555 continue;
556 }
557
558
559 final TethysUIScrollItem<MoneyWiseSecurity> myItem = pMenu.addItem(mySecurity);
560
561
562 if (mySecurity.equals(myCurr)) {
563
564 myActive = myItem;
565 }
566 }
567
568
569 if (myActive != null) {
570 myActive.scrollToItem();
571 }
572 }
573
574
575
576
577
578
579
580 public void buildCurrencyMenu(final TethysUIScrollMenu<MoneyWiseCurrency> pMenu,
581 final MoneyWiseSecurity pSecurity) {
582
583 pMenu.removeAllItems();
584
585
586 final MoneyWiseCurrency myCurr = pSecurity.getAssetCurrency();
587 TethysUIScrollItem<MoneyWiseCurrency> myActive = null;
588
589
590 final MoneyWiseCurrencyList myCurrencies = getDataList(MoneyWiseStaticDataType.CURRENCY, MoneyWiseCurrencyList.class);
591
592
593 final Iterator<MoneyWiseCurrency> myIterator = myCurrencies.iterator();
594 while (myIterator.hasNext()) {
595 final MoneyWiseCurrency myCurrency = myIterator.next();
596
597
598 final boolean bIgnore = myCurrency.isDeleted() || !myCurrency.getEnabled();
599 if (bIgnore) {
600 continue;
601 }
602
603
604 final TethysUIScrollItem<MoneyWiseCurrency> myItem = pMenu.addItem(myCurrency);
605
606
607 if (myCurrency.equals(myCurr)) {
608
609 myActive = myItem;
610 }
611 }
612
613
614 if (myActive != null) {
615 myActive.scrollToItem();
616 }
617 }
618 }