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.metis.data.MetisDataItem.MetisDataFieldId;
21  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
22  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicResource;
23  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee.MoneyWisePayeeList;
25  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoClass;
26  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAssetCategory;
27  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePayeeClass;
28  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePayeeType;
29  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePayeeType.MoneyWisePayeeTypeList;
30  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
31  import io.github.tonywasher.joceanus.moneywise.ui.MoneyWiseIcon;
32  import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseAssetTable;
33  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
34  import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSet;
35  import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSetEvent;
36  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
37  import io.github.tonywasher.joceanus.tethys.api.control.TethysUIControl.TethysUIIconMapSet;
38  import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
39  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUICharArrayEditField;
40  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUICharArrayTextAreaField;
41  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIIconButtonField;
42  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIScrollButtonField;
43  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIStringEditField;
44  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIFieldFactory;
45  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
46  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
47  
48  import java.util.Iterator;
49  import java.util.Map;
50  
51  /**
52   * Panel to display/edit/create a Payee.
53   */
54  public class MoneyWisePayeeDialog
55          extends MoneyWiseAssetDialog<MoneyWisePayee> {
56      /**
57       * The fieldSet.
58       */
59      private final PrometheusFieldSet<MoneyWisePayee> theFieldSet;
60  
61      /**
62       * The Closed State.
63       */
64      private Boolean theClosedState = Boolean.FALSE;
65  
66      /**
67       * Constructor.
68       *
69       * @param pFactory the GUI factory
70       * @param pEditSet the edit set
71       * @param pOwner   the owning table
72       */
73      public MoneyWisePayeeDialog(final TethysUIFactory<?> pFactory,
74                                  final PrometheusEditSet pEditSet,
75                                  final MoneyWiseAssetTable<MoneyWisePayee> pOwner) {
76          /* Initialise the panel */
77          super(pFactory, pEditSet, pOwner);
78  
79          /* Access the fieldSet */
80          theFieldSet = getFieldSet();
81          theFieldSet.setReporter(pOwner::showValidateError);
82  
83          /* Build the main panel */
84          buildMainPanel(pFactory);
85  
86          /* Build the account panel */
87          buildAccountPanel(pFactory);
88  
89          /* Build the web panel */
90          buildWebPanel(pFactory);
91  
92          /* Build the notes panel */
93          buildNotesPanel(pFactory);
94      }
95  
96      /**
97       * Build Main subPanel.
98       *
99       * @param pFactory the GUI factory
100      */
101     private void buildMainPanel(final TethysUIFactory<?> pFactory) {
102         /* Create the text fields */
103         final TethysUIFieldFactory myFields = pFactory.fieldFactory();
104         final TethysUIStringEditField myName = myFields.newStringField();
105         final TethysUIStringEditField myDesc = myFields.newStringField();
106 
107         /* Create the buttons */
108         final TethysUIScrollButtonField<MoneyWiseAssetCategory> myTypeButton = myFields.newScrollField(MoneyWiseAssetCategory.class);
109         final TethysUIIconButtonField<Boolean> myClosedButton = myFields.newIconField(Boolean.class);
110 
111         /* Assign the fields to the panel */
112         theFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_NAME, myName, MoneyWisePayee::getName);
113         theFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_DESC, myDesc, MoneyWisePayee::getDesc);
114         theFieldSet.addField(MoneyWiseBasicResource.CATEGORY_NAME, myTypeButton, MoneyWisePayee::getCategory);
115         theFieldSet.addField(MoneyWiseBasicResource.ASSET_CLOSED, myClosedButton, MoneyWisePayee::isClosed);
116 
117         /* Configure the menuBuilders */
118         myTypeButton.setMenuConfigurator(c -> buildPayeeTypeMenu(c, getItem()));
119         final Map<Boolean, TethysUIIconMapSet<Boolean>> myMapSets = MoneyWiseIcon.configureLockedIconButton(pFactory);
120         myClosedButton.setIconMapSet(() -> myMapSets.get(theClosedState));
121 
122         /* Configure validation checks */
123         myName.setValidator(this::isValidName);
124         myDesc.setValidator(this::isValidDesc);
125     }
126 
127     /**
128      * Build account subPanel.
129      *
130      * @param pFactory the GUI factory
131      */
132     private void buildAccountPanel(final TethysUIFactory<?> pFactory) {
133         /* Create a new panel */
134         theFieldSet.newPanel(TAB_ACCOUNT);
135 
136         /* Allocate fields */
137         final TethysUIFieldFactory myFields = pFactory.fieldFactory();
138         final TethysUICharArrayEditField mySortCode = myFields.newCharArrayField();
139         final TethysUICharArrayEditField myAccount = myFields.newCharArrayField();
140         final TethysUICharArrayEditField myReference = myFields.newCharArrayField();
141 
142         /* Assign the fields to the panel */
143         theFieldSet.addField(MoneyWiseAccountInfoClass.SORTCODE, mySortCode, MoneyWisePayee::getSortCode);
144         theFieldSet.addField(MoneyWiseAccountInfoClass.ACCOUNT, myAccount, MoneyWisePayee::getAccount);
145         theFieldSet.addField(MoneyWiseAccountInfoClass.REFERENCE, myReference, MoneyWisePayee::getReference);
146 
147         /* Configure validation checks */
148         mySortCode.setValidator(this::isValidSortCode);
149         myAccount.setValidator(this::isValidAccount);
150         myReference.setValidator(this::isValidReference);
151     }
152 
153     /**
154      * Build web subPanel.
155      *
156      * @param pFactory the GUI factory
157      */
158     private void buildWebPanel(final TethysUIFactory<?> pFactory) {
159         /* Create a new panel */
160         theFieldSet.newPanel(TAB_WEB);
161 
162         /* Allocate fields */
163         final TethysUIFieldFactory myFields = pFactory.fieldFactory();
164         final TethysUICharArrayEditField myWebSite = myFields.newCharArrayField();
165         final TethysUICharArrayEditField myCustNo = myFields.newCharArrayField();
166         final TethysUICharArrayEditField myUserId = myFields.newCharArrayField();
167         final TethysUICharArrayEditField myPassWord = myFields.newCharArrayField();
168 
169         /* Assign the fields to the panel */
170         theFieldSet.addField(MoneyWiseAccountInfoClass.WEBSITE, myWebSite, MoneyWisePayee::getWebSite);
171         theFieldSet.addField(MoneyWiseAccountInfoClass.CUSTOMERNO, myCustNo, MoneyWisePayee::getCustNo);
172         theFieldSet.addField(MoneyWiseAccountInfoClass.USERID, myUserId, MoneyWisePayee::getUserId);
173         theFieldSet.addField(MoneyWiseAccountInfoClass.PASSWORD, myPassWord, MoneyWisePayee::getPassword);
174 
175         /* Configure validation checks */
176         myWebSite.setValidator(this::isValidWebSite);
177         myCustNo.setValidator(this::isValidCustNo);
178         myUserId.setValidator(this::isValidUserId);
179         myPassWord.setValidator(this::isValidPassword);
180     }
181 
182     /**
183      * Build Notes subPanel.
184      *
185      * @param pFactory the GUI factory
186      */
187     private void buildNotesPanel(final TethysUIFactory<?> pFactory) {
188         /* Allocate fields */
189         final TethysUIFieldFactory myFields = pFactory.fieldFactory();
190         final TethysUICharArrayTextAreaField myNotes = myFields.newCharArrayAreaField();
191 
192         /* Assign the fields to the panel */
193         theFieldSet.newTextArea(TAB_NOTES, MoneyWiseAccountInfoClass.NOTES, myNotes, MoneyWisePayee::getNotes);
194 
195         /* Configure validation checks */
196         myNotes.setValidator(this::isValidNotes);
197     }
198 
199     @Override
200     public void refreshData() {
201         /* If we have an item */
202         final MoneyWisePayee myItem = getItem();
203         if (myItem != null) {
204             final MoneyWisePayeeList myPayees = getDataList(MoneyWiseBasicDataType.PAYEE, MoneyWisePayeeList.class);
205             setItem(myPayees.findItemById(myItem.getIndexedId()));
206         }
207 
208         /* Make sure that the item is not editable */
209         setEditable(false);
210     }
211 
212     @Override
213     protected void adjustFields(final boolean isEditable) {
214         /* Access the item */
215         final MoneyWisePayee myPayee = getItem();
216         final boolean bIsClosed = myPayee.isClosed();
217         final boolean bIsActive = myPayee.isActive();
218         final boolean bIsRelevant = myPayee.isRelevant();
219 
220         /* Determine whether the closed button should be visible */
221         final boolean bShowClosed = bIsClosed || (bIsActive && !bIsRelevant);
222         theFieldSet.setFieldVisible(MoneyWiseBasicResource.ASSET_CLOSED, bShowClosed);
223 
224         /* Determine the state of the closed button */
225         final boolean bEditClosed = bIsClosed || !bIsRelevant;
226         theFieldSet.setFieldEditable(MoneyWiseBasicResource.ASSET_CLOSED, isEditable && bEditClosed);
227         theClosedState = bEditClosed;
228 
229         /* Determine whether the description field should be visible */
230         final boolean bShowDesc = isEditable || myPayee.getDesc() != null;
231         theFieldSet.setFieldVisible(PrometheusDataResource.DATAITEM_FIELD_DESC, bShowDesc);
232 
233         /* Determine whether the account details should be visible */
234         final boolean bShowSortCode = isEditable || myPayee.getSortCode() != null;
235         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.SORTCODE, bShowSortCode);
236         final boolean bShowAccount = isEditable || myPayee.getAccount() != null;
237         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.ACCOUNT, bShowAccount);
238         final boolean bShowReference = isEditable || myPayee.getReference() != null;
239         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.REFERENCE, bShowReference);
240         final boolean bShowWebSite = isEditable || myPayee.getWebSite() != null;
241         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.WEBSITE, bShowWebSite);
242         final boolean bShowCustNo = isEditable || myPayee.getCustNo() != null;
243         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.CUSTOMERNO, bShowCustNo);
244         final boolean bShowUserId = isEditable || myPayee.getUserId() != null;
245         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.USERID, bShowUserId);
246         final boolean bShowPasswd = isEditable || myPayee.getPassword() != null;
247         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.PASSWORD, bShowPasswd);
248         final boolean bShowNotes = isEditable || myPayee.getNotes() != null;
249         theFieldSet.setFieldVisible(MoneyWiseAccountInfoClass.NOTES, bShowNotes);
250 
251         /* Payee type cannot be changed if the item is singular, or if its relevant */
252         final MoneyWisePayeeClass myClass = myPayee.getCategoryClass();
253         final boolean bIsSingular = myClass.isSingular();
254         theFieldSet.setFieldEditable(MoneyWiseBasicResource.CATEGORY_NAME, isEditable && !bIsSingular && !bIsRelevant);
255     }
256 
257     @Override
258     protected void updateField(final PrometheusFieldSetEvent pUpdate) throws OceanusException {
259         /* Access the field */
260         final MetisDataFieldId myField = pUpdate.getFieldId();
261         final MoneyWisePayee myPayee = getItem();
262 
263         /* Process updates */
264         if (PrometheusDataResource.DATAITEM_FIELD_NAME.equals(myField)) {
265             /* Update the Name */
266             myPayee.setName(pUpdate.getValue(String.class));
267         } else if (PrometheusDataResource.DATAITEM_FIELD_DESC.equals(myField)) {
268             /* Update the Description */
269             myPayee.setDescription(pUpdate.getValue(String.class));
270         } else if (MoneyWiseBasicResource.CATEGORY_NAME.equals(myField)) {
271             /* Update the Payee Type */
272             myPayee.setCategory(pUpdate.getValue(MoneyWisePayeeType.class));
273         } else if (MoneyWiseBasicResource.ASSET_CLOSED.equals(myField)) {
274             /* Update the Closed indication */
275             myPayee.setClosed(pUpdate.getValue(Boolean.class));
276         } else if (MoneyWiseAccountInfoClass.SORTCODE.equals(myField)) {
277             /* Update the SortCode */
278             myPayee.setSortCode(pUpdate.getValue(char[].class));
279         } else if (MoneyWiseAccountInfoClass.ACCOUNT.equals(myField)) {
280             /* Update the Account */
281             myPayee.setAccount(pUpdate.getValue(char[].class));
282         } else if (MoneyWiseAccountInfoClass.REFERENCE.equals(myField)) {
283             /* Update the Reference */
284             myPayee.setReference(pUpdate.getValue(char[].class));
285         } else if (MoneyWiseAccountInfoClass.WEBSITE.equals(myField)) {
286             /* Update the WebSite */
287             myPayee.setWebSite(pUpdate.getValue(char[].class));
288         } else if (MoneyWiseAccountInfoClass.CUSTOMERNO.equals(myField)) {
289             /* Update the Customer# */
290             myPayee.setCustNo(pUpdate.getValue(char[].class));
291         } else if (MoneyWiseAccountInfoClass.USERID.equals(myField)) {
292             /* Update the UserId */
293             myPayee.setUserId(pUpdate.getValue(char[].class));
294         } else if (MoneyWiseAccountInfoClass.PASSWORD.equals(myField)) {
295             /* Update the Password */
296             myPayee.setPassword(pUpdate.getValue(char[].class));
297         } else if (MoneyWiseAccountInfoClass.NOTES.equals(myField)) {
298             /* Update the Notes */
299             myPayee.setNotes(pUpdate.getValue(char[].class));
300         }
301     }
302 
303     @Override
304     protected void declareGoToItems(final boolean pUpdates) {
305         if (!pUpdates) {
306             final MoneyWisePayee myItem = getItem();
307             final MoneyWisePayeeType myType = myItem.getCategory();
308             declareGoToItem(myType);
309         }
310     }
311 
312     /**
313      * Build the payeeType menu for an item.
314      *
315      * @param pMenu  the menu
316      * @param pPayee the payee to build for
317      */
318     public void buildPayeeTypeMenu(final TethysUIScrollMenu<MoneyWiseAssetCategory> pMenu,
319                                    final MoneyWisePayee pPayee) {
320         /* Clear the menu */
321         pMenu.removeAllItems();
322 
323         /* Record active item */
324         final MoneyWisePayeeType myCurr = pPayee.getCategory();
325         final MoneyWisePayeeList myList = pPayee.getList();
326         TethysUIScrollItem<MoneyWiseAssetCategory> myActive = null;
327 
328         /* Access PayeeTypes */
329         final MoneyWisePayeeTypeList myTypes = getDataList(MoneyWiseStaticDataType.PAYEETYPE, MoneyWisePayeeTypeList.class);
330 
331         /* Loop through the PayeeTypes */
332         final Iterator<MoneyWisePayeeType> myIterator = myTypes.iterator();
333         while (myIterator.hasNext()) {
334             final MoneyWisePayeeType myType = myIterator.next();
335 
336             /* Ignore deleted or disabled */
337             boolean bIgnore = myType.isDeleted() || !myType.getEnabled();
338 
339             /* If the type is a likely candidate */
340             if (!bIgnore) {
341                 /* Check for singular class */
342                 final MoneyWisePayeeClass myClass = myType.getPayeeClass();
343                 if (myClass.isSingular()) {
344                     /* Cannot change to this type if one already exists */
345                     final MoneyWisePayee myExisting = myList.getSingularClass(myClass);
346                     bIgnore = myExisting != null;
347                 }
348             }
349 
350             /* Skip record if necessary */
351             if (bIgnore) {
352                 continue;
353             }
354 
355             /* Create a new action for the payeeType */
356             final TethysUIScrollItem<MoneyWiseAssetCategory> myItem = pMenu.addItem(myType);
357 
358             /* If this is the active type */
359             if (myType.equals(myCurr)) {
360                 /* Record it */
361                 myActive = myItem;
362             }
363         }
364 
365         /* Ensure active item is visible */
366         if (myActive != null) {
367             myActive.scrollToItem();
368         }
369     }
370 }