]> git.ktnx.net Git - mobile-ledger.git/blobdiff - app/src/main/java/net/ktnx/mobileledger/ui/activity/NewTransactionItemsAdapter.java
NT: correctly disable swiping of top and bottom entries, let all the rest be swiped
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / ui / activity / NewTransactionItemsAdapter.java
index 452e348efb308afec5984f7e5bbd7d189aa02d0b..5f2f4c6c4fa653b0a610a0187535a269a8387da1 100644 (file)
@@ -23,6 +23,7 @@ import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
 import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.ItemTouchHelper;
 import androidx.recyclerview.widget.RecyclerView;
 
 import net.ktnx.mobileledger.App;
@@ -43,6 +44,8 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
         implements DescriptionSelectedCallback {
     NewTransactionModel model;
     private MobileLedgerProfile mProfile;
+    private ItemTouchHelper touchHelper;
+    private RecyclerView recyclerView;
     NewTransactionItemsAdapter(NewTransactionModel viewModel, MobileLedgerProfile profile) {
         super();
         model = viewModel;
@@ -53,6 +56,61 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
                     String.format(Locale.US, "%d accounts is too little, Calling addRow()", size));
             size = addRow();
         }
+
+        NewTransactionItemsAdapter adapter = this;
+
+        touchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
+            @Override
+            public boolean isLongPressDragEnabled() {
+                return true;
+            }
+            @Override
+            public boolean canDropOver(@NonNull RecyclerView recyclerView,
+                                       @NonNull RecyclerView.ViewHolder current,
+                                       @NonNull RecyclerView.ViewHolder target) {
+                final int adapterPosition = target.getAdapterPosition();
+
+                // first and last items are immovable
+                if (adapterPosition == 0)
+                    return false;
+                if (adapterPosition == adapter.getItemCount() - 1)
+                    return false;
+
+                return super.canDropOver(recyclerView, current, target);
+            }
+            @Override
+            public int getMovementFlags(@NonNull RecyclerView recyclerView,
+                                        @NonNull RecyclerView.ViewHolder viewHolder) {
+                int flags = makeFlag(ItemTouchHelper.ACTION_STATE_IDLE, ItemTouchHelper.END);
+                // the top (date and description) and the bottom (padding) items are always there
+                final int adapterPosition = viewHolder.getAdapterPosition();
+                if ((adapterPosition > 0) && (adapterPosition < adapter.getItemCount() - 1)) {
+                    flags |= makeFlag(ItemTouchHelper.ACTION_STATE_DRAG,
+                            ItemTouchHelper.UP | ItemTouchHelper.DOWN) |
+                             makeFlag(ItemTouchHelper.ACTION_STATE_SWIPE,
+                                     ItemTouchHelper.START | ItemTouchHelper.END);
+                }
+
+                return flags;
+            }
+            @Override
+            public boolean onMove(@NonNull RecyclerView recyclerView,
+                                  @NonNull RecyclerView.ViewHolder viewHolder,
+                                  @NonNull RecyclerView.ViewHolder target) {
+
+                model.swapItems(viewHolder.getAdapterPosition(), target.getAdapterPosition());
+                notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
+                return true;
+            }
+            @Override
+            public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
+                int pos = viewHolder.getAdapterPosition();
+                viewModel.removeItem(pos - 1);
+                notifyItemRemoved(pos);
+                viewModel.sendCountNotifications(); // needed after items re-arrangement
+                viewModel.checkTransactionSubmittable(adapter);
+            }
+        });
     }
     public void setProfile(MobileLedgerProfile profile) {
         mProfile = profile;
@@ -72,6 +130,7 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
         LinearLayout row = (LinearLayout) LayoutInflater.from(parent.getContext())
                                                         .inflate(R.layout.new_transaction_row,
                                                                 parent, false);
+
         return new NewTransactionItemHolder(row, this);
     }
     @Override
@@ -99,6 +158,18 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
 
         return true;
     }
+    @Override
+    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
+        super.onAttachedToRecyclerView(recyclerView);
+        this.recyclerView = recyclerView;
+        touchHelper.attachToRecyclerView(recyclerView);
+    }
+    @Override
+    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
+        touchHelper.attachToRecyclerView(null);
+        super.onDetachedFromRecyclerView(recyclerView);
+        this.recyclerView = null;
+    }
     public void descriptionSelected(String description) {
         debug("descr selected", description);
         if (!accountListIsEmpty())
@@ -145,7 +216,9 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
             tr = profile.loadTransaction(transactionId);
             ArrayList<LedgerTransactionAccount> accounts = tr.getAccounts();
             NewTransactionModel.Item firstNegative = null;
-            boolean singleNegative = false;
+            NewTransactionModel.Item firstPositive = null;
+            int singleNegativeIndex = -1;
+            int singlePositiveIndex = -1;
             int negativeCount = 0;
             for (int i = 0; i < accounts.size(); i++) {
                 LedgerTransactionAccount acc = accounts.get(i);
@@ -164,10 +237,18 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
                     if (acc.getAmount() < 0) {
                         if (firstNegative == null) {
                             firstNegative = item;
-                            singleNegative = true;
+                            singleNegativeIndex = i;
+                        }
+                        else
+                            singleNegativeIndex = -1;
+                    }
+                    else {
+                        if (firstPositive == null) {
+                            firstPositive = item;
+                            singlePositiveIndex = i;
                         }
                         else
-                            singleNegative = false;
+                            singlePositiveIndex = -1;
                     }
                 }
                 else
@@ -176,9 +257,15 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
                 notifyItemChanged(i + 1);
             }
 
-            if (singleNegative) {
+            if (singleNegativeIndex != -1) {
                 firstNegative.getAccount()
                              .resetAmount();
+                model.moveItemLast(singleNegativeIndex);
+            }
+            else if (singlePositiveIndex != -1) {
+                firstPositive.getAccount()
+                             .resetAmount();
+                model.moveItemLast(singlePositiveIndex);
             }
         }
         model.checkTransactionSubmittable(this);
@@ -204,4 +291,16 @@ class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItem
     public void updateFocusedItem(int position) {
         model.updateFocusedItem(position);
     }
+    public void noteFocusIsOnAccount(int position) {
+        model.noteFocusChanged(position, NewTransactionModel.FocusedElement.Account);
+    }
+    public void noteFocusIsOnAmount(int position) {
+        model.noteFocusChanged(position, NewTransactionModel.FocusedElement.Amount);
+    }
+    public void noteFocusIsOnComment(int position) {
+        model.noteFocusChanged(position, NewTransactionModel.FocusedElement.Comment);
+    }
+    public void toggleComment(int position) {
+        model.toggleComment(position);
+    }
 }