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.MoneyWiseCashCategory;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseCashCategory.MoneyWiseCashCategoryList;
25  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCashCategoryClass;
26  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCashCategoryType;
27  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCashCategoryType.MoneyWiseCashCategoryTypeList;
28  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
29  import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseBaseTable;
30  import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseItemPanel;
31  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
32  import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSet;
33  import io.github.tonywasher.joceanus.prometheus.ui.fieldset.PrometheusFieldSetEvent;
34  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
35  import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
36  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIScrollButtonField;
37  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIDataEditField.TethysUIStringEditField;
38  import io.github.tonywasher.joceanus.tethys.api.field.TethysUIFieldFactory;
39  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollItem;
40  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
41  
42  import java.util.Iterator;
43  
44  /**
45   * Panel to display/edit/create a CashCategory.
46   */
47  public class MoneyWiseCashCategoryDialog
48          extends MoneyWiseItemPanel<MoneyWiseCashCategory> {
49      /**
50       * Constructor.
51       *
52       * @param pFactory the GUI factory
53       * @param pEditSet the edit set
54       * @param pOwner   the owning table
55       */
56      public MoneyWiseCashCategoryDialog(final TethysUIFactory<?> pFactory,
57                                         final PrometheusEditSet pEditSet,
58                                         final MoneyWiseBaseTable<MoneyWiseCashCategory> pOwner) {
59          /* Initialise the panel */
60          super(pFactory, pEditSet, pOwner);
61  
62          /* Create a new panel */
63          final PrometheusFieldSet<MoneyWiseCashCategory> myFieldSet = getFieldSet();
64  
65          /* Create the text fields */
66          final TethysUIFieldFactory myFields = pFactory.fieldFactory();
67          final TethysUIStringEditField myName = myFields.newStringField();
68          final TethysUIStringEditField mySubName = myFields.newStringField();
69          final TethysUIStringEditField myDesc = myFields.newStringField();
70  
71          /* Create the buttons */
72          final TethysUIScrollButtonField<MoneyWiseCashCategoryType> myTypeButton = myFields.newScrollField(MoneyWiseCashCategoryType.class);
73          final TethysUIScrollButtonField<MoneyWiseCashCategory> myParentButton = myFields.newScrollField(MoneyWiseCashCategory.class);
74  
75          /* Assign the fields to the panel */
76          myFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_NAME, myName, MoneyWiseCashCategory::getName);
77          myFieldSet.addField(MoneyWiseBasicResource.CATEGORY_SUBCAT, mySubName, MoneyWiseCashCategory::getSubCategory);
78          myFieldSet.addField(PrometheusDataResource.DATAITEM_FIELD_DESC, myDesc, MoneyWiseCashCategory::getDesc);
79          myFieldSet.addField(MoneyWiseStaticDataType.CASHTYPE, myTypeButton, MoneyWiseCashCategory::getCategoryType);
80          myFieldSet.addField(PrometheusDataResource.DATAGROUP_PARENT, myParentButton, MoneyWiseCashCategory::getParentCategory);
81  
82          /* Configure the menuBuilders */
83          myTypeButton.setMenuConfigurator(c -> buildCategoryTypeMenu(c, getItem()));
84          myParentButton.setMenuConfigurator(c -> buildParentMenu(c, getItem()));
85  
86          /* Configure name checks */
87          mySubName.setValidator(this::isValidName);
88          mySubName.setReporter(pOwner::showValidateError);
89  
90          /* Configure description checks */
91          myDesc.setValidator(this::isValidDesc);
92          myDesc.setReporter(pOwner::showValidateError);
93      }
94  
95      @Override
96      public void refreshData() {
97          /* If we have an item */
98          final MoneyWiseCashCategory myItem = getItem();
99          if (myItem != null) {
100             final MoneyWiseCashCategoryList myCategories = getDataList(MoneyWiseBasicDataType.CASHCATEGORY, MoneyWiseCashCategoryList.class);
101             setItem(myCategories.findItemById(myItem.getIndexedId()));
102         }
103 
104         /* Make sure that the item is not editable */
105         setEditable(false);
106     }
107 
108     @Override
109     protected void adjustFields(final boolean isEditable) {
110         /* Access the fieldSet */
111         final PrometheusFieldSet<MoneyWiseCashCategory> myFieldSet = getFieldSet();
112 
113         /* Determine whether parent/full-name fields are visible */
114         final MoneyWiseCashCategory myCategory = getItem();
115         final MoneyWiseCashCategoryType myType = myCategory.getCategoryType();
116         final boolean isParent = myType.isCashCategory(MoneyWiseCashCategoryClass.PARENT);
117 
118         /* Determine whether the description field should be visible */
119         final boolean bShowDesc = isEditable || myCategory.getDesc() != null;
120         myFieldSet.setFieldVisible(PrometheusDataResource.DATAITEM_FIELD_DESC, bShowDesc);
121 
122         /* Set visibility */
123         myFieldSet.setFieldVisible(PrometheusDataResource.DATAGROUP_PARENT, !isParent);
124         myFieldSet.setFieldVisible(MoneyWiseBasicResource.CATEGORY_SUBCAT, !isParent);
125 
126         /* If the category is active then we cannot change the category type */
127         boolean canEdit = isEditable && !myCategory.isActive();
128 
129         /* We cannot change a parent category type */
130         canEdit &= !isParent;
131         myFieldSet.setFieldEditable(MoneyWiseStaticDataType.CASHTYPE, canEdit);
132 
133         /* If the category is not a parent then we cannot edit the full name */
134         myFieldSet.setFieldEditable(PrometheusDataResource.DATAITEM_FIELD_NAME, isEditable && isParent);
135     }
136 
137     @Override
138     protected void updateField(final PrometheusFieldSetEvent pUpdate) throws OceanusException {
139         /* Access the field */
140         final MetisDataFieldId myField = pUpdate.getFieldId();
141         final MoneyWiseCashCategory myCategory = getItem();
142 
143         /* Process updates */
144         if (PrometheusDataResource.DATAITEM_FIELD_NAME.equals(myField)) {
145             /* Update the SUBCATEGORY(!!) Name */
146             myCategory.setSubCategoryName(pUpdate.getValue(String.class));
147         } else if (MoneyWiseBasicResource.CATEGORY_SUBCAT.equals(myField)) {
148             /* Update the SubCategory */
149             myCategory.setSubCategoryName(pUpdate.getValue(String.class));
150         } else if (PrometheusDataResource.DATAGROUP_PARENT.equals(myField)) {
151             /* Update the Parent */
152             myCategory.setParentCategory(pUpdate.getValue(MoneyWiseCashCategory.class));
153         } else if (PrometheusDataResource.DATAITEM_FIELD_DESC.equals(myField)) {
154             /* Update the Description */
155             myCategory.setDescription(pUpdate.getValue(String.class));
156         } else if (MoneyWiseStaticDataType.CASHTYPE.equals(myField)) {
157             /* Update the Category Type */
158             myCategory.setCategoryType(pUpdate.getValue(MoneyWiseCashCategoryType.class));
159         }
160     }
161 
162     @Override
163     protected void declareGoToItems(final boolean pUpdates) {
164         final MoneyWiseCashCategory myItem = getItem();
165         final MoneyWiseCashCategory myParent = myItem.getParentCategory();
166         if (!pUpdates) {
167             final MoneyWiseCashCategoryType myType = myItem.getCategoryType();
168             declareGoToItem(myType);
169         }
170         declareGoToItem(myParent);
171     }
172 
173     /**
174      * Build the category type menu for an item.
175      *
176      * @param pMenu     the menu
177      * @param pCategory the category to build for
178      */
179     public void buildCategoryTypeMenu(final TethysUIScrollMenu<MoneyWiseCashCategoryType> pMenu,
180                                       final MoneyWiseCashCategory pCategory) {
181         /* Clear the menu */
182         pMenu.removeAllItems();
183 
184         /* Record active item */
185         final MoneyWiseCashCategoryType myCurr = pCategory.getCategoryType();
186         TethysUIScrollItem<MoneyWiseCashCategoryType> myActive = null;
187 
188         /* Access Cash Category types */
189         final MoneyWiseCashCategoryTypeList myCategoryTypes = getDataList(MoneyWiseStaticDataType.CASHTYPE, MoneyWiseCashCategoryTypeList.class);
190 
191         /* Loop through the CashCategoryTypes */
192         final Iterator<MoneyWiseCashCategoryType> myIterator = myCategoryTypes.iterator();
193         while (myIterator.hasNext()) {
194             final MoneyWiseCashCategoryType myType = myIterator.next();
195 
196             /* Ignore deleted or disabled */
197             boolean bIgnore = myType.isDeleted() || !myType.getEnabled();
198 
199             /* Ignore category if it is a parent */
200             bIgnore |= myType.getCashClass().isParentCategory();
201             if (bIgnore) {
202                 continue;
203             }
204 
205             /* Create a new action for the type */
206             final TethysUIScrollItem<MoneyWiseCashCategoryType> myItem = pMenu.addItem(myType);
207 
208             /* If this is the active type */
209             if (myType.equals(myCurr)) {
210                 /* Record it */
211                 myActive = myItem;
212             }
213         }
214 
215         /* Ensure active item is visible */
216         if (myActive != null) {
217             myActive.scrollToItem();
218         }
219     }
220 
221     /**
222      * Build the parent menu for an item.
223      *
224      * @param pMenu     the menu
225      * @param pCategory the category to build for
226      */
227     private static void buildParentMenu(final TethysUIScrollMenu<MoneyWiseCashCategory> pMenu,
228                                         final MoneyWiseCashCategory pCategory) {
229         /* Clear the menu */
230         pMenu.removeAllItems();
231 
232         /* Record active item */
233         final MoneyWiseCashCategory myCurr = pCategory.getParentCategory();
234         TethysUIScrollItem<MoneyWiseCashCategory> myActive = null;
235 
236         /* Loop through the CashCategories */
237         final MoneyWiseCashCategoryList myCategories = pCategory.getList();
238         final Iterator<MoneyWiseCashCategory> myIterator = myCategories.iterator();
239         while (myIterator.hasNext()) {
240             final MoneyWiseCashCategory myCat = myIterator.next();
241 
242             /* Ignore deleted and non-parent items */
243             final MoneyWiseCashCategoryClass myClass = myCat.getCategoryTypeClass();
244             if (myCat.isDeleted() || !myClass.isParentCategory()) {
245                 continue;
246             }
247 
248             /* Create a new action for the type */
249             final TethysUIScrollItem<MoneyWiseCashCategory> myItem = pMenu.addItem(myCat);
250 
251             /* If this is the active parent */
252             if (myCat.equals(myCurr)) {
253                 /* Record it */
254                 myActive = myItem;
255             }
256         }
257 
258         /* Ensure active item is visible */
259         if (myActive != null) {
260             myActive.scrollToItem();
261         }
262     }
263 }