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.MoneyWiseXAnalysisTransCategoryBucket;
26 import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisTransCategoryBucket.MoneyWiseXAnalysisTransCategoryBucketList;
27 import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter;
28 import io.github.tonywasher.joceanus.moneywise.atlas.views.MoneyWiseXAnalysisFilter.MoneyWiseXAnalysisTransCategoryFilter;
29 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
30 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory;
31 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransCategoryClass;
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 MoneyWiseXTransCategoryAnalysisSelect
52 implements MoneyWiseXAnalysisFilterSelection, 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<MoneyWiseXAnalysisTransCategoryBucket> theButton;
72
73
74
75
76 private final TethysUIScrollMenu<MoneyWiseXAnalysisTransCategoryBucket> theCategoryMenu;
77
78
79
80
81 private MoneyWiseXAnalysisTransCategoryBucketList 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 MoneyWiseXTransCategoryAnalysisSelect(final TethysUIFactory<?> pFactory) {
99
100 theButton = pFactory.buttonFactory().newScrollButton(MoneyWiseXAnalysisTransCategoryBucket.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 MoneyWiseXAnalysisTransCategoryFilter 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 MoneyWiseXAnalysis pAnalysis) {
184
185 theCategories = pAnalysis.getTransCategories();
186
187
188 MoneyWiseXAnalysisTransCategoryBucket 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 MoneyWiseXAnalysisFilter<?, ?> pFilter) {
203
204 if (pFilter instanceof MoneyWiseXAnalysisTransCategoryFilter myFilter) {
205
206 MoneyWiseXAnalysisTransCategoryBucket myCategory = myFilter.getBucket();
207
208
209 myCategory = theCategories.getMatchingCategory(myCategory.getTransactionCategory());
210
211
212 theState.setTheCategory(myCategory);
213 theState.setDateRange(myFilter.getDateRange());
214 theState.applyState();
215 }
216 }
217
218
219
220
221 private void handleNewCategory() {
222
223 if (theState.setCategory(theButton.getValue())) {
224 theState.applyState();
225 theEventManager.fireEvent(PrometheusDataEvent.SELECTIONCHANGED);
226 }
227 }
228
229
230
231
232 private void buildCategoryMenu() {
233
234 theCategoryMenu.removeAllItems();
235
236
237 final Map<String, TethysUIScrollSubMenu<MoneyWiseXAnalysisTransCategoryBucket>> myMap = new HashMap<>();
238
239
240 final MoneyWiseXAnalysisTransCategoryBucket myCurrent = theState.getEventCategory();
241 TethysUIScrollItem<MoneyWiseXAnalysisTransCategoryBucket> myActive = null;
242
243
244 final Iterator<MoneyWiseXAnalysisTransCategoryBucket> myIterator = theCategories.iterator();
245 while (myIterator.hasNext()) {
246 final MoneyWiseXAnalysisTransCategoryBucket myBucket = myIterator.next();
247
248
249 final MoneyWiseTransCategoryClass myClass = myBucket.getTransactionCategoryType().getCategoryClass();
250 if (myClass.canParentCategory()) {
251 continue;
252 }
253
254
255 final MoneyWiseTransCategory myCategory = myBucket.getTransactionCategory();
256 final MoneyWiseTransCategory myParent = myCategory.getParentCategory();
257 final String myParentName = myParent.getName();
258 final TethysUIScrollSubMenu<MoneyWiseXAnalysisTransCategoryBucket> myMenu = myMap.computeIfAbsent(myParentName, theCategoryMenu::addSubMenu);
259
260
261 final TethysUIScrollItem<MoneyWiseXAnalysisTransCategoryBucket> myItem = myMenu.getSubMenu().addItem(myBucket, myCategory.getSubCategory());
262
263
264 if (myBucket.equals(myCurrent)) {
265
266 myActive = myItem;
267 }
268 }
269
270
271 if (myActive != null) {
272 myActive.scrollToItem();
273 }
274 }
275
276
277
278
279 private final class MoneyWiseEventState {
280
281
282
283 private MoneyWiseXAnalysisTransCategoryBucket theCategory;
284
285
286
287
288 private OceanusDateRange theDateRange;
289
290
291
292
293 private MoneyWiseXAnalysisTransCategoryFilter theFilter;
294
295
296
297
298 private MoneyWiseEventState() {
299 }
300
301
302
303
304
305
306 private MoneyWiseEventState(final MoneyWiseEventState pState) {
307
308 theCategory = pState.getEventCategory();
309 theDateRange = pState.getDateRange();
310 theFilter = pState.getFilter();
311 }
312
313
314
315
316
317
318 private MoneyWiseXAnalysisTransCategoryBucket getEventCategory() {
319 return theCategory;
320 }
321
322
323
324
325
326
327 private OceanusDateRange getDateRange() {
328 return theDateRange;
329 }
330
331
332
333
334
335
336 private MoneyWiseXAnalysisTransCategoryFilter getFilter() {
337 return theFilter;
338 }
339
340
341
342
343
344
345
346 private boolean setCategory(final MoneyWiseXAnalysisTransCategoryBucket pCategory) {
347
348 if (!MetisDataDifference.isEqual(pCategory, theCategory)) {
349 setTheCategory(pCategory);
350 return true;
351 }
352 return false;
353 }
354
355
356
357
358
359
360 private void setTheCategory(final MoneyWiseXAnalysisTransCategoryBucket pCategory) {
361
362 theCategory = pCategory;
363 if (theCategory != null) {
364 theFilter = new MoneyWiseXAnalysisTransCategoryFilter(theCategory);
365 theFilter.setDateRange(theDateRange);
366 } else {
367 theFilter = null;
368 }
369 }
370
371
372
373
374
375
376
377 private void setDateRange(final OceanusDateRange pRange) {
378
379 theDateRange = pRange;
380 if (theFilter != null) {
381 theFilter.setDateRange(theDateRange);
382 }
383 }
384
385
386
387
388 private void applyState() {
389
390 setEnabled(true);
391 theButton.setValue(theCategory);
392 }
393 }
394 }