]> git.ktnx.net Git - mobile-ledger.git/blob - app/src/main/java/net/ktnx/mobileledger/ui/account_summary/AccountSummaryAdapter.java
c0ed9bd7a4f3421c28b7df2bfb86323d03e9f26a
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / ui / account_summary / AccountSummaryAdapter.java
1 /*
2  * Copyright © 2020 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.account_summary;
19
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.text.TextUtils;
23 import android.util.Log;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.widget.ImageView;
28 import android.widget.TextView;
29
30 import androidx.annotation.NonNull;
31 import androidx.appcompat.app.AlertDialog;
32 import androidx.constraintlayout.widget.ConstraintLayout;
33 import androidx.recyclerview.widget.AsyncListDiffer;
34 import androidx.recyclerview.widget.DiffUtil;
35 import androidx.recyclerview.widget.RecyclerView;
36
37 import net.ktnx.mobileledger.R;
38 import net.ktnx.mobileledger.async.DbOpQueue;
39 import net.ktnx.mobileledger.model.LedgerAccount;
40 import net.ktnx.mobileledger.model.MobileLedgerProfile;
41 import net.ktnx.mobileledger.ui.activity.MainActivity;
42
43 import org.jetbrains.annotations.NotNull;
44
45 import java.util.ArrayList;
46
47 import static net.ktnx.mobileledger.utils.Logger.debug;
48
49 public class AccountSummaryAdapter
50         extends RecyclerView.Adapter<AccountSummaryAdapter.LedgerRowHolder> {
51     public static final int AMOUNT_LIMIT = 3;
52     private MobileLedgerProfile profile;
53     private AsyncListDiffer<LedgerAccount> listDiffer;
54     AccountSummaryAdapter() {
55         listDiffer = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<LedgerAccount>() {
56             @Override
57             public boolean areItemsTheSame(@NotNull LedgerAccount oldItem,
58                                            @NotNull LedgerAccount newItem) {
59                 return TextUtils.equals(oldItem.getName(), newItem.getName());
60             }
61             @Override
62             public boolean areContentsTheSame(@NotNull LedgerAccount oldItem,
63                                               @NotNull LedgerAccount newItem) {
64                 return (oldItem.isExpanded() == newItem.isExpanded()) &&
65                        (oldItem.amountsExpanded() == newItem.amountsExpanded() &&
66                         TextUtils.equals(oldItem.getAmountsString(), newItem.getAmountsString()));
67             }
68         });
69     }
70
71     public void onBindViewHolder(@NonNull LedgerRowHolder holder, int position) {
72         holder.bindToAccount(listDiffer.getCurrentList()
73                                        .get(position));
74     }
75
76     @NonNull
77     @Override
78     public LedgerRowHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
79         View row = LayoutInflater.from(parent.getContext())
80                                  .inflate(R.layout.account_summary_row, parent, false);
81         return new LedgerRowHolder(row);
82     }
83
84     @Override
85     public int getItemCount() {
86         return listDiffer.getCurrentList()
87                          .size();
88     }
89     public void setAccounts(MobileLedgerProfile profile, ArrayList<LedgerAccount> newList) {
90         this.profile = profile;
91         listDiffer.submitList(newList);
92     }
93     class LedgerRowHolder extends RecyclerView.ViewHolder {
94         TextView tvAccountName, tvAccountAmounts;
95         ConstraintLayout row;
96         View expanderContainer;
97         ImageView expander;
98         View accountExpanderContainer;
99         public LedgerRowHolder(@NonNull View itemView) {
100             super(itemView);
101             row = itemView.findViewById(R.id.account_summary_row);
102             tvAccountName = itemView.findViewById(R.id.account_row_acc_name);
103             tvAccountAmounts = itemView.findViewById(R.id.account_row_acc_amounts);
104             expanderContainer = itemView.findViewById(R.id.account_expander_container);
105             expander = itemView.findViewById(R.id.account_expander);
106             accountExpanderContainer =
107                     itemView.findViewById(R.id.account_row_amounts_expander_container);
108
109             itemView.setOnLongClickListener(this::onItemLongClick);
110             tvAccountName.setOnLongClickListener(this::onItemLongClick);
111             tvAccountAmounts.setOnLongClickListener(this::onItemLongClick);
112             expanderContainer.setOnLongClickListener(this::onItemLongClick);
113             expander.setOnLongClickListener(this::onItemLongClick);
114             row.setOnLongClickListener(this::onItemLongClick);
115
116             tvAccountName.setOnClickListener(v -> toggleAccountExpanded());
117             expanderContainer.setOnClickListener(v -> toggleAccountExpanded());
118             expander.setOnClickListener(v -> toggleAccountExpanded());
119             tvAccountAmounts.setOnClickListener(v -> toggleAmountsExpanded());
120         }
121         private @NonNull
122         LedgerAccount getAccount() {
123             final ArrayList<LedgerAccount> accountList = profile.getAccounts()
124                                                                 .getValue();
125             if (accountList == null)
126                 throw new IllegalStateException("No account list");
127
128             return accountList.get(getAdapterPosition());
129         }
130         private void toggleAccountExpanded() {
131             LedgerAccount acc = getAccount();
132             if (!acc.hasSubAccounts())
133                 return;
134             debug("accounts", "Account expander clicked");
135
136             acc.toggleExpanded();
137             expanderContainer.animate()
138                              .rotation(acc.isExpanded() ? 0 : 180);
139
140             MobileLedgerProfile profile = acc.getProfile();
141             if (profile == null)
142                 return;
143
144             DbOpQueue.add("update accounts set expanded=? where name=? and profile=?",
145                     new Object[]{acc.isExpanded(), acc.getName(), profile.getUuid()
146                     }, profile::scheduleAccountListReload);
147
148         }
149         private void toggleAmountsExpanded() {
150             LedgerAccount acc = getAccount();
151             if (acc.getAmountCount() <= AMOUNT_LIMIT)
152                 return;
153
154             acc.toggleAmountsExpanded();
155             if (acc.amountsExpanded()) {
156                 tvAccountAmounts.setText(acc.getAmountsString());
157                 accountExpanderContainer.setVisibility(View.GONE);
158             }
159             else {
160                 tvAccountAmounts.setText(acc.getAmountsString(AMOUNT_LIMIT));
161                 accountExpanderContainer.setVisibility(View.VISIBLE);
162             }
163
164             MobileLedgerProfile profile = acc.getProfile();
165             if (profile == null)
166                 return;
167
168             DbOpQueue.add("update accounts set amounts_expanded=? where name=? and profile=?",
169                     new Object[]{acc.amountsExpanded(), acc.getName(), profile.getUuid()
170                     });
171
172         }
173         private boolean onItemLongClick(View v) {
174             MainActivity activity = (MainActivity) v.getContext();
175             AlertDialog.Builder builder = new AlertDialog.Builder(activity);
176             View row;
177             int id = v.getId();
178             switch (id) {
179                 case R.id.account_summary_row:
180                     row = v;
181                     break;
182                 case R.id.account_row_acc_amounts:
183                 case R.id.account_row_amounts_expander_container:
184                     row = (View) v.getParent();
185                     break;
186                 case R.id.account_row_acc_name:
187                 case R.id.account_expander_container:
188                     row = (View) v.getParent()
189                                   .getParent();
190                     break;
191                 case R.id.account_expander:
192                     row = (View) v.getParent()
193                                   .getParent()
194                                   .getParent();
195                     break;
196                 default:
197                     Log.e("error",
198                             String.format("Don't know how to handle long click on id %d", id));
199                     return false;
200             }
201             LedgerAccount acc = getAccount();
202             builder.setTitle(acc.getName());
203             builder.setItems(R.array.acc_ctx_menu, (dialog, which) -> {
204                 switch (which) {
205                     case 0:
206                         // show transactions
207                         activity.showAccountTransactions(acc.getName());
208                         break;
209                 }
210                 dialog.dismiss();
211             });
212             builder.show();
213             return true;
214         }
215         public void bindToAccount(LedgerAccount acc) {
216             Context ctx = row.getContext();
217             Resources rm = ctx.getResources();
218
219             row.setTag(acc);
220
221             tvAccountName.setText(acc.getShortName());
222
223             ConstraintLayout.LayoutParams lp =
224                     (ConstraintLayout.LayoutParams) tvAccountName.getLayoutParams();
225             lp.setMarginStart(
226                     acc.getLevel() * rm.getDimensionPixelSize(R.dimen.thumb_row_height) / 3);
227
228             if (acc.hasSubAccounts()) {
229                 expanderContainer.setVisibility(View.VISIBLE);
230                 expanderContainer.setRotation(acc.isExpanded() ? 0 : 180);
231             }
232             else {
233                 expanderContainer.setVisibility(View.GONE);
234             }
235
236             int amounts = acc.getAmountCount();
237             if ((amounts > AMOUNT_LIMIT) && !acc.amountsExpanded()) {
238                 tvAccountAmounts.setText(acc.getAmountsString(AMOUNT_LIMIT));
239                 accountExpanderContainer.setVisibility(View.VISIBLE);
240             }
241             else {
242                 tvAccountAmounts.setText(acc.getAmountsString());
243                 accountExpanderContainer.setVisibility(View.GONE);
244             }
245         }
246     }
247 }