1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.moneywise.atlas.ui.controls;
18
19 import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
20 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventManager;
21 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar;
22 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar.OceanusEventProvider;
23 import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
24 import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysis;
25 import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisCashBucket;
26 import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisCashBucket.MoneyWiseXAnalysisCashBucketList;
27 import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisCashCategoryBucket;
28 import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisCashCategoryBucket.MoneyWiseXAnalysisCashCategoryBucketList;
29 import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter;
30 import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter.MoneyWiseXAnalysisCashFilter;
31 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
32 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCashCategory;
33 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCashCategoryClass;
34 import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
35 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIComponent;
36 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIConstant;
37 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
38 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButtonFactory;
39 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIScrollButtonManager;
40 import io.github.tonywasher.joceanus.tethys.api.control.TethysUIControlFactory;
41 import io.github.tonywasher.joceanus.tethys.api.control.TethysUILabel;
42 import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
43 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
44 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
45 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollSubMenu;
46 import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIBoxPaneManager;
47
48 import java.util.HashMap;
49 import java.util.Iterator;
50 import java.util.Map;
51
52
53
54
55 public class MoneyWiseXCashAnalysisSelect
56 implements MoneyWiseXAnalysisFilterSelection, OceanusEventProvider<PrometheusDataEvent> {
57
58
59
60 private static final String NLS_CATEGORY = MoneyWiseBasicDataType.CASHCATEGORY.getItemName();
61
62
63
64
65 private static final String NLS_CASH = MoneyWiseBasicDataType.CASH.getItemName();
66
67
68
69
70 private final OceanusEventManager<PrometheusDataEvent> theEventManager;
71
72
73
74
75 private final TethysUIBoxPaneManager thePanel;
76
77
78
79
80 private final TethysUIScrollButtonManager<MoneyWiseXAnalysisCashBucket> theCashButton;
81
82
83
84
85 private final TethysUIScrollButtonManager<MoneyWiseCashCategory> theCatButton;
86
87
88
89
90 private final TethysUIScrollMenu<MoneyWiseCashCategory> theCategoryMenu;
91
92
93
94
95 private final TethysUIScrollMenu<MoneyWiseXAnalysisCashBucket> theCashMenu;
96
97
98
99
100 private MoneyWiseXAnalysisCashCategoryBucketList theCategories;
101
102
103
104
105 private MoneyWiseXAnalysisCashBucketList theCash;
106
107
108
109
110 private MoneyWiseCashState theState;
111
112
113
114
115 private MoneyWiseCashState theSavePoint;
116
117
118
119
120
121
122 protected MoneyWiseXCashAnalysisSelect(final TethysUIFactory<?> pFactory) {
123
124 final TethysUIButtonFactory<?> myButtons = pFactory.buttonFactory();
125 theCashButton = myButtons.newScrollButton(MoneyWiseXAnalysisCashBucket.class);
126
127
128 theCatButton = myButtons.newScrollButton(MoneyWiseCashCategory.class);
129
130
131 theEventManager = new OceanusEventManager<>();
132
133
134 final TethysUIControlFactory myControls = pFactory.controlFactory();
135 final TethysUILabel myCatLabel = myControls.newLabel(NLS_CATEGORY + TethysUIConstant.STR_COLON);
136 final TethysUILabel myCshLabel = myControls.newLabel(NLS_CASH + TethysUIConstant.STR_COLON);
137
138
139 thePanel = pFactory.paneFactory().newHBoxPane();
140 thePanel.addSpacer();
141 thePanel.addNode(myCatLabel);
142 thePanel.addNode(theCatButton);
143 thePanel.addStrut();
144 thePanel.addNode(myCshLabel);
145 thePanel.addNode(theCashButton);
146
147
148 theState = new MoneyWiseCashState();
149 theState.applyState();
150
151
152 theCategoryMenu = theCatButton.getMenu();
153 theCashMenu = theCashButton.getMenu();
154
155
156 OceanusEventRegistrar<TethysUIEvent> myRegistrar = theCatButton.getEventRegistrar();
157 myRegistrar.addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewCategory());
158 theCatButton.setMenuConfigurator(e -> buildCategoryMenu());
159 myRegistrar = theCashButton.getEventRegistrar();
160 myRegistrar.addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewCash());
161 theCashButton.setMenuConfigurator(e -> buildCashMenu());
162 }
163
164 @Override
165 public TethysUIComponent getUnderlying() {
166 return thePanel;
167 }
168
169 @Override
170 public OceanusEventRegistrar<PrometheusDataEvent> getEventRegistrar() {
171 return theEventManager.getEventRegistrar();
172 }
173
174 @Override
175 public MoneyWiseXAnalysisCashFilter getFilter() {
176 return theState.getFilter();
177 }
178
179 @Override
180 public boolean isAvailable() {
181 return theCash != null
182 && !theCash.isEmpty();
183 }
184
185
186
187
188 protected void createSavePoint() {
189
190 theSavePoint = new MoneyWiseCashState(theState);
191 }
192
193
194
195
196 protected void restoreSavePoint() {
197
198 theState = new MoneyWiseCashState(theSavePoint);
199
200
201 theState.applyState();
202 }
203
204 @Override
205 public void setEnabled(final boolean bEnabled) {
206
207 final boolean csAvailable = bEnabled && isAvailable();
208
209
210 theCashButton.setEnabled(csAvailable);
211 theCatButton.setEnabled(csAvailable);
212 }
213
214 @Override
215 public void setVisible(final boolean pVisible) {
216 thePanel.setVisible(pVisible);
217 }
218
219
220
221
222
223
224 public void setAnalysis(final MoneyWiseXAnalysis pAnalysis) {
225
226 theCategories = pAnalysis.getCashCategories();
227 theCash = pAnalysis.getCash();
228
229
230 MoneyWiseXAnalysisCashBucket myCash = theState.getCash();
231
232
233 myCash = myCash != null
234 ? theCash.getMatchingCash(myCash.getAccount())
235 : theCash.getDefaultCash();
236
237
238 theState.setTheCash(myCash);
239 theState.setDateRange(pAnalysis.getDateRange());
240 theState.applyState();
241 }
242
243 @Override
244 public void setFilter(final MoneyWiseXAnalysisFilter<?, ?> pFilter) {
245
246 if (pFilter instanceof MoneyWiseXAnalysisCashFilter myFilter) {
247
248 MoneyWiseXAnalysisCashBucket myCash = myFilter.getBucket();
249
250
251 myCash = theCash.getMatchingCash(myCash.getAccount());
252
253
254 theState.setTheCash(myCash);
255 theState.setDateRange(myFilter.getDateRange());
256 theState.applyState();
257 }
258 }
259
260
261
262
263
264
265
266 protected MoneyWiseXAnalysisCashBucket getDefaultCash(final MoneyWiseCashCategory pCategory) {
267 return theCash.getDefaultCash(pCategory);
268 }
269
270
271
272
273 private void handleNewCategory() {
274
275 if (theState.setCategory(theCatButton.getValue())) {
276 theState.applyState();
277 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
278 }
279 }
280
281
282
283
284 private void handleNewCash() {
285
286 if (theState.setCash(theCashButton.getValue())) {
287 theState.applyState();
288 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
289 }
290 }
291
292
293
294
295 private void buildCategoryMenu() {
296
297 theCategoryMenu.removeAllItems();
298
299
300 final Map<String, TethysUIScrollSubMenu<MoneyWiseCashCategory>> myMap = new HashMap<>();
301
302
303 final MoneyWiseCashCategory myCurrent = theState.getCategory();
304 TethysUIScrollItem<MoneyWiseCashCategory> myActive = null;
305
306
307 final Iterator<MoneyWiseXAnalysisCashCategoryBucket> myIterator = theCategories.iterator();
308 while (myIterator.hasNext()) {
309 final MoneyWiseXAnalysisCashCategoryBucket myBucket = myIterator.next();
310
311
312 if (myBucket.getAccountCategory().isCategoryClass(MoneyWiseCashCategoryClass.PARENT)) {
313 continue;
314 }
315
316
317 final MoneyWiseCashCategory myParent = myBucket.getAccountCategory().getParentCategory();
318 final String myParentName = myParent.getName();
319 final TethysUIScrollSubMenu<MoneyWiseCashCategory> myMenu = myMap.computeIfAbsent(myParentName, theCategoryMenu::addSubMenu);
320
321
322 final MoneyWiseCashCategory myCategory = myBucket.getAccountCategory();
323 final TethysUIScrollItem<MoneyWiseCashCategory> myItem = myMenu.getSubMenu().addItem(myCategory, myCategory.getSubCategory());
324
325
326 if (myCategory.equals(myCurrent)) {
327
328 myActive = myItem;
329 }
330 }
331
332
333 if (myActive != null) {
334 myActive.scrollToItem();
335 }
336 }
337
338
339
340
341 private void buildCashMenu() {
342
343 theCashMenu.removeAllItems();
344
345
346 final MoneyWiseCashCategory myCategory = theState.getCategory();
347 final MoneyWiseXAnalysisCashBucket myCash = theState.getCash();
348
349
350 TethysUIScrollItem<MoneyWiseXAnalysisCashBucket> myActive = null;
351
352
353 final Iterator<MoneyWiseXAnalysisCashBucket> myIterator = theCash.iterator();
354 while (myIterator.hasNext()) {
355 final MoneyWiseXAnalysisCashBucket myBucket = myIterator.next();
356
357
358 if (!MetisDataDifference.isEqual(myCategory, myBucket.getCategory())) {
359 continue;
360 }
361
362
363 final TethysUIScrollItem<MoneyWiseXAnalysisCashBucket> myItem = theCashMenu.addItem(myBucket);
364
365
366 if (myBucket.equals(myCash)) {
367
368 myActive = myItem;
369 }
370 }
371
372
373 if (myActive != null) {
374 myActive.scrollToItem();
375 }
376 }
377
378
379
380
381 private final class MoneyWiseCashState {
382
383
384
385 private MoneyWiseCashCategory theCategory;
386
387
388
389
390 private MoneyWiseXAnalysisCashBucket theCash;
391
392
393
394
395 private OceanusDateRange theDateRange;
396
397
398
399
400 private MoneyWiseXAnalysisCashFilter theFilter;
401
402
403
404
405 private MoneyWiseCashState() {
406 }
407
408
409
410
411
412
413 private MoneyWiseCashState(final MoneyWiseCashState pState) {
414
415 theCash = pState.getCash();
416 theCategory = pState.getCategory();
417 theDateRange = pState.getDateRange();
418 theFilter = pState.getFilter();
419 }
420
421
422
423
424
425
426 private MoneyWiseXAnalysisCashBucket getCash() {
427 return theCash;
428 }
429
430
431
432
433
434
435 private MoneyWiseCashCategory getCategory() {
436 return theCategory;
437 }
438
439
440
441
442
443
444 private OceanusDateRange getDateRange() {
445 return theDateRange;
446 }
447
448
449
450
451
452
453 private MoneyWiseXAnalysisCashFilter getFilter() {
454 return theFilter;
455 }
456
457
458
459
460
461
462
463 private boolean setCash(final MoneyWiseXAnalysisCashBucket pCash) {
464
465 if (!MetisDataDifference.isEqual(pCash, theCash)) {
466
467 setTheCash(pCash);
468 return true;
469 }
470 return false;
471 }
472
473
474
475
476
477
478 private void setTheCash(final MoneyWiseXAnalysisCashBucket pCash) {
479
480 final MoneyWiseCashCategory myCategory = pCash == null
481 ? null
482 : pCash.getCategory();
483 setTheCash(myCategory, pCash);
484 }
485
486
487
488
489
490
491
492 private void setTheCash(final MoneyWiseCashCategory pCategory,
493 final MoneyWiseXAnalysisCashBucket pCash) {
494
495 theCash = pCash;
496 theCategory = pCategory;
497
498
499 if (theCash != null) {
500 theFilter = new MoneyWiseXAnalysisCashFilter(theCash);
501 theFilter.setDateRange(theDateRange);
502 } else {
503 theFilter = null;
504 }
505 }
506
507
508
509
510
511
512
513 private boolean setCategory(final MoneyWiseCashCategory pCategory) {
514
515 if (!MetisDataDifference.isEqual(pCategory, theCategory)) {
516 setTheCash(pCategory, getDefaultCash(pCategory));
517 return true;
518 }
519 return false;
520 }
521
522
523
524
525
526
527 private void setDateRange(final OceanusDateRange pRange) {
528
529 theDateRange = pRange;
530 if (theFilter != null) {
531 theFilter.setDateRange(theDateRange);
532 }
533 }
534
535
536
537
538 private void applyState() {
539
540 setEnabled(true);
541 theCashButton.setValue(theCash);
542 theCatButton.setValue(theCategory);
543 }
544 }
545 }