]> git.ktnx.net Git - mobile-ledger.git/blob - app/src/main/java/net/ktnx/mobileledger/ui/new_transaction/NewTransactionItemsAdapter.java
f8686dcfa72c4690320ebd962d4c19ca951e489a
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / ui / new_transaction / NewTransactionItemsAdapter.java
1 /*
2  * Copyright © 2021 Damyan Ivanov.
3  * This file is part of MoLe.
4  * MoLe is free software: you can distribute it and/or modify it
5  * under the term of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your opinion), any later version.
8  *
9  * MoLe is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License terms for details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with MoLe. If not, see <https://www.gnu.org/licenses/>.
16  */
17
18 package net.ktnx.mobileledger.ui.new_transaction;
19
20 import android.view.LayoutInflater;
21 import android.view.ViewGroup;
22
23 import androidx.annotation.NonNull;
24 import androidx.recyclerview.widget.AsyncListDiffer;
25 import androidx.recyclerview.widget.DiffUtil;
26 import androidx.recyclerview.widget.ItemTouchHelper;
27 import androidx.recyclerview.widget.RecyclerView;
28
29 import net.ktnx.mobileledger.databinding.NewTransactionRowBinding;
30 import net.ktnx.mobileledger.model.MobileLedgerProfile;
31 import net.ktnx.mobileledger.utils.Logger;
32
33 import java.util.List;
34 import java.util.Locale;
35 import java.util.Objects;
36
37 class NewTransactionItemsAdapter extends RecyclerView.Adapter<NewTransactionItemHolder> {
38     final NewTransactionModel model;
39     private final ItemTouchHelper touchHelper;
40     private final AsyncListDiffer<NewTransactionModel.Item> differ =
41             new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<NewTransactionModel.Item>() {
42                 @Override
43                 public boolean areItemsTheSame(@NonNull NewTransactionModel.Item oldItem,
44                                                @NonNull NewTransactionModel.Item newItem) {
45 //                    Logger.debug("new-trans",
46 //                            String.format("comparing ids of {%s} and {%s}", oldItem.toString(),
47 //                                    newItem.toString()));
48                     return oldItem.getId() == newItem.getId();
49                 }
50                 @Override
51                 public boolean areContentsTheSame(@NonNull NewTransactionModel.Item oldItem,
52                                                   @NonNull NewTransactionModel.Item newItem) {
53
54 //                    Logger.debug("new-trans",
55 //                            String.format("comparing contents of {%s} and {%s}", oldItem.toString(),
56 //                                    newItem.toString()));
57                     return oldItem.equalContents(newItem);
58                 }
59             });
60     private MobileLedgerProfile mProfile;
61     private int checkHoldCounter = 0;
62     NewTransactionItemsAdapter(NewTransactionModel viewModel, MobileLedgerProfile profile) {
63         super();
64         setHasStableIds(true);
65         model = viewModel;
66         mProfile = profile;
67
68
69         NewTransactionItemsAdapter adapter = this;
70
71         touchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
72             @Override
73             public boolean isLongPressDragEnabled() {
74                 return true;
75             }
76             @Override
77             public boolean canDropOver(@NonNull RecyclerView recyclerView,
78                                        @NonNull RecyclerView.ViewHolder current,
79                                        @NonNull RecyclerView.ViewHolder target) {
80                 final int adapterPosition = target.getAdapterPosition();
81
82                 // first and last items are immovable
83                 if (adapterPosition == 0)
84                     return false;
85                 if (adapterPosition == adapter.getItemCount() - 1)
86                     return false;
87
88                 return super.canDropOver(recyclerView, current, target);
89             }
90             @Override
91             public int getMovementFlags(@NonNull RecyclerView recyclerView,
92                                         @NonNull RecyclerView.ViewHolder viewHolder) {
93                 int flags = makeFlag(ItemTouchHelper.ACTION_STATE_IDLE, ItemTouchHelper.END);
94                 // the top (date and description) and the bottom (padding) items are always there
95                 final int adapterPosition = viewHolder.getAdapterPosition();
96                 if ((adapterPosition > 0) && (adapterPosition < adapter.getItemCount() - 1)) {
97                     flags |= makeFlag(ItemTouchHelper.ACTION_STATE_DRAG,
98                             ItemTouchHelper.UP | ItemTouchHelper.DOWN) |
99                              makeFlag(ItemTouchHelper.ACTION_STATE_SWIPE,
100                                      ItemTouchHelper.START | ItemTouchHelper.END);
101                 }
102
103                 return flags;
104             }
105             @Override
106             public boolean onMove(@NonNull RecyclerView recyclerView,
107                                   @NonNull RecyclerView.ViewHolder viewHolder,
108                                   @NonNull RecyclerView.ViewHolder target) {
109
110                 model.moveItem(viewHolder.getAdapterPosition(), target.getAdapterPosition());
111                 return true;
112             }
113             @Override
114             public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
115                 int pos = viewHolder.getAdapterPosition();
116                 viewModel.removeItem(pos);
117             }
118         });
119     }
120     @Override
121     public long getItemId(int position) {
122         return differ.getCurrentList()
123                      .get(position)
124                      .getId();
125     }
126     public void setProfile(MobileLedgerProfile profile) {
127         mProfile = profile;
128     }
129     @NonNull
130     @Override
131     public NewTransactionItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
132         NewTransactionRowBinding b =
133                 NewTransactionRowBinding.inflate(LayoutInflater.from(parent.getContext()), parent,
134                         false);
135
136         return new NewTransactionItemHolder(b, this);
137     }
138     @Override
139     public void onBindViewHolder(@NonNull NewTransactionItemHolder holder, int position) {
140         Logger.debug("bind", String.format(Locale.US, "Binding item at position %d", position));
141         NewTransactionModel.Item item = Objects.requireNonNull(differ.getCurrentList()
142                                                                      .get(position));
143         holder.bind(item);
144         Logger.debug("bind", String.format(Locale.US, "Bound %s item at position %d", item.getType()
145                                                                                           .toString(),
146                 position));
147     }
148     @Override
149     public int getItemCount() {
150         return differ.getCurrentList()
151                      .size();
152     }
153     @Override
154     public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
155         super.onAttachedToRecyclerView(recyclerView);
156         touchHelper.attachToRecyclerView(recyclerView);
157     }
158     @Override
159     public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
160         touchHelper.attachToRecyclerView(null);
161         super.onDetachedFromRecyclerView(recyclerView);
162     }
163     void noteFocusIsOnAccount(int position) {
164         model.noteFocusChanged(position, FocusedElement.Account);
165     }
166     void noteFocusIsOnAmount(int position) {
167         model.noteFocusChanged(position, FocusedElement.Amount);
168     }
169     void noteFocusIsOnComment(int position) {
170         model.noteFocusChanged(position, FocusedElement.Comment);
171     }
172     void noteFocusIsOnTransactionComment(int position) {
173         model.noteFocusChanged(position, FocusedElement.TransactionComment);
174     }
175     public void noteFocusIsOnDescription(int pos) {
176         model.noteFocusChanged(pos, FocusedElement.Description);
177     }
178     private void holdSubmittableChecks() {
179         checkHoldCounter++;
180     }
181     private void releaseSubmittableChecks() {
182         if (checkHoldCounter == 0)
183             throw new RuntimeException("Asymmetrical call to releaseSubmittableChecks");
184         checkHoldCounter--;
185     }
186     void setItemCurrency(int position, String newCurrency) {
187         model.setItemCurrency(position, newCurrency);
188     }
189
190     public void setItems(List<NewTransactionModel.Item> newList) {
191         Logger.debug("new-trans", "adapter: submitting new item list");
192         differ.submitList(newList);
193     }
194 }