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.MoneyWiseCategoryBase;
26  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDataSet;
27  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDepositCategory;
28  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDepositCategory.MoneyWiseDepositCategoryList;
29  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseDepositCategoryClass;
30  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseDepositCategoryType;
31  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
32  import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseDataException;
33  import io.github.tonywasher.joceanus.moneywise.ui.base.MoneyWiseCategoryTable;
34  import io.github.tonywasher.joceanus.moneywise.ui.dialog.MoneyWiseDepositCategoryDialog;
35  import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseView;
36  import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
37  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
38  import io.github.tonywasher.joceanus.tethys.api.factory.TethysUIFactory;
39  import io.github.tonywasher.joceanus.tethys.api.menu.TethysUIScrollMenu;
40  import io.github.tonywasher.joceanus.tethys.api.table.TethysUITableManager;
41  
42  import java.util.List;
43  
44  /**
45   * MoneyWise DepositCategory Table.
46   */
47  public class MoneyWiseDepositCategoryTable
48          extends MoneyWiseCategoryTable<MoneyWiseDepositCategory, MoneyWiseDepositCategoryType> {
49      /**
50       * The Category dialog.
51       */
52      private final MoneyWiseDepositCategoryDialog theActiveCategory;
53  
54      /**
55       * The edit list.
56       */
57      private MoneyWiseDepositCategoryList theCategories;
58  
59      /**
60       * Constructor.
61       *
62       * @param pView    the view
63       * @param pEditSet the editSet
64       * @param pError   the error panel
65       */
66      MoneyWiseDepositCategoryTable(final MoneyWiseView pView,
67                                    final PrometheusEditSet pEditSet,
68                                    final MetisErrorPanel pError) {
69          /* Store parameters */
70          super(pView, pEditSet, pError, MoneyWiseDepositCategory.class, MoneyWiseBasicDataType.DEPOSITCATEGORY);
71  
72          /* Access Gui factory */
73          final TethysUIFactory<?> myGuiFactory = pView.getGuiFactory();
74  
75          /* Create a category panel */
76          theActiveCategory = new MoneyWiseDepositCategoryDialog(myGuiFactory, pEditSet, this);
77          declareItemPanel(theActiveCategory);
78  
79          /* Add listeners */
80          theActiveCategory.getEventRegistrar().addEventListener(PrometheusDataEvent.ADJUSTVISIBILITY, e -> handlePanelState());
81      }
82  
83      @Override
84      protected void addCategoryTypeColumn() {
85          final TethysUITableManager<MetisDataFieldId, MoneyWiseDepositCategory> myTable = getTable();
86          myTable.declareScrollColumn(MoneyWiseStaticDataType.DEPOSITTYPE, MoneyWiseDepositCategoryType.class)
87                  .setMenuConfigurator(this::buildCategoryTypeMenu)
88                  .setCellValueFactory(MoneyWiseDepositCategory::getCategoryType)
89                  .setEditable(true)
90                  .setCellEditable(r -> !r.isActive())
91                  .setColumnWidth(WIDTH_NAME)
92                  .setOnCommit((r, v) -> updateField(MoneyWiseCategoryBase::setCategoryType, r, v));
93      }
94  
95      @Override
96      protected boolean isItemEditing() {
97          return theActiveCategory.isEditing();
98      }
99  
100     @Override
101     protected List<MoneyWiseDepositCategory> getCategories() {
102         return theCategories == null ? null : theCategories.getUnderlyingList();
103     }
104 
105     @Override
106     protected boolean isChildCategory(final MoneyWiseDepositCategoryType pCategoryType) {
107         return !pCategoryType.getDepositClass().isParentCategory();
108     }
109 
110     @Override
111     protected void refreshData() throws OceanusException {
112         /* Obtain the active profile */
113         OceanusProfile myTask = getView().getActiveTask();
114         myTask = myTask.startTask("DepositCategories");
115 
116         /* Access list */
117         final MoneyWiseDataSet myData = getView().getData();
118         final MoneyWiseDepositCategoryList myBase = myData.getDepositCategories();
119         theCategories = myBase.deriveEditList(getEditSet());
120         getTable().setItems(theCategories.getUnderlyingList());
121 
122         /* If we have a parent */
123         MoneyWiseDepositCategory myParent = getParent();
124         if (myParent != null) {
125             /* Update the parent via the edit list */
126             myParent = theCategories.findItemById(myParent.getIndexedId());
127             updateParent(myParent);
128         }
129 
130         /* Notify panel of refresh */
131         theActiveCategory.refreshData();
132         restoreSelected();
133 
134         /* Complete the task */
135         myTask.end();
136     }
137 
138     @Override
139     public void cancelEditing() {
140         super.cancelEditing();
141         theActiveCategory.setEditable(false);
142     }
143 
144     /**
145      * Select category.
146      *
147      * @param pCategory the category to select
148      */
149     void selectCategory(final MoneyWiseDepositCategory pCategory) {
150         /* If we are changing the selection */
151         final MoneyWiseDepositCategory myCurrent = theActiveCategory.getSelectedItem();
152         if (!MetisDataDifference.isEqual(myCurrent, pCategory)) {
153             /* Ensure the correct parent is selected */
154             MoneyWiseDepositCategory myParent = pCategory.getParentCategory();
155             if (!MetisDataDifference.isEqual(getParent(), myParent)) {
156                 if (myParent != null) {
157                     myParent = theCategories.findItemById(myParent.getIndexedId());
158                 }
159                 selectParent(myParent);
160             }
161 
162             /* Select the row and ensure that it is visible */
163             getTable().selectRow(pCategory);
164         }
165     }
166 
167     @Override
168     protected void handleRewind() {
169         /* Only action if we are not editing */
170         if (!theActiveCategory.isEditing()) {
171             /* Handle the reWind */
172             setEnabled(true);
173             super.handleRewind();
174         }
175 
176         /* Adjust for changes */
177         notifyChanges();
178     }
179 
180     /**
181      * Handle panel state.
182      */
183     private void handlePanelState() {
184         /* Only action if we are not editing */
185         if (!theActiveCategory.isEditing()) {
186             /* handle the edit transition */
187             setEnabled(true);
188             final MoneyWiseDepositCategory myCategory = theActiveCategory.getSelectedItem();
189             updateTableData();
190             if (myCategory != null) {
191                 getTable().selectRow(myCategory);
192             } else {
193                 restoreSelected();
194             }
195         } else {
196             getTable().cancelEditing();
197         }
198 
199         /* Note changes */
200         notifyChanges();
201     }
202 
203     @Override
204     protected void buildCategoryTypeMenu(final MoneyWiseDepositCategory pCategory,
205                                          final TethysUIScrollMenu<MoneyWiseDepositCategoryType> pMenu) {
206         /* Build the menu */
207         theActiveCategory.buildCategoryTypeMenu(pMenu, pCategory);
208     }
209 
210     @Override
211     protected void addNewItem() {
212         /* Protect against Exceptions */
213         try {
214             /* Make sure that we have finished editing */
215             cancelEditing();
216 
217             /* Create a new profile */
218             final OceanusProfile myTask = getView().getNewProfile("addNewItem");
219 
220             /* Create the new category */
221             myTask.startTask("buildItem");
222             final MoneyWiseDepositCategory myCategory = theCategories.addNewItem();
223             myCategory.setDefaults(getParent());
224 
225             /* Set as new and adjust map */
226             myTask.startTask("incrementVersion");
227             myCategory.setNewVersion();
228             myCategory.adjustMapForItem();
229             getEditSet().incrementVersion();
230 
231             /* Validate the new item */
232             myTask.startTask("validate");
233             myCategory.validate();
234 
235             /* update panel */
236             myTask.startTask("setItem");
237             theActiveCategory.setNewItem(myCategory);
238 
239             /* Lock the table */
240             setTableEnabled(false);
241             myTask.end();
242 
243             /* Handle Exceptions */
244         } catch (OceanusException e) {
245             /* Build the error */
246             final OceanusException myError = new MoneyWiseDataException("Failed to create new category", e);
247 
248             /* Show the error */
249             setError(myError);
250         }
251     }
252 
253     @Override
254     protected boolean isFiltered(final MoneyWiseDepositCategory pRow) {
255         final MoneyWiseDepositCategory myParent = getParent();
256         return super.isFiltered(pRow) && (myParent == null
257                 ? pRow.isCategoryClass(MoneyWiseDepositCategoryClass.PARENT)
258                 : myParent.equals(pRow.getParentCategory()));
259     }
260 }