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.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.data.basic.MoneyWiseBasicDataType;
25 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory;
26 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransCategoryClass;
27 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysis;
28 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransCategoryBucket;
29 import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisTransCategoryBucket.MoneyWiseAnalysisTransCategoryBucketList;
30 import io.github.tonywasher.joceanus.moneywise.lethe.views.MoneyWiseAnalysisFilter;
31 import io.github.tonywasher.joceanus.moneywise.lethe.views.MoneyWiseAnalysisFilter.MoneyWiseAnalysisTransCategoryFilter;
32 import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
33 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIComponent;
34 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIConstant;
35 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIEvent;
36 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIScrollButtonManager;
37 import io.github.tonywasher.joceanus.tethys.api.control.TethysUILabel;
38 import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
39 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
40 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
41 import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollSubMenu;
42 import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIBoxPaneManager;
43
44 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.Map;
47
48
49
50
51 public class MoneyWiseTransCategoryAnalysisSelect
52 implements MoneyWiseAnalysisFilterSelection, OceanusEventProvider<PrometheusDataEvent> {
53
54
55
56 private static final String NLS_CATEGORY = MoneyWiseBasicDataType.TRANSCATEGORY.getItemName();
57
58
59
60
61 private final OceanusEventManager<PrometheusDataEvent> theEventManager;
62
63
64
65
66 private final TethysUIBoxPaneManager thePanel;
67
68
69
70
71 private final TethysUIScrollButtonManager<MoneyWiseAnalysisTransCategoryBucket> theButton;
72
73
74
75
76 private final TethysUIScrollMenu<MoneyWiseAnalysisTransCategoryBucket> theCategoryMenu;
77
78
79
80
81 private MoneyWiseAnalysisTransCategoryBucketList theCategories;
82
83
84
85
86 private MoneyWiseEventState theState;
87
88
89
90
91 private MoneyWiseEventState theSavePoint;
92
93
94
95
96
97
98 protected MoneyWiseTransCategoryAnalysisSelect(final TethysUIFactory<?> pFactory) {
99
100 theButton = pFactory.buttonFactory().newScrollButton(MoneyWiseAnalysisTransCategoryBucket.class);
101
102
103 final TethysUILabel myLabel = pFactory.controlFactory().newLabel(NLS_CATEGORY + TethysUIConstant.STR_COLON);
104
105
106 theEventManager = new OceanusEventManager<>();
107
108
109 thePanel = pFactory.paneFactory().newHBoxPane();
110 thePanel.addSpacer();
111 thePanel.addNode(myLabel);
112 thePanel.addNode(theButton);
113
114
115 theState = new MoneyWiseEventState();
116 theState.applyState();
117
118
119 theCategoryMenu = theButton.getMenu();
120
121
122 final OceanusEventRegistrar<TethysUIEvent> myRegistrar = theButton.getEventRegistrar();
123 myRegistrar.addEventListener(TethysUIEvent.NEWVALUE, e -> handleNewCategory());
124 theButton.setMenuConfigurator(e -> buildCategoryMenu());
125 }
126
127 @Override
128 public TethysUIComponent getUnderlying() {
129 return thePanel;
130 }
131
132 @Override
133 public OceanusEventRegistrar<PrometheusDataEvent> getEventRegistrar() {
134 return theEventManager.getEventRegistrar();
135 }
136
137 @Override
138 public MoneyWiseAnalysisTransCategoryFilter getFilter() {
139 return theState.getFilter();
140 }
141
142 @Override
143 public boolean isAvailable() {
144 return theCategories != null
145 && !theCategories.isEmpty();
146 }
147
148
149
150
151 public void createSavePoint() {
152
153 theSavePoint = new MoneyWiseEventState(theState);
154 }
155
156
157
158
159 public void restoreSavePoint() {
160
161 theState = new MoneyWiseEventState(theSavePoint);
162
163
164 theState.applyState();
165 }
166
167 @Override
168 public void setEnabled(final boolean bEnabled) {
169
170 theButton.setEnabled(bEnabled && isAvailable());
171 }
172
173 @Override
174 public void setVisible(final boolean pVisible) {
175 thePanel.setVisible(pVisible);
176 }
177
178
179
180
181
182
183 public void setAnalysis(final MoneyWiseAnalysis pAnalysis) {
184
185 theCategories = pAnalysis.getTransCategories();
186
187
188 MoneyWiseAnalysisTransCategoryBucket myCategory = theState.getEventCategory();
189
190
191 myCategory = myCategory != null
192 ? theCategories.getMatchingCategory(myCategory.getTransactionCategory())
193 : theCategories.getDefaultCategory();
194
195
196 theState.setTheCategory(myCategory);
197 theState.setDateRange(pAnalysis.getDateRange());
198 theState.applyState();
199 }
200
201 @Override
202 public void setFilter(final MoneyWiseAnalysisFilter<?, ?> pFilter) {
203
204 if (pFilter instanceof MoneyWiseAnalysisTransCategoryFilter) {
205
206 final MoneyWiseAnalysisTransCategoryFilter myFilter = (MoneyWiseAnalysisTransCategoryFilter) pFilter;
207
208
209 MoneyWiseAnalysisTransCategoryBucket myCategory = myFilter.getBucket();
210
211
212 myCategory = theCategories.getMatchingCategory(myCategory.getTransactionCategory());
213
214
215 theState.setTheCategory(myCategory);
216 theState.setDateRange(myFilter.getDateRange());
217 theState.applyState();
218 }
219 }
220
221
222
223
224 private void handleNewCategory() {
225
226 if (theState.setCategory(theButton.getValue())) {
227 theState.applyState();
228 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
229 }
230 }
231
232
233
234
235 private void buildCategoryMenu() {
236
237 theCategoryMenu.removeAllItems();
238
239
240 final Map<String, TethysUIScrollSubMenu<MoneyWiseAnalysisTransCategoryBucket>> myMap = new HashMap<>();
241
242
243 final MoneyWiseAnalysisTransCategoryBucket myCurrent = theState.getEventCategory();
244 TethysUIScrollItem<MoneyWiseAnalysisTransCategoryBucket> myActive = null;
245
246
247 final Iterator<MoneyWiseAnalysisTransCategoryBucket> myIterator = theCategories.iterator();
248 while (myIterator.hasNext()) {
249 final MoneyWiseAnalysisTransCategoryBucket myBucket = myIterator.next();
250
251
252 final MoneyWiseTransCategoryClass myClass = myBucket.getTransactionCategoryType().getCategoryClass();
253 if (myClass.canParentCategory()) {
254 continue;
255 }
256
257
258 final MoneyWiseTransCategory myCategory = myBucket.getTransactionCategory();
259 final MoneyWiseTransCategory myParent = myCategory.getParentCategory();
260 final String myParentName = myParent.getName();
261 final TethysUIScrollSubMenu<MoneyWiseAnalysisTransCategoryBucket> myMenu = myMap.computeIfAbsent(myParentName, theCategoryMenu::addSubMenu);
262
263
264 final TethysUIScrollItem<MoneyWiseAnalysisTransCategoryBucket> myItem = myMenu.getSubMenu().addItem(myBucket, myCategory.getSubCategory());
265
266
267 if (myBucket.equals(myCurrent)) {
268
269 myActive = myItem;
270 }
271 }
272
273
274 if (myActive != null) {
275 myActive.scrollToItem();
276 }
277 }
278
279
280
281
282 private final class MoneyWiseEventState {
283
284
285
286 private MoneyWiseAnalysisTransCategoryBucket theCategory;
287
288
289
290
291 private OceanusDateRange theDateRange;
292
293
294
295
296 private MoneyWiseAnalysisTransCategoryFilter theFilter;
297
298
299
300
301 private MoneyWiseEventState() {
302 }
303
304
305
306
307
308
309 private MoneyWiseEventState(final MoneyWiseEventState pState) {
310
311 theCategory = pState.getEventCategory();
312 theDateRange = pState.getDateRange();
313 theFilter = pState.getFilter();
314 }
315
316
317
318
319
320
321 private MoneyWiseAnalysisTransCategoryBucket getEventCategory() {
322 return theCategory;
323 }
324
325
326
327
328
329
330 private OceanusDateRange getDateRange() {
331 return theDateRange;
332 }
333
334
335
336
337
338
339 private MoneyWiseAnalysisTransCategoryFilter getFilter() {
340 return theFilter;
341 }
342
343
344
345
346
347
348
349 private boolean setCategory(final MoneyWiseAnalysisTransCategoryBucket pCategory) {
350
351 if (!MetisDataDifference.isEqual(pCategory, theCategory)) {
352 setTheCategory(pCategory);
353 return true;
354 }
355 return false;
356 }
357
358
359
360
361
362
363 private void setTheCategory(final MoneyWiseAnalysisTransCategoryBucket pCategory) {
364
365 theCategory = pCategory;
366 if (theCategory != null) {
367 theFilter = new MoneyWiseAnalysisTransCategoryFilter(theCategory);
368 theFilter.setDateRange(theDateRange);
369 } else {
370 theFilter = null;
371 }
372 }
373
374
375
376
377
378
379
380 private void setDateRange(final OceanusDateRange pRange) {
381
382 theDateRange = pRange;
383 if (theFilter != null) {
384 theFilter.setDateRange(theDateRange);
385 }
386 }
387
388
389
390
391 private void applyState() {
392
393 setEnabled(true);
394 theButton.setValue(theCategory);
395 }
396 }
397 }