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.dialog;
18  
19  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
21  import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
22  import io.github.tonywasher.joceanus.metis.field.MetisFieldRequired;
23  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicResource;
25  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee;
26  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee.MoneyWisePayeeList;
27  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseRegion;
28  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseRegion.MoneyWiseRegionList;
29  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity;
30  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity.MoneyWiseSecurityList;
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.data.statics.MoneyWiseCurrency.MoneyWiseCurrencyList;
35  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityClass;
36  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityType;
37  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityType.MoneyWiseSecurityTypeList;
38  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
39  import io.github.tonywasher.joceanus.moneywise.data.validate.MoneyWiseValidateSecurity;
40  import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseIcon;
41  import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseUIResource;
42  import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseAssetTable;
43  import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseView;
44  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
45  import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSet;
46  import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSetEvent;
47  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
48  import io.github.tonywasher.joceanus.tethys.api.control.TethysUIControl.TethysUIIconMapSet;
49  import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
50  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUICharArrayTextAreaField;
51  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIIconButtonField;
52  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIPriceEditField;
53  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIScrollButtonField;
54  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIStringEditField;
55  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIFieldFactory;
56  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
57  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
58  
59  import java.util.Iterator;
60  import java.util.Map;
61  
62  /**
63   * Panel to display/edit/create a Security.
64   */
65  public class MoneyWiseSecurityDialog
66          extends MoneyWiseAssetDialog<MoneyWiseSecurity> {
67      /**
68       * Prices Tab Title.
69       */
70      private static final String TAB_PRICES = MoneyWiseUIResource.SECURITYPANEL_TAB_PRICES.getValue();
71  
72      /**
73       * The fieldSet.
74       */
75      private final PrometheusFieldSet<MoneyWiseSecurity> theFieldSet;
76  
77      /**
78       * SecurityPrice Table.
79       */
80      private final MoneyWiseSecurityPriceTable thePrices;
81  
82      /**
83       * The Closed State.
84       */
85      private Boolean theClosedState = Boolean.FALSE;
86  
87      /**
88       * Constructor.
89       *
90       * @param pFactory the GUI factory
91       * @param pView    the data view
92       * @param pEditSet the edit set
93       * @param pOwner   the owning table
94       */
95      public MoneyWiseSecurityDialog(final TethysUIFactory<?> pFactory,
96                                     final MoneyWiseView pView,
97                                     final PrometheusEditSet pEditSet,
98                                     final MoneyWiseAssetTable<MoneyWiseSecurity> pOwner) {
99          /* Initialise the panel */
100         super(pFactory, pEditSet, pOwner);
101 
102         /* Access the fieldSet */
103         theFieldSet = getFieldSet();
104         theFieldSet.setReporter(pOwner::showValidateError);
105 
106         /* Build the main panel */
107         buildMainPanel(pFactory);
108 
109         /* Build the details panel */
110         buildDetailsPanel(pFactory);
111 
112         /* Build the notes panel */
113         buildNotesPanel(pFactory);
114 
115         /* Create the SecurityPrices table */
116         thePrices = new MoneyWiseSecurityPriceTable(pView, getEditSet(), pOwner.getErrorPanel());
117         theFieldSet.newTable(TAB_PRICES, thePrices);
118 
119         /* Create the listener */
120         thePrices.getEventRegistrar().addEventListener(e -> {
121             updateActions();
122             fireStateChanged();
123         });
124     }
125 
126     /**
127      * Build Main subPanel.
128      *
129      * @param pFactory the GUI factory
130      */
131     private void buildMainPanel(final TethysUIFactory<?> pFactory) {
132         /* Create the text fields */
133         final TethysUIFieldFactory myFields = pFactory.fieldFactory();
134         final TethysUIStringEditField myName = myFields.newStringField();
135         final TethysUIStringEditField myDesc = myFields.newStringField();
136 
137         /* Create the buttons */
138         final TethysUIScrollButtonField<MoneyWiseAssetCategory> myTypeButton = myFields.newScrollField(MoneyWiseAssetCategory.class);
139         final TethysUIScrollButtonField<MoneyWisePayee> myParentButton = myFields.newScrollField(MoneyWisePayee.class);
140         final TethysUIScrollButtonField<MoneyWiseCurrency> myCurrencyButton = myFields.newScrollField(MoneyWiseCurrency.class);
141         final TethysUIIconButtonField<Boolean> myClosedButton = myFields.newIconField(Boolean.class);
142 
143         /* Assign the fields to the panel */
144         theFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_NAME, myName, MoneyWiseSecurity::getName);
145         theFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_DESC, myDesc, MoneyWiseSecurity::getDesc);
146         theFieldSet.addField(MoneyWiseBasicResource.CATEGORY_NAME, myTypeButton, MoneyWiseSecurity::getCategory);
147         theFieldSet.addField(MoneyWiseBasicResource.ASSET_PARENT, myParentButton, MoneyWiseSecurity::getParent);
148         theFieldSet.addField(MoneyWiseStaticDataType.CURRENCY, myCurrencyButton, MoneyWiseSecurity::getAssetCurrency);
149         theFieldSet.addField(MoneyWiseBasicResource.ASSET_CLOSED, myClosedButton, MoneyWiseSecurity::isClosed);
150 
151         /* Configure the menuBuilders */
152         myTypeButton.setMenuConfigurator(c -> buildSecTypeMenu(c, getItem()));
153         myParentButton.setMenuConfigurator(c -> buildParentMenu(c, getItem()));
154         myCurrencyButton.setMenuConfigurator(c -> buildCurrencyMenu(c, getItem()));
155         final Map<Boolean, TethysUIIconMapSet<Boolean>> myMapSets = MoneyWiseIcon.configureLockedIconButton(pFactory);
156         myClosedButton.setIconMapSet(() -> myMapSets.get(theClosedState));
157 
158         /* Configure validation checks */
159         myName.setValidator(this::isValidName);
160         myDesc.setValidator(this::isValidDesc);
161     }
162 
163     /**
164      * Build details subPanel.
165      *
166      * @param pFactory the GUI factory
167      */
168     private void buildDetailsPanel(final TethysUIFactory<?> pFactory) {
169         /* Create a new panel */
170         theFieldSet.newPanel(TAB_DETAILS);
171 
172         /* Allocate fields */
173         final TethysUIFieldFactory myFields = pFactory.fieldFactory();
174         final TethysUIStringEditField mySymbol = myFields.newStringField();
175         final TethysUIPriceEditField myPrice = myFields.newPriceField();
176 
177         /* Create the buttons */
178         final TethysUIScrollButtonField<MoneyWiseRegion> myRegionButton = myFields.newScrollField(MoneyWiseRegion.class);
179         final TethysUIScrollButtonField<MoneyWiseSecurity> myStockButton = myFields.newScrollField(MoneyWiseSecurity.class);
180 
181         /* Assign the fields to the panel */
182         theFieldSet.addField(MoneyWiseAccountInfoClass.SYMBOL, mySymbol, MoneyWiseSecurity::getSymbol);
183         theFieldSet.addField(MoneyWiseAccountInfoClass.REGION, myRegionButton, MoneyWiseSecurity::getRegion);
184         theFieldSet.addField(MoneyWiseAccountInfoClass.UNDERLYINGSTOCK, myStockButton, MoneyWiseSecurity::getUnderlyingStock);
185         theFieldSet.addField(MoneyWiseAccountInfoClass.OPTIONPRICE, myPrice, MoneyWiseSecurity::getOptionPrice);
186 
187         /* Configure the menuBuilders */
188         myRegionButton.setMenuConfigurator(c -> buildRegionMenu(c, getItem()));
189         myStockButton.setMenuConfigurator(c -> buildStockMenu(c, getItem()));
190         myPrice.setDeemedCurrency(() -> getItem().getCurrency());
191 
192         /* Configure validation checks */
193         mySymbol.setValidator(this::isValidSymbol);
194     }
195 
196     /**
197      * Build Notes subPanel.
198      *
199      * @param pFactory the GUI factory
200      */
201     private void buildNotesPanel(final TethysUIFactory<?> pFactory) {
202         /* Allocate fields */
203         final TethysUIFieldFactory myFields = pFactory.fieldFactory();
204         final TethysUICharArrayTextAreaField myNotes = myFields.newCharArrayAreaField();
205 
206         /* Assign the fields to the panel */
207         theFieldSet.newTextArea(TAB_NOTES, MoneyWiseAccountInfoClass.NOTES, myNotes, MoneyWiseSecurity::getNotes);
208 
209         /* Configure validation checks */
210         myNotes.setValidator(this::isValidNotes);
211     }
212 
213     @Override
214     public void refreshData() {
215         /* If we have an item */
216         final MoneyWiseSecurity myItem = getItem();
217         if (myItem != null) {
218             final MoneyWiseSecurityList mySecurities = getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class);
219             setItem(mySecurities.findItemById(myItem.getIndexedId()));
220         }
221 
222         /* Refresh the prices */
223         thePrices.refreshData();
224 
225         /* Make sure that the item is not editable */
226         setEditable(false);
227     }
228 
229     @Override
230     protected void adjustFields(final boolean isEditable) {
231         /* Access the item */
232         final MoneyWiseSecurity mySecurity = getItem();
233         final boolean bIsClosed = mySecurity.isClosed();
234         final boolean bIsActive = mySecurity.isActive();
235         final boolean bIsRelevant = mySecurity.isRelevant();
236 
237         /* Determine whether the closed button should be visible */
238         final boolean bShowClosed = bIsClosed || (bIsActive && !bIsRelevant);
239         theFieldSet.setFieldVisible(MoneyWiseBasicResource.ASSET_CLOSED, bShowClosed);
240 
241         /* Determine the state of the closed button */
242         final boolean bEditClosed = bIsClosed
243                 ? !mySecurity.getParent().isClosed()
244                 : !bIsRelevant;
245         theFieldSet.setFieldEditable(MoneyWiseBasicResource.ASSET_CLOSED, isEditable && bEditClosed);
246         theClosedState = bEditClosed;
247 
248         /* Determine whether the description field should be visible */
249         final boolean bShowDesc = isEditable || mySecurity.getDesc() != null;
250         theFieldSet.setFieldVisible(PrometheusDataResource.DATAITEM_FIELD_DESC, bShowDesc);
251 
252         /* Determine whether the account details should be visible */
253         final boolean bShowNotes = isEditable || mySecurity.getNotes() != null;
254         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.NOTES, bShowNotes);
255 
256         /* Determine whether the symbol field should be visible */
257         boolean bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.SYMBOL);
258         boolean bShowField = bEditField || mySecurity.getSymbol() != null;
259         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.SYMBOL, bShowField);
260         theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.SYMBOL, bEditField);
261 
262         /* Determine whether the region field should be visible */
263         bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.REGION);
264         bShowField = bEditField || mySecurity.getRegion() != null;
265         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.REGION, bShowField);
266         theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.REGION, bEditField);
267 
268         /* Determine whether the stock field should be visible */
269         bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.UNDERLYINGSTOCK);
270         bShowField = bEditField || mySecurity.getRegion() != null;
271         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.UNDERLYINGSTOCK, bShowField);
272         theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.UNDERLYINGSTOCK, bEditField);
273 
274         /* Determine whether the price field should be visible */
275         bEditField = isEditable && isEditableField(mySecurity, MoneyWiseAccountInfoClass.OPTIONPRICE);
276         bShowField = bEditField || mySecurity.getRegion() != null;
277         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.OPTIONPRICE, bShowField);
278         theFieldSet.setFieldEditable(MoneyWiseAccountInfoClass.OPTIONPRICE, bEditField);
279 
280         /* Security type and currency cannot be changed if the item is active */
281         theFieldSet.setFieldEditable(MoneyWiseBasicResource.CATEGORY_NAME, isEditable && !bIsActive);
282         theFieldSet.setFieldEditable(MoneyWiseStaticDataType.CURRENCY, isEditable && !bIsActive);
283 
284         /* Set editable value for parent */
285         theFieldSet.setFieldEditable(MoneyWiseBasicResource.ASSET_PARENT, isEditable && !bIsClosed);
286     }
287 
288     /**
289      * Is the field editable?
290      *
291      * @param pSecurity the security
292      * @param pField    the field class
293      * @return true/false
294      */
295     public static boolean isEditableField(final MoneyWiseSecurity pSecurity,
296                                           final MoneyWiseAccountInfoClass pField) {
297         /* Check whether the field is available */
298         final MoneyWiseValidateSecurity myValidator = (MoneyWiseValidateSecurity) pSecurity.getList().getValidator();
299         final MetisFieldRequired isRequired = myValidator.isClassRequired(pField);
300         return !isRequired.equals(MetisFieldRequired.NOTALLOWED);
301     }
302 
303     @Override
304     protected void updateField(final PrometheusFieldSetEvent pUpdate) throws OceanusException {
305         /* Access the field */
306         final MetisDataFieldId myField = pUpdate.getFieldId();
307         final MoneyWiseSecurity mySecurity = getItem();
308 
309         /* Process updates */
310         if (PrometheusDataResource.DATAITEM_FIELD_NAME.equals(myField)) {
311             /* Update the Name */
312             mySecurity.setName(pUpdate.getValue(String.class));
313         } else if (PrometheusDataResource.DATAITEM_FIELD_DESC.equals(myField)) {
314             /* Update the Description */
315             mySecurity.setDescription(pUpdate.getValue(String.class));
316         } else if (MoneyWiseBasicResource.CATEGORY_NAME.equals(myField)) {
317             /* Update the Security Type */
318             mySecurity.setCategory(pUpdate.getValue(MoneyWiseSecurityType.class));
319             mySecurity.autoCorrect();
320         } else if (MoneyWiseBasicResource.ASSET_PARENT.equals(myField)) {
321             /* Update the Parent */
322             mySecurity.setParent(pUpdate.getValue(MoneyWisePayee.class));
323         } else if (MoneyWiseStaticDataType.CURRENCY.equals(myField)) {
324             /* Update the Currency */
325             mySecurity.setAssetCurrency(pUpdate.getValue(MoneyWiseCurrency.class));
326         } else if (MoneyWiseBasicResource.ASSET_CLOSED.equals(myField)) {
327             /* Update the Closed indication */
328             mySecurity.setClosed(pUpdate.getValue(Boolean.class));
329         } else if (MoneyWiseAccountInfoClass.SYMBOL.equals(myField)) {
330             /* Update the Symbol */
331             mySecurity.setSymbol(pUpdate.getValue(String.class));
332         } else if (MoneyWiseAccountInfoClass.REGION.equals(myField)) {
333             /* Update the Region */
334             mySecurity.setRegion(pUpdate.getValue(MoneyWiseRegion.class));
335         } else if (MoneyWiseAccountInfoClass.UNDERLYINGSTOCK.equals(myField)) {
336             /* Update the Underlying Stock */
337             mySecurity.setUnderlyingStock(pUpdate.getValue(MoneyWiseSecurity.class));
338         } else if (MoneyWiseAccountInfoClass.OPTIONPRICE.equals(myField)) {
339             /* Update the OptionPrice */
340             mySecurity.setOptionPrice(pUpdate.getValue(OceanusPrice.class));
341         } else if (MoneyWiseAccountInfoClass.NOTES.equals(myField)) {
342             /* Update the Notes */
343             mySecurity.setNotes(pUpdate.getValue(char[].class));
344         }
345     }
346 
347     @Override
348     protected void declareGoToItems(final boolean pUpdates) {
349         final MoneyWiseSecurity myItem = getItem();
350         final MoneyWisePayee myParent = myItem.getParent();
351         if (!pUpdates) {
352             final MoneyWiseSecurityType myType = myItem.getCategory();
353             final MoneyWiseCurrency myCurrency = myItem.getAssetCurrency();
354             final MoneyWiseRegion myRegion = myItem.getRegion();
355             declareGoToItem(myType);
356             declareGoToItem(myRegion);
357             declareGoToItem(myCurrency);
358         }
359         declareGoToItem(myParent);
360     }
361 
362     /**
363      * Add a new price for a new security.
364      *
365      * @param pSecurity the security
366      * @throws OceanusException on error
367      */
368     public void addNewPrice(final MoneyWiseSecurity pSecurity) throws OceanusException {
369         /* Create the new price */
370         thePrices.addNewPrice(pSecurity);
371     }
372 
373     @Override
374     public void setEditable(final boolean isEditable) {
375         /* Update the prices */
376         thePrices.setEditable(isEditable);
377 
378         /* Pass call onwards */
379         super.setEditable(isEditable);
380     }
381 
382     @Override
383     protected void refreshAfterUpdate() {
384         /* Pass call onwards */
385         super.refreshAfterUpdate();
386 
387         /* Refresh the prices */
388         thePrices.refreshAfterUpdate();
389     }
390 
391     /**
392      * Build the securityType menu for an item.
393      *
394      * @param pMenu     the menu
395      * @param pSecurity the security to build for
396      */
397     public void buildSecTypeMenu(final TethysUIScrollMenu<MoneyWiseAssetCategory> pMenu,
398                                  final MoneyWiseSecurity pSecurity) {
399         /* Clear the menu */
400         pMenu.removeAllItems();
401 
402         /* Record active item */
403         final MoneyWiseSecurityType myCurr = pSecurity.getCategory();
404         TethysUIScrollItem<MoneyWiseAssetCategory> myActive = null;
405 
406         /* Access SecurityTypes */
407         final MoneyWiseSecurityTypeList myTypes = getDataList(MoneyWiseStaticDataType.SECURITYTYPE, MoneyWiseSecurityTypeList.class);
408 
409         /* Loop through the SecurityTypes */
410         final Iterator<MoneyWiseSecurityType> myIterator = myTypes.iterator();
411         while (myIterator.hasNext()) {
412             final MoneyWiseSecurityType myType = myIterator.next();
413 
414             /* Ignore deleted or disabled */
415             final boolean bIgnore = myType.isDeleted() || !myType.getEnabled();
416             if (bIgnore) {
417                 continue;
418             }
419 
420             /* Create a new action for the secType */
421             final TethysUIScrollItem<MoneyWiseAssetCategory> myItem = pMenu.addItem(myType);
422 
423             /* If this is the active secType */
424             if (myType.equals(myCurr)) {
425                 /* Record it */
426                 myActive = myItem;
427             }
428         }
429 
430         /* Ensure active item is visible */
431         if (myActive != null) {
432             myActive.scrollToItem();
433         }
434     }
435 
436     /**
437      * Build the parent menu for an item.
438      *
439      * @param pMenu     the menu
440      * @param pSecurity the security to build for
441      */
442     public void buildParentMenu(final TethysUIScrollMenu<MoneyWisePayee> pMenu,
443                                 final MoneyWiseSecurity pSecurity) {
444         /* Clear the menu */
445         pMenu.removeAllItems();
446 
447         /* Record active item */
448         final MoneyWiseSecurityClass myType = pSecurity.getCategoryClass();
449         final MoneyWisePayee myCurr = pSecurity.getParent();
450         TethysUIScrollItem<MoneyWisePayee> myActive = null;
451 
452         /* Access Payees */
453         final MoneyWisePayeeList myPayees = getDataList(MoneyWiseBasicDataType.PAYEE, MoneyWisePayeeList.class);
454 
455         /* Loop through the Payees */
456         final Iterator<MoneyWisePayee> myIterator = myPayees.iterator();
457         while (myIterator.hasNext()) {
458             final MoneyWisePayee myPayee = myIterator.next();
459 
460             /* Ignore deleted or non-owner */
461             boolean bIgnore = myPayee.isDeleted() || !myPayee.getCategoryClass().canParentSecurity(myType);
462             bIgnore |= myPayee.isClosed();
463             if (bIgnore) {
464                 continue;
465             }
466 
467             /* Create a new action for the payee */
468             final TethysUIScrollItem<MoneyWisePayee> myItem = pMenu.addItem(myPayee);
469 
470             /* If this is the active parent */
471             if (myPayee.equals(myCurr)) {
472                 /* Record it */
473                 myActive = myItem;
474             }
475         }
476 
477         /* Ensure active item is visible */
478         if (myActive != null) {
479             myActive.scrollToItem();
480         }
481     }
482 
483     /**
484      * Build the region menu for an item.
485      *
486      * @param pMenu     the menu
487      * @param pSecurity the security to build for
488      */
489     public void buildRegionMenu(final TethysUIScrollMenu<MoneyWiseRegion> pMenu,
490                                 final MoneyWiseSecurity pSecurity) {
491         /* Clear the menu */
492         pMenu.removeAllItems();
493 
494         /* Record active item */
495         final MoneyWiseRegion myCurr = pSecurity.getRegion();
496         TethysUIScrollItem<MoneyWiseRegion> myActive = null;
497 
498         /* Access regions */
499         final MoneyWiseRegionList myRegions = getDataList(MoneyWiseBasicDataType.REGION, MoneyWiseRegionList.class);
500 
501         /* Loop through the Regions */
502         final Iterator<MoneyWiseRegion> myIterator = myRegions.iterator();
503         while (myIterator.hasNext()) {
504             final MoneyWiseRegion myRegion = myIterator.next();
505 
506             /* Ignore deleted */
507             final boolean bIgnore = myRegion.isDeleted();
508             if (bIgnore) {
509                 continue;
510             }
511 
512             /* Create a new action for the region */
513             final TethysUIScrollItem<MoneyWiseRegion> myItem = pMenu.addItem(myRegion);
514 
515             /* If this is the active region */
516             if (myRegion.equals(myCurr)) {
517                 /* Record it */
518                 myActive = myItem;
519             }
520         }
521 
522         /* Ensure active item is visible */
523         if (myActive != null) {
524             myActive.scrollToItem();
525         }
526     }
527 
528     /**
529      * Build the stock menu for an item.
530      *
531      * @param pMenu     the menu
532      * @param pSecurity the security to build for
533      */
534     public void buildStockMenu(final TethysUIScrollMenu<MoneyWiseSecurity> pMenu,
535                                final MoneyWiseSecurity pSecurity) {
536         /* Clear the menu */
537         pMenu.removeAllItems();
538 
539         /* Record active item */
540         final MoneyWiseSecurity myCurr = pSecurity.getUnderlyingStock();
541         TethysUIScrollItem<MoneyWiseSecurity> myActive = null;
542 
543         /* Access securities */
544         final MoneyWiseSecurityList mySecurities = getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class);
545 
546         /* Loop through the Securities */
547         final Iterator<MoneyWiseSecurity> myIterator = mySecurities.iterator();
548         while (myIterator.hasNext()) {
549             final MoneyWiseSecurity mySecurity = myIterator.next();
550 
551             /* Ignore deleted and non share */
552             boolean bIgnore = mySecurity.isDeleted();
553             bIgnore |= !mySecurity.getCategoryClass().isShares();
554             if (bIgnore) {
555                 continue;
556             }
557 
558             /* Create a new action for the region */
559             final TethysUIScrollItem<MoneyWiseSecurity> myItem = pMenu.addItem(mySecurity);
560 
561             /* If this is the active stock */
562             if (mySecurity.equals(myCurr)) {
563                 /* Record it */
564                 myActive = myItem;
565             }
566         }
567 
568         /* Ensure active item is visible */
569         if (myActive != null) {
570             myActive.scrollToItem();
571         }
572     }
573 
574     /**
575      * Build the currency menu for an item.
576      *
577      * @param pMenu     the menu
578      * @param pSecurity the security to build for
579      */
580     public void buildCurrencyMenu(final TethysUIScrollMenu<MoneyWiseCurrency> pMenu,
581                                   final MoneyWiseSecurity pSecurity) {
582         /* Clear the menu */
583         pMenu.removeAllItems();
584 
585         /* Record active item */
586         final MoneyWiseCurrency myCurr = pSecurity.getAssetCurrency();
587         TethysUIScrollItem<MoneyWiseCurrency> myActive = null;
588 
589         /* Access Currencies */
590         final MoneyWiseCurrencyList myCurrencies = getDataList(MoneyWiseStaticDataType.CURRENCY, MoneyWiseCurrencyList.class);
591 
592         /* Loop through the AccountCurrencies */
593         final Iterator<MoneyWiseCurrency> myIterator = myCurrencies.iterator();
594         while (myIterator.hasNext()) {
595             final MoneyWiseCurrency myCurrency = myIterator.next();
596 
597             /* Ignore deleted or disabled */
598             final boolean bIgnore = myCurrency.isDeleted() || !myCurrency.getEnabled();
599             if (bIgnore) {
600                 continue;
601             }
602 
603             /* Create a new action for the currency */
604             final TethysUIScrollItem<MoneyWiseCurrency> myItem = pMenu.addItem(myCurrency);
605 
606             /* If this is the active currency */
607             if (myCurrency.equals(myCurr)) {
608                 /* Record it */
609                 myActive = myItem;
610             }
611         }
612 
613         /* Ensure active item is visible */
614         if (myActive != null) {
615             myActive.scrollToItem();
616         }
617     }
618 }