1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.moneywise.ui.panel;
18
19 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20 import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
21 import io.github.tonywasher.joceanus.oceanus.event.OceanusEvent;
22 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventManager;
23 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar;
24 import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar.OceanusEventProvider;
25 import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
26 import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
27 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
28 import io.github.tonywasher.joceanus.metis.ui.MetisAction;
29 import io.github.tonywasher.joceanus.metis.ui.MetisErrorPanel;
30 import io.github.tonywasher.joceanus.metis.ui.MetisIcon;
31 import io.github.tonywasher.joceanus.metis.viewer.MetisViewerEntry;
32 import io.github.tonywasher.joceanus.metis.viewer.MetisViewerManager;
33 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
34 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicResource;
35 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio;
36 import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseUIResource;
37 import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseBaseTable;
38 import io.github.tonywasher.joceanus.moneywise.ui.controls.MoneyWiseSpotPricesSelect;
39 import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseSpotSecurityPrice;
40 import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseSpotSecurityPrice.MoneyWiseSpotSecurityList;
41 import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseView;
42 import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseViewResource;
43 import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseYQLDownloader;
44 import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
45 import io.github.tonywasher.joceanus.prometheus.ui.PrometheusActionButtons;
46 import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
47 import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
48 import io.github.tonywasher.joceanus.prometheus.views.PrometheusUIEvent;
49 import io.github.tonywasher.joceanus.prometheus.views.PrometheusViewerEntryId;
50 import io.github.tonywasher.joceanus.tethys.api.base.TethysUIComponent;
51 import io.github.tonywasher.joceanus.tethys.api.button.TethysUIButton;
52 import io.github.tonywasher.joceanus.tethys.api.control.TethysUIControl.TethysUIIconMapSet;
53 import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
54 import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIBorderPaneManager;
55 import io.github.tonywasher.joceanus.tethys.api.pane.TethysUIPaneFactory;
56 import io.github.tonywasher.joceanus.tethys.api.table.TethysUITableManager;
57
58
59
60
61 public class MoneyWiseMarketPricesTable
62 extends MoneyWiseBaseTable<MoneyWiseSpotSecurityPrice> {
63
64
65
66 private final MoneyWiseSpotPricesSelect theSelect;
67
68
69
70
71 private MoneyWiseSpotSecurityList thePrices;
72
73
74
75
76 private OceanusDate theDate;
77
78
79
80
81 private MoneyWisePortfolio thePortfolio;
82
83
84
85
86
87
88
89
90 MoneyWiseMarketPricesTable(final MoneyWiseView pView,
91 final PrometheusEditSet pEditSet,
92 final MetisErrorPanel pError) {
93
94 super(pView, pEditSet, pError, MoneyWiseBasicDataType.SECURITYPRICE);
95
96
97 final TethysUIFactory<?> myGuiFactory = pView.getGuiFactory();
98 final TethysUITableManager<MetisDataFieldId, MoneyWiseSpotSecurityPrice> myTable = getTable();
99
100
101 final TethysUIButton myNewButton = myGuiFactory.buttonFactory().newButton();
102 MetisIcon.configureNewIconButton(myNewButton);
103
104
105 theSelect = new MoneyWiseSpotPricesSelect(myGuiFactory, pView);
106
107
108 myTable.setDisabled(MoneyWiseSpotSecurityPrice::isDisabled)
109 .setComparator(MoneyWiseSpotSecurityPrice::compareTo);
110
111
112 myTable.declareStringColumn(MoneyWiseBasicDataType.SECURITY)
113 .setCellValueFactory(MoneyWiseSpotSecurityPrice::getSecurityName)
114 .setEditable(false)
115 .setColumnWidth(WIDTH_NAME);
116
117
118 myTable.declarePriceColumn(MoneyWiseBasicResource.MONEYWISEDATA_FIELD_PRICE)
119 .setCellValueFactory(MoneyWiseSpotSecurityPrice::getPrice)
120 .setEditable(true)
121 .setCellEditable(r -> !r.isDisabled())
122 .setColumnWidth(WIDTH_PRICE)
123 .setOnCommit((r, v) -> updateField(MoneyWiseSpotSecurityPrice::setPrice, r, v));
124
125
126 myTable.declarePriceColumn(MoneyWiseViewResource.SPOTPRICE_PREVPRICE)
127 .setCellValueFactory(MoneyWiseSpotSecurityPrice::getPrevPrice)
128 .setName(MoneyWiseViewResource.SPOTPRICE_PREVPRICE.getValue())
129 .setEditable(false)
130 .setColumnWidth(WIDTH_PRICE);
131
132
133 myTable.declareDateColumn(MoneyWiseViewResource.SPOTEVENT_PREVDATE)
134 .setCellValueFactory(MoneyWiseSpotSecurityPrice::getPrevDate)
135 .setName(MoneyWiseViewResource.SPOTEVENT_PREVDATE.getValue())
136 .setEditable(false)
137 .setColumnWidth(WIDTH_DATE);
138
139
140 final TethysUIIconMapSet<MetisAction> myActionMapSet = MetisIcon.configureStatusIconButton(myGuiFactory);
141 myTable.declareIconColumn(PrometheusDataResource.DATAITEM_TOUCH, MetisAction.class)
142 .setIconMapSet(r -> myActionMapSet)
143 .setCellValueFactory(r -> r.getPrice() != null && !r.isDisabled() ? MetisAction.DELETE : MetisAction.DO)
144 .setName(MoneyWiseUIResource.STATICDATA_ACTIVE.getValue())
145 .setEditable(true)
146 .setCellEditable(r -> r.getPrice() != null && !r.isDisabled())
147 .setColumnWidth(WIDTH_ICON)
148 .setOnCommit((r, v) -> updateField(this::deleteRow, r, v));
149
150
151 theSelect.getEventRegistrar().addEventListener(PrometheusDataEvent.SELECTIONCHANGED, e -> handleNewSelection());
152 theSelect.getEventRegistrar().addEventListener(PrometheusDataEvent.DOWNLOAD, e -> downloadPrices());
153 pView.getEventRegistrar().addEventListener(e -> refreshData());
154 pEditSet.getEventRegistrar().addEventListener(e -> updateTableData());
155 }
156
157
158
159
160
161
162 MoneyWiseSpotPricesSelect getSelect() {
163 return theSelect;
164 }
165
166 @Override
167 protected void refreshData() {
168
169 OceanusProfile myTask = getView().getActiveTask();
170 myTask = myTask.startTask("SpotPrices1");
171
172
173 theSelect.refreshData();
174
175
176 setSelection(theSelect.getPortfolio(), theSelect.getDate());
177
178
179 theSelect.createSavePoint();
180
181
182 myTask.end();
183 }
184
185
186
187
188
189
190
191 public void setSelection(final MoneyWisePortfolio pPortfolio,
192 final OceanusDate pDate) {
193
194 theDate = pDate;
195 thePortfolio = pPortfolio;
196
197
198 if (theDate != null
199 && thePortfolio != null) {
200
201 thePrices = new MoneyWiseSpotSecurityList(getView(), pPortfolio, pDate);
202
203
204 theSelect.setAdjacent(thePrices.getPrev(), thePrices.getNext());
205
206
207 } else {
208
209 thePrices = null;
210 theSelect.setAdjacent(null, null);
211 }
212
213
214 getTable().setItems(thePrices == null ? null : thePrices.getUnderlyingList());
215 getEditEntry().setDataList(thePrices);
216 theSelect.setEnabled(true);
217 }
218
219
220
221
222 private void handleNewSelection() {
223
224 setShowAll();
225
226
227 final MoneyWisePortfolio myPortfolio = theSelect.getPortfolio();
228 final OceanusDate myDate = theSelect.getDate();
229
230
231 if (!MetisDataDifference.isEqual(theDate, myDate)
232 || !MetisDataDifference.isEqual(thePortfolio, myPortfolio)) {
233
234 setSelection(myPortfolio, myDate);
235
236
237 theSelect.createSavePoint();
238 }
239 }
240
241
242
243
244 private void setShowAll() {
245 cancelEditing();
246 getTable().setFilter(this::isFiltered);
247 }
248
249 @Override
250 protected boolean isFiltered(final MoneyWiseSpotSecurityPrice pRow) {
251
252 return theSelect.getShowClosed() || !pRow.isDisabled();
253 }
254
255 @Override
256 protected void deleteRow(final MoneyWiseSpotSecurityPrice pRow,
257 final Object pValue) throws OceanusException {
258 pRow.setPrice(null);
259 }
260
261
262
263
264 public void determineFocus() {
265
266 getTable().requestFocus();
267 }
268
269 @Override
270 protected void notifyChanges() {
271 theSelect.setEnabled(!hasUpdates());
272 super.notifyChanges();
273 }
274
275
276
277
278 private void downloadPrices() {
279
280 cancelEditing();
281
282
283 try {
284
285 if (MoneyWiseYQLDownloader.downloadPrices(thePrices)) {
286
287 getEditSet().incrementVersion();
288
289
290 updateTableData();
291 notifyChanges();
292 }
293 } catch (OceanusException e) {
294
295 setError(e);
296 }
297 }
298
299
300
301
302 public static class MoneyWiseSpotPricesPanel
303 implements TethysUIComponent, OceanusEventProvider<PrometheusDataEvent> {
304
305
306
307 private static final String NLS_DATAENTRY = MoneyWiseUIResource.PRICES_DATAENTRY.getValue();
308
309
310
311
312 private final OceanusEventManager<PrometheusDataEvent> theEventManager;
313
314
315
316
317 private final PrometheusEditSet theEditSet;
318
319
320
321
322 private final MetisErrorPanel theError;
323
324
325
326
327 private final PrometheusActionButtons theActionButtons;
328
329
330
331
332 private final MoneyWiseMarketPricesTable theTable;
333
334
335
336
337 private final TethysUIBorderPaneManager thePanel;
338
339
340
341
342 private final MetisViewerEntry theViewerPrice;
343
344
345
346
347
348
349 public MoneyWiseSpotPricesPanel(final MoneyWiseView pView) {
350
351 theEditSet = new PrometheusEditSet(pView);
352
353
354 theEventManager = new OceanusEventManager<>();
355
356
357 final MetisViewerEntry mySection = pView.getViewerEntry(PrometheusViewerEntryId.VIEW);
358 final MetisViewerManager myViewer = pView.getViewerManager();
359 theViewerPrice = myViewer.newEntry(mySection, NLS_DATAENTRY);
360 theViewerPrice.setTreeObject(theEditSet);
361
362
363 theError = pView.getToolkit().getToolkit().newErrorPanel(theViewerPrice);
364
365
366 theTable = new MoneyWiseMarketPricesTable(pView, theEditSet, theError);
367
368
369 final TethysUIFactory<?> myGuiFactory = pView.getGuiFactory();
370 theActionButtons = new PrometheusActionButtons(myGuiFactory, theEditSet);
371 theActionButtons.setVisible(false);
372
373
374 final TethysUIPaneFactory myPanes = myGuiFactory.paneFactory();
375 final TethysUIBorderPaneManager myHeader = myPanes.newBorderPane();
376 myHeader.setCentre(theTable.getSelect());
377 myHeader.setNorth(theError);
378 myHeader.setEast(theActionButtons);
379
380
381 thePanel = myPanes.newBorderPane();
382 thePanel.setNorth(myHeader);
383 thePanel.setCentre(theTable);
384
385
386 theError.getEventRegistrar().addEventListener(e -> handleErrorPane());
387 theActionButtons.getEventRegistrar().addEventListener(this::handleActionButtons);
388 theTable.getEventRegistrar().addEventListener(e -> notifyChanges());
389 }
390
391 @Override
392 public TethysUIComponent getUnderlying() {
393 return thePanel;
394 }
395
396 @Override
397 public OceanusEventRegistrar<PrometheusDataEvent> getEventRegistrar() {
398 return theEventManager.getEventRegistrar();
399 }
400
401
402
403
404 private void handleErrorPane() {
405
406 final boolean isError = theError.hasError();
407
408
409 theTable.getSelect().setVisible(!isError);
410
411
412 theTable.setEnabled(!isError);
413
414
415 theActionButtons.setEnabled(!isError);
416 }
417
418
419
420
421
422
423 private void handleActionButtons(final OceanusEvent<PrometheusUIEvent> pEvent) {
424
425 theTable.cancelEditing();
426
427
428 theEditSet.processCommand(pEvent.getEventId(), theError);
429
430
431 theTable.notifyChanges();
432 }
433
434
435
436
437 public void determineFocus() {
438
439 theTable.determineFocus();
440
441
442 theViewerPrice.setFocus();
443 }
444
445
446
447
448 private void notifyChanges() {
449
450 final boolean hasUpdates = hasUpdates();
451
452
453 theActionButtons.setEnabled(true);
454 theActionButtons.setVisible(hasUpdates);
455
456
457 theEventManager.fireEvent(PrometheusDataEvent.ADJUSTVISIBILITY);
458 }
459
460
461
462
463
464
465 public boolean hasUpdates() {
466 return theTable.hasUpdates();
467 }
468
469
470
471
472
473
474 public boolean hasSession() {
475 return theTable.hasUpdates();
476 }
477
478
479
480
481
482
483 public boolean hasErrors() {
484 return theTable.hasErrors();
485 }
486 }
487 }