]> git.ktnx.net Git - mobile-ledger.git/blobdiff - app/src/main/java/net/ktnx/mobileledger/ui/new_transaction/NewTransactionModel.java
make transaction header row always have Id of 0
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / ui / new_transaction / NewTransactionModel.java
index 637518f2eef27b446dd7977d44a7ea8040c27174..36b457ff4bf76bc1c0973a1db085196c2f3ee4e3 100644 (file)
@@ -93,7 +93,6 @@ public class NewTransactionModel extends ViewModel {
         setItemsWithoutSubmittableChecks(newList);
     }
     private void setItemsWithoutSubmittableChecks(@NonNull List<Item> list) {
-        Logger.debug("new-trans", "model: Setting new item list");
         final int cnt = list.size();
         for (int i = 1; i < cnt - 1; i++) {
             final TransactionAccount item = list.get(i)
@@ -112,14 +111,13 @@ public class NewTransactionModel extends ViewModel {
             list.set(cnt - 1, replacement);
         }
 
+        if (BuildConfig.DEBUG)
+            dumpItemList("Before setValue()", list);
         items.setValue(list);
     }
     private List<Item> copyList() {
-        return copyList(null);
-    }
-    private List<Item> copyList(@Nullable List<Item> source) {
         List<Item> copy = new ArrayList<>();
-        List<Item> oldList = (source == null) ? items.getValue() : source;
+        List<Item> oldList = items.getValue();
 
         if (oldList != null)
             for (Item item : oldList) {
@@ -128,7 +126,7 @@ public class NewTransactionModel extends ViewModel {
 
         return copy;
     }
-    private List<Item> shallowCopyListWithoutItem(int position) {
+    private List<Item> copyListWithoutItem(int position) {
         List<Item> copy = new ArrayList<>();
         List<Item> oldList = items.getValue();
 
@@ -137,7 +135,7 @@ public class NewTransactionModel extends ViewModel {
             for (Item item : oldList) {
                 if (i++ == position)
                     continue;
-                copy.add(item);
+                copy.add(Item.from(item));
             }
         }
 
@@ -172,10 +170,12 @@ public class NewTransactionModel extends ViewModel {
     void reset() {
         Logger.debug("new-trans", "Resetting model");
         List<Item> list = new ArrayList<>();
+        Item.resetIdDispenser();
         list.add(new TransactionHead(""));
         list.add(new TransactionAccount(""));
         list.add(new TransactionAccount(""));
         noteFocusChanged(0, FocusedElement.Description);
+        isSubmittable.setValue(false);
         setItemsWithoutSubmittableChecks(list);
     }
     boolean accountsInInitialState() {
@@ -330,7 +330,11 @@ public class NewTransactionModel extends ViewModel {
         return null;
     }
     void removeItem(int pos) {
-        List<Item> newList = shallowCopyListWithoutItem(pos);
+        Logger.debug("new-trans", String.format(Locale.US, "Removing item at position %d", pos));
+        List<Item> newList = copyListWithoutItem(pos);
+        final FocusInfo fi = focusInfo.getValue();
+        if ((fi != null) && (pos < fi.position))
+            noteFocusChanged(fi.position - 1, fi.element);
         setItems(newList);
     }
     void noteFocusChanged(int position, FocusedElement element) {
@@ -345,6 +349,11 @@ public class NewTransactionModel extends ViewModel {
         List<Item> newList = shallowCopyList();
         Item item = newList.remove(fromIndex);
         newList.add(toIndex, item);
+
+        FocusInfo fi = focusInfo.getValue();
+        if (fi != null && fi.position == fromIndex)
+            noteFocusChanged(toIndex, fi.element);
+
         items.setValue(newList); // same count, same submittable state
     }
     void moveItemLast(List<Item> list, int index) {
@@ -360,7 +369,20 @@ public class NewTransactionModel extends ViewModel {
             list.add(list.remove(index));
     }
     void toggleCurrencyVisible() {
-        showCurrency.setValue(!Objects.requireNonNull(showCurrency.getValue()));
+        final boolean newValue = !Objects.requireNonNull(showCurrency.getValue());
+
+        // remove currency from all items, or reset currency to the default
+        // no need to clone the list, because the removal of the currency won't lead to
+        // visual changes -- the currency fields will be hidden or reset to default anyway
+        // still, there may be changes in the submittable state
+        final List<Item> list = Objects.requireNonNull(this.items.getValue());
+        for (int i = 1; i < list.size(); i++) {
+            ((TransactionAccount) list.get(i)).setCurrency(newValue ? Data.getProfile()
+                                                                          .getDefaultCommodity()
+                                                                    : null);
+        }
+        checkTransactionSubmittable(null);
+        showCurrency.setValue(newValue);
     }
     void stopObservingBusyFlag(Observer<Boolean> observer) {
         busyFlag.removeObserver(observer);
@@ -421,6 +443,7 @@ public class NewTransactionModel extends ViewModel {
     }
     void loadTransactionIntoModel(String profileUUID, int transactionId) {
         List<Item> newList = new ArrayList<>();
+        Item.resetIdDispenser();
         LedgerTransaction tr;
         MobileLedgerProfile profile = Data.getProfile(profileUUID);
         if (profile == null)
@@ -507,14 +530,14 @@ public class NewTransactionModel extends ViewModel {
     @SuppressLint("DefaultLocale")
     void checkTransactionSubmittable(@Nullable List<Item> list) {
         boolean workingWithLiveList = false;
-        boolean liveListCopied = false;
         if (list == null) {
-            list = Objects.requireNonNull(items.getValue());
+            list = copyList();
             workingWithLiveList = true;
         }
 
         if (BuildConfig.DEBUG)
-            dumpItemList("Before submittable checks", list);
+            dumpItemList(String.format("Before submittable checks (%s)",
+                    workingWithLiveList ? "LIVE LIST" : "custom list"), list);
 
         int accounts = 0;
         final BalanceForCurrency balance = new BalanceForCurrency();
@@ -613,25 +636,15 @@ public class NewTransactionModel extends ViewModel {
                         if (Misc.equalStrings(acc.getCurrency(), balCurrency)) {
                             if (BuildConfig.DEBUG)
                                 Logger.debug("submittable",
-                                        String.format("Resetting hint of '%s' [%s]",
-                                                Misc.nullIsEmpty(acc.getAccountName()),
+                                        String.format(Locale.US, "Resetting hint of %d:'%s' [%s]",
+                                                i, Misc.nullIsEmpty(acc.getAccountName()),
                                                 balCurrency));
                             // skip if the amount is set, in which case the hint is not
                             // important/visible
                             if (!acc.isAmountSet() && acc.amountHintIsSet &&
                                 !TextUtils.isEmpty(acc.getAmountHint()))
                             {
-                                if (workingWithLiveList && !liveListCopied) {
-                                    list = copyList(list);
-                                    liveListCopied = true;
-                                }
-                                final TransactionAccount newAcc = new TransactionAccount(acc);
-                                newAcc.setAmountHint(null);
-                                if (!liveListCopied) {
-                                    list = copyList(list);
-                                    liveListCopied = true;
-                                }
-                                list.set(i, newAcc);
+                                acc.setAmountHint(null);
                                 listChanged = true;
                             }
                         }
@@ -677,18 +690,12 @@ public class NewTransactionModel extends ViewModel {
                         if (item == receiver) {
                             final String hint = String.format("%1.2f", -currencyBalance);
                             if (!acc.isAmountHintSet() ||
-                                !TextUtils.equals(acc.getAmountHint(), hint))
+                                !Misc.equalStrings(acc.getAmountHint(), hint))
                             {
                                 Logger.debug("submittable",
                                         String.format("Setting amount hint of {%s} to %s [%s]",
                                                 acc.toString(), hint, balCurrency));
-                                if (workingWithLiveList & !liveListCopied) {
-                                    list = copyList(list);
-                                    liveListCopied = true;
-                                }
-                                final TransactionAccount newAcc = new TransactionAccount(acc);
-                                newAcc.setAmountHint(hint);
-                                list.set(i, newAcc);
+                                acc.setAmountHint(hint);
                                 listChanged = true;
                             }
                         }
@@ -699,13 +706,7 @@ public class NewTransactionModel extends ViewModel {
                                                 Misc.nullIsEmpty(acc.getAccountName()),
                                                 balCurrency));
                             if (acc.amountHintIsSet && !TextUtils.isEmpty(acc.getAmountHint())) {
-                                if (workingWithLiveList && !liveListCopied) {
-                                    list = copyList(list);
-                                    liveListCopied = true;
-                                }
-                                final TransactionAccount newAcc = new TransactionAccount(acc);
-                                newAcc.setAmountHint(null);
-                                list.set(i, newAcc);
+                                acc.setAmountHint(null);
                                 listChanged = true;
                             }
                         }
@@ -740,10 +741,6 @@ public class NewTransactionModel extends ViewModel {
 //                        }
 //
 //                        if (!foundIt)
-                    if (workingWithLiveList && !liveListCopied) {
-                        list = copyList(list);
-                        liveListCopied = true;
-                    }
                     final TransactionAccount newAcc = new TransactionAccount("", balCurrency);
                     final float bal = balance.get(balCurrency);
                     if (!Misc.isZero(bal) && currAmounts == currRows)
@@ -760,10 +757,6 @@ public class NewTransactionModel extends ViewModel {
             for (String currName : emptyRowsForCurrency.currencies()) {
                 List<Item> emptyItems = emptyRowsForCurrency.getList(currName);
                 while ((list.size() > MIN_ITEMS) && (emptyItems.size() > 1)) {
-                    if (workingWithLiveList && !liveListCopied) {
-                        list = copyList(list);
-                        liveListCopied = true;
-                    }
                     // the list is a copy, so the empty item is no longer present
                     Item itemToRemove = emptyItems.remove(1);
                     removeItemById(list, itemToRemove.id);
@@ -775,10 +768,6 @@ public class NewTransactionModel extends ViewModel {
                     List<Item> currItems = itemsForCurrency.getList(currName);
 
                     if (currItems.size() == 1) {
-                        if (workingWithLiveList && !liveListCopied) {
-                            list = copyList(list);
-                            liveListCopied = true;
-                        }
                         // the list is a copy, so the empty item is no longer present
                         removeItemById(list, emptyItems.get(0).id);
                         listChanged = true;
@@ -789,15 +778,10 @@ public class NewTransactionModel extends ViewModel {
             // 6) at least two rows need to be present in the ledger
             //    (the list also contains header and trailer)
             while (list.size() < MIN_ITEMS) {
-                if (workingWithLiveList && !liveListCopied) {
-                    list = copyList(list);
-                    liveListCopied = true;
-                }
                 list.add(new TransactionAccount(""));
                 listChanged = true;
             }
 
-
             Logger.debug("submittable", submittable ? "YES" : "NO");
             isSubmittable.setValue(submittable);
 
@@ -881,11 +865,17 @@ public class NewTransactionModel extends ViewModel {
 
     static abstract class Item {
         private static int idDispenser = 0;
-        protected int id;
+        protected final int id;
         private Item() {
-            synchronized (Item.class) {
-                id = ++idDispenser;
-            }
+            if (this instanceof TransactionHead)
+                id = 0;
+            else
+                synchronized (Item.class) {
+                    id = ++idDispenser;
+                }
+        }
+        public Item(int id) {
+            this.id = id;
         }
         public static Item from(Item origin) {
             if (origin instanceof TransactionHead)
@@ -894,6 +884,9 @@ public class NewTransactionModel extends ViewModel {
                 return new TransactionAccount((TransactionAccount) origin);
             throw new RuntimeException("Don't know how to handle " + origin);
         }
+        private static void resetIdDispenser() {
+            idDispenser = 0;
+        }
         public int getId() {
             return id;
         }
@@ -942,7 +935,7 @@ public class NewTransactionModel extends ViewModel {
             this.description = description;
         }
         public TransactionHead(TransactionHead origin) {
-            id = origin.id;
+            super(origin.id);
             date = origin.date;
             description = origin.description;
             comment = origin.comment;
@@ -991,7 +984,7 @@ public class NewTransactionModel extends ViewModel {
             if (TextUtils.isEmpty(description))
                 b.append(" «no description»");
             else
-                b.append(String.format(" descr'%s'", description));
+                b.append(String.format(" '%s'", description));
 
             if (date != null)
                 b.append(String.format("@%s", date.toString()));
@@ -1025,8 +1018,8 @@ public class NewTransactionModel extends ViewModel {
                 return false;
 
             return Objects.equals(date, other.date) &&
-                   TextUtils.equals(description, other.description) &&
-                   TextUtils.equals(comment, other.comment);
+                   Misc.equalStrings(description, other.description) &&
+                   Misc.equalStrings(comment, other.comment);
         }
     }
 
@@ -1039,11 +1032,11 @@ public class NewTransactionModel extends ViewModel {
         private boolean amountSet;
         private boolean amountValid = true;
         private FocusedElement focusedElement = FocusedElement.Account;
-        private boolean amountHintIsSet = true;
+        private boolean amountHintIsSet = false;
         private boolean isLast = false;
         private int accountNameCursorPosition;
         public TransactionAccount(TransactionAccount origin) {
-            id = origin.id;
+            super(origin.id);
             accountName = origin.accountName;
             amount = origin.amount;
             amountSet = origin.amountSet;
@@ -1159,22 +1152,25 @@ public class NewTransactionModel extends ViewModel {
             if (!TextUtils.isEmpty(comment))
                 b.append(String.format(" /%s/", comment));
 
+            if (isLast)
+                b.append(" last");
+
             return b.toString();
         }
         public boolean equalContents(TransactionAccount other) {
             if (other == null)
                 return false;
 
-            boolean equal = TextUtils.equals(accountName, other.accountName);
-            equal = equal && TextUtils.equals(comment, other.comment) &&
+            boolean equal = Misc.equalStrings(accountName, other.accountName);
+            equal = equal && Misc.equalStrings(comment, other.comment) &&
                     (amountSet ? other.amountSet && amount == other.amount : !other.amountSet);
 
             // compare amount hint only if there is no amount
             if (!amountSet)
                 equal = equal && (amountHintIsSet ? other.amountHintIsSet &&
-                                                    TextUtils.equals(amountHint, other.amountHint)
+                                                    Misc.equalStrings(amountHint, other.amountHint)
                                                   : !other.amountHintIsSet);
-            equal = equal && TextUtils.equals(currency, other.currency) && isLast == other.isLast;
+            equal = equal && Misc.equalStrings(currency, other.currency) && isLast == other.isLast;
 
             Logger.debug("new-trans",
                     String.format("Comparing {%s} and {%s}: %s", this.toString(), other.toString(),