View Javadoc
1   /*
2    * MoneyWise: Finance Application
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
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.profile.OceanusProfile;
21  import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
22  import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
23  import io.github.tonywasher.joceanus.metis.ui.MetisErrorPanel;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
25  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDataSet;
26  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee;
27  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity;
28  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity.MoneyWiseSecurityList;
29  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityPrice;
30  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityPrice.MoneyWiseSecurityPriceList;
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.exc.MoneyWiseDataException;
35  import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseAssetTable;
36  import io.github.tonywasher.joceanus.moneywise.ui.dialog.MoneyWiseSecurityDialog;
37  import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseView;
38  import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
39  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditEntry;
40  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
41  import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
42  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
43  import io.github.tonywasher.joceanus.tethys.api.table.TethysUITableManager;
44  
45  /**
46   * MoneyWise Security Table.
47   */
48  public class MoneyWiseSecurityTable
49          extends MoneyWiseAssetTable<MoneyWiseSecurity> {
50      /**
51       * The Info UpdateEntry.
52       */
53      private final PrometheusEditEntry<MoneyWiseSecurityPrice> thePriceEntry;
54  
55      /**
56       * The Security dialog.
57       */
58      private final MoneyWiseSecurityDialog theActiveSecurity;
59  
60      /**
61       * The edit list.
62       */
63      private MoneyWiseSecurityList theSecurities;
64  
65      /**
66       * Constructor.
67       *
68       * @param pView    the view
69       * @param pEditSet the editSet
70       * @param pError   the error panel
71       */
72      MoneyWiseSecurityTable(final MoneyWiseView pView,
73                             final PrometheusEditSet pEditSet,
74                             final MetisErrorPanel pError) {
75          /* Store parameters */
76          super(pView, pEditSet, pError, MoneyWiseBasicDataType.SECURITY);
77  
78          /* register the info/priceEntries */
79          getEditSet().registerType(MoneyWiseBasicDataType.SECURITYINFO);
80          thePriceEntry = getEditSet().registerType(MoneyWiseBasicDataType.SECURITYPRICE);
81  
82          /* Access Gui factory */
83          final TethysUIFactory<?> myGuiFactory = pView.getGuiFactory();
84          final TethysUITableManager<MetisDataFieldId, MoneyWiseSecurity> myTable = getTable();
85  
86          /* Create a security panel */
87          theActiveSecurity = new MoneyWiseSecurityDialog(myGuiFactory, pView, pEditSet, this);
88          declareItemPanel(theActiveSecurity);
89  
90          /* Create the symbol column */
91          myTable.declareStringColumn(MoneyWiseAccountInfoClass.SYMBOL)
92                  .setValidator(this::isValidSymbol)
93                  .setCellValueFactory(MoneyWiseSecurity::getSymbol)
94                  .setEditable(true)
95                  .setColumnWidth(WIDTH_NAME)
96                  .setOnCommit((r, v) -> updateField(MoneyWiseSecurity::setSymbol, r, v));
97  
98          /* Finish the table */
99          finishTable(true, true, false);
100 
101         /* Add listeners */
102         theActiveSecurity.getEventRegistrar().addEventListener(PrometheusDataEvent.ADJUSTVISIBILITY, e -> handlePanelState());
103     }
104 
105     @Override
106     protected boolean isItemEditing() {
107         return theActiveSecurity.isEditing();
108     }
109 
110     @Override
111     protected void refreshData() throws OceanusException {
112         /* Obtain the active profile */
113         OceanusProfile myTask = getView().getActiveTask();
114         myTask = myTask.startTask("Securities");
115 
116         /* Access list */
117         final MoneyWiseDataSet myData = getView().getData();
118         final MoneyWiseSecurityList myBase = myData.getSecurities();
119         theSecurities = myBase.deriveEditList(getEditSet());
120         getTable().setItems(theSecurities.getUnderlyingList());
121 
122         /* Get the Security prices list */
123         MoneyWiseSecurityPriceList myPrices = myData.getSecurityPrices();
124         myPrices = myPrices.deriveEditList(getEditSet());
125         thePriceEntry.setDataList(myPrices);
126 
127         /* Notify panel of refresh */
128         theActiveSecurity.refreshData();
129         restoreSelected();
130 
131         /* Complete the task */
132         myTask.end();
133     }
134 
135     @Override
136     public void cancelEditing() {
137         super.cancelEditing();
138         theActiveSecurity.setEditable(false);
139     }
140 
141     /**
142      * Select security.
143      *
144      * @param pSecurity the security to select
145      */
146     void selectSecurity(final MoneyWiseSecurity pSecurity) {
147         /* Check whether we need to showAll */
148         checkShowAll(pSecurity);
149 
150         /* If we are changing the selection */
151         final MoneyWiseSecurity myCurrent = theActiveSecurity.getSelectedItem();
152         if (!MetisDataDifference.isEqual(myCurrent, pSecurity)) {
153             /* Select the row */
154             getTable().selectRow(pSecurity);
155         }
156     }
157 
158     @Override
159     protected void handleRewind() {
160         /* Only action if we are not editing */
161         if (!theActiveSecurity.isEditing()) {
162             /* Handle the reWind */
163             setEnabled(true);
164             super.handleRewind();
165         }
166 
167         /* Adjust for changes */
168         notifyChanges();
169     }
170 
171     /**
172      * Handle panel state.
173      */
174     private void handlePanelState() {
175         /* Only action if we are not editing */
176         if (!theActiveSecurity.isEditing()) {
177             /* handle the edit transition */
178             setEnabled(true);
179             final MoneyWiseSecurity mySecurity = theActiveSecurity.getSelectedItem();
180             updateTableData();
181             if (mySecurity != null) {
182                 getTable().selectRow(mySecurity);
183             } else {
184                 restoreSelected();
185             }
186         } else {
187             getTable().cancelEditing();
188         }
189 
190         /* Note changes */
191         notifyChanges();
192     }
193 
194     @Override
195     protected void buildCategoryMenu(final MoneyWiseSecurity pSecurity,
196                                      final TethysUIScrollMenu<MoneyWiseAssetCategory> pMenu) {
197         /* Build the menu */
198         theActiveSecurity.buildSecTypeMenu(pMenu, pSecurity);
199     }
200 
201     @Override
202     protected void buildParentMenu(final MoneyWiseSecurity pSecurity,
203                                    final TethysUIScrollMenu<MoneyWisePayee> pMenu) {
204         /* Build the menu */
205         theActiveSecurity.buildParentMenu(pMenu, pSecurity);
206     }
207 
208     @Override
209     protected void buildCurrencyMenu(final MoneyWiseSecurity pSecurity,
210                                      final TethysUIScrollMenu<MoneyWiseCurrency> pMenu) {
211         /* Build the menu */
212         theActiveSecurity.buildCurrencyMenu(pMenu, pSecurity);
213     }
214 
215     @Override
216     protected void addNewItem() {
217         /* Protect against Exceptions */
218         try {
219             /* Make sure that we have finished editing */
220             cancelEditing();
221 
222             /* Create a new profile */
223             final OceanusProfile myTask = getView().getNewProfile("addNewItem");
224 
225             /* Create the new asset */
226             myTask.startTask("buildItem");
227             final MoneyWiseSecurity mySecurity = theSecurities.addNewItem();
228             mySecurity.setDefaults();
229 
230             /* Set as new and adjust map */
231             myTask.startTask("incrementVersion");
232             mySecurity.setNewVersion();
233             mySecurity.adjustMapForItem();
234             getEditSet().incrementVersion();
235 
236             /* Validate the new item */
237             myTask.startTask("validate");
238             mySecurity.validate();
239 
240             /* update panel */
241             myTask.startTask("setItem");
242             theActiveSecurity.setNewItem(mySecurity);
243 
244             /* Lock the table */
245             setTableEnabled(false);
246             myTask.end();
247 
248             /* Handle Exceptions */
249         } catch (OceanusException e) {
250             /* Build the error */
251             final OceanusException myError = new MoneyWiseDataException("Failed to create new security", e);
252 
253             /* Show the error */
254             setError(myError);
255         }
256     }
257 }