]> git.ktnx.net Git - mobile-ledger.git/blobdiff - app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionModel.java
NewTransaction Item.setEditable: allow to be called for head row too
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / ui / activity / NewTransactionModel.java
index 0f46d8aeb4815672d7af952c333e273a51845f37..443c21f911ff310681c683a60fdd744e77a95c5f 100644 (file)
 
 package net.ktnx.mobileledger.ui.activity;
 
+import android.annotation.SuppressLint;
+
 import androidx.annotation.NonNull;
 import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Observer;
 import androidx.lifecycle.ViewModel;
 
 import net.ktnx.mobileledger.model.LedgerTransactionAccount;
+import net.ktnx.mobileledger.utils.Misc;
 
 import org.jetbrains.annotations.NotNull;
 
@@ -95,10 +99,12 @@ public class NewTransactionModel extends ViewModel {
     boolean accountsInInitialState() {
         for (Item item : items) {
             LedgerTransactionAccount acc = item.getAccount();
-            if (acc.isAmountSet()) return false;
+            if (acc.isAmountSet())
+                return false;
             if (!acc.getAccountName()
                     .trim()
-                    .isEmpty()) return false;
+                    .isEmpty())
+                return false;
         }
 
         return true;
@@ -111,8 +117,11 @@ public class NewTransactionModel extends ViewModel {
         if (index == 0) {
             return header;
         }
-        else if (index <= items.size()) return items.get(index - 1);
-        else return trailer;
+
+        if (index <= items.size())
+            return items.get(index - 1);
+
+        return trailer;
     }
     // rules:
     // 1) at least two account names
@@ -121,6 +130,7 @@ public class NewTransactionModel extends ViewModel {
     // 3a) there must be exactly one empty amount
     // 4) empty accounts with empty amounts are ignored
     // 5) a row with an empty account name or empty amount is guaranteed to exist
+    @SuppressLint("DefaultLocale")
     public void checkTransactionSubmittable(NewTransactionItemsAdapter adapter) {
         int accounts = 0;
         int accounts_with_values = 0;
@@ -141,27 +151,31 @@ public class NewTransactionModel extends ViewModel {
                 LedgerTransactionAccount acc = item.getAccount();
                 String acc_name = acc.getAccountName()
                                      .trim();
-                if (!acc_name.isEmpty()) {
+                if (acc_name.isEmpty()) {
+                    empty_rows++;
+                }
+                else {
                     accounts++;
 
                     if (acc.isAmountSet()) {
                         accounts_with_values++;
                     }
                 }
-                else empty_rows++;
 
-                if (!acc.isAmountSet()) {
+                if (acc.isAmountSet()) {
+                    amounts++;
+                    if (!acc_name.isEmpty())
+                        amounts_with_accounts++;
+                    running_total += acc.getAmount();
+                }
+                else {
                     if (empty_amount == null) {
                         empty_amount = item;
                         single_empty_amount = true;
                         single_empty_amount_has_account = !acc_name.isEmpty();
                     }
-                    else if (!acc_name.isEmpty()) single_empty_amount = false;
-                }
-                else {
-                    amounts++;
-                    if (!acc_name.isEmpty()) amounts_with_accounts++;
-                    running_total += acc.getAmount();
+                    else if (!acc_name.isEmpty())
+                        single_empty_amount = false;
                 }
             }
 
@@ -171,9 +185,27 @@ public class NewTransactionModel extends ViewModel {
                 adapter.addRow();
             }
 
-            if (single_empty_amount) {
-                empty_amount.setAmountHint(String.format(Locale.US, "%1.2f",
-                        (Math.abs(running_total) > 0.005) ? -running_total : 0f));
+            for (NewTransactionModel.Item item : items) {
+
+                final LedgerTransactionAccount acc = item.getAccount();
+                if (acc.isAmountSet())
+                    continue;
+
+                if (single_empty_amount) {
+                    if (item.equals(empty_amount)) {
+                        empty_amount.setAmountHint(Misc.isZero(running_total) ? null
+                                                                              : String.format(
+                                                                                      "%1.2f",
+                                                                                      -running_total));
+                        continue;
+                    }
+                }
+                else {
+                    // no single empty account and this account's amount is not set
+                    // => hint should be '0.00'
+                    item.setAmountHint(null);
+                }
+
             }
 
             debug("submittable", String.format(Locale.US,
@@ -206,10 +238,12 @@ public class NewTransactionModel extends ViewModel {
             isSubmittable.setValue(false);
         }
     }
-    public void removeItem(int pos, NewTransactionItemsAdapter adapter) {
+    public void removeItem(int pos) {
         items.remove(pos);
         accountCount.setValue(getAccountCount());
-        checkTransactionSubmittable(adapter);
+    }
+    public void sendCountNotifications() {
+        accountCount.setValue(getAccountCount());
     }
     enum ItemType {generalData, transactionRow, bottomFiller}
 
@@ -218,34 +252,40 @@ public class NewTransactionModel extends ViewModel {
         private MutableLiveData<Date> date = new MutableLiveData<>();
         private MutableLiveData<String> description = new MutableLiveData<>();
         private LedgerTransactionAccount account;
-        private MutableLiveData<String> amountHint = new MutableLiveData<>();
+        private MutableLiveData<String> amountHint = new MutableLiveData<>(null);
         private NewTransactionModel model;
-        private boolean editable = true;
+        private MutableLiveData<Boolean> editable = new MutableLiveData<>(true);
         public Item(NewTransactionModel model) {
             this.model = model;
             type = ItemType.bottomFiller;
+            editable.setValue(false);
         }
         public Item(NewTransactionModel model, Date date, String description) {
             this.model = model;
             this.type = ItemType.generalData;
             this.date.setValue(date);
             this.description.setValue(description);
+            this.editable.setValue(true);
         }
         public Item(NewTransactionModel model, LedgerTransactionAccount account) {
             this.model = model;
             this.type = ItemType.transactionRow;
             this.account = account;
+            this.editable.setValue(true);
         }
         public NewTransactionModel getModel() {
             return model;
         }
-        public boolean isEditable() {
-            ensureType(ItemType.transactionRow);
-            return editable;
-        }
         public void setEditable(boolean editable) {
-            ensureType(ItemType.transactionRow);
-            this.editable = editable;
+            ensureType(ItemType.generalData, ItemType.transactionRow);
+            this.editable.setValue(editable);
+        }
+        private void ensureType(ItemType type1, ItemType type2) {
+            if ((type != type1) && (type != type2)) {
+                throw new RuntimeException(
+                        String.format("Actual type (%s) differs from wanted (%s or %s)", type,
+                                type1, type2));
+            }
         }
         public String getAmountHint() {
             ensureType(ItemType.transactionRow);
@@ -253,6 +293,17 @@ public class NewTransactionModel extends ViewModel {
         }
         public void setAmountHint(String amountHint) {
             ensureType(ItemType.transactionRow);
+
+            // avoid unnecessary triggers
+            if (amountHint == null) {
+                if (this.amountHint.getValue() == null)
+                    return;
+            }
+            else {
+                if (amountHint.equals(this.amountHint.getValue()))
+                    return;
+            }
+
             this.amountHint.setValue(amountHint);
         }
         public void observeAmountHint(@NonNull @NotNull androidx.lifecycle.LifecycleOwner owner,
@@ -270,7 +321,7 @@ public class NewTransactionModel extends ViewModel {
         public void ensureType(ItemType wantedType) {
             if (type != wantedType) {
                 throw new RuntimeException(
-                        String.format("Actual type (%d) differs from wanted (%s)", type,
+                        String.format("Actual type (%s) differs from wanted (%s)", type,
                                 wantedType));
             }
         }
@@ -351,9 +402,11 @@ public class NewTransactionModel extends ViewModel {
          * @return nicely formatted, shortest available date representation
          */
         public String getFormattedDate() {
-            if (date == null) return null;
+            if (date == null)
+                return null;
             Date time = date.getValue();
-            if (time == null) return null;
+            if (time == null)
+                return null;
 
             Calendar c = GregorianCalendar.getInstance();
             c.setTime(time);
@@ -373,5 +426,12 @@ public class NewTransactionModel extends ViewModel {
 
             return String.valueOf(myDay);
         }
+        public void observeEditableFlag(NewTransactionActivity activity,
+                                        Observer<Boolean> observer) {
+            editable.observe(activity, observer);
+        }
+        public void stopObservingEditableFlag(Observer<Boolean> observer) {
+            editable.removeObserver(observer);
+        }
     }
 }