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;
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;
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
// 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;
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;
}
}
adapter.addRow();
}
- if (single_empty_amount) {
- empty_amount.setAmountHint(String.format(Locale.US, "%1.2f",
- Misc.isZero(running_total) ? 0f : -running_total));
+ 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,
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}
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);
}
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,
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));
}
}
* @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);
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);
+ }
}
}