import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import net.ktnx.mobileledger.R;
class TemplateDetailsAdapter extends RecyclerView.Adapter<TemplateDetailsAdapter.ViewHolder> {
private static final String D_TEMPLATE_UI = "template-ui";
private final AsyncListDiffer<TemplateDetailsItem> differ;
- public TemplateDetailsAdapter() {
+ private final TemplateDetailsViewModel mModel;
+ private final ItemTouchHelper itemTouchHelper;
+ public TemplateDetailsAdapter(TemplateDetailsViewModel model) {
super();
+ mModel = model;
setHasStableIds(true);
differ = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<TemplateDetailsItem>() {
@Override
}
}
});
+ itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
+ @Override
+ public float getMoveThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
+ return 0.1f;
+ }
+ @Override
+ public boolean isLongPressDragEnabled() {
+ return false;
+ }
+ @Override
+ public RecyclerView.ViewHolder chooseDropTarget(
+ @NonNull RecyclerView.ViewHolder selected,
+ @NonNull List<RecyclerView.ViewHolder> dropTargets, int curX, int curY) {
+ RecyclerView.ViewHolder best = null;
+ int bestDistance = 0;
+ for (RecyclerView.ViewHolder v : dropTargets) {
+ if (v == selected)
+ continue;
+
+ final int viewTop = v.itemView.getTop();
+ int distance = Math.abs(viewTop - curY);
+ if (best == null) {
+ best = v;
+ bestDistance = distance;
+ }
+ else {
+ if (distance < bestDistance) {
+ bestDistance = distance;
+ best = v;
+ }
+ }
+ }
+
+ Logger.debug("dnd", "Best target is " + best);
+ return best;
+ }
+ @Override
+ public boolean canDropOver(@NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder current,
+ @NonNull RecyclerView.ViewHolder target) {
+ final int adapterPosition = target.getAdapterPosition();
+
+ // first item is immovable
+ if (adapterPosition == 0)
+ return false;
+
+ return super.canDropOver(recyclerView, current, target);
+ }
+ @Override
+ public int getMovementFlags(@NonNull RecyclerView recyclerView,
+ @NonNull RecyclerView.ViewHolder viewHolder) {
+ int flags = 0;
+ // the top item (transaction params) is always there
+ final int adapterPosition = viewHolder.getAdapterPosition();
+ if (adapterPosition > 0)
+ 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) {
+
+ final int fromPosition = viewHolder.getAdapterPosition();
+ final int toPosition = target.getAdapterPosition();
+ mModel.moveItem(fromPosition, toPosition);
+
+ return true;
+ }
+ @Override
+ public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
+ int pos = viewHolder.getAdapterPosition();
+ mModel.removeItem(pos);
+ }
+ });
+ }
+ @Override
+ public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
+ super.onAttachedToRecyclerView(recyclerView);
+
+ itemTouchHelper.attachToRecyclerView(recyclerView);
+ }
+ @Override
+ public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
+ super.onDetachedFromRecyclerView(recyclerView);
+
+ itemTouchHelper.attachToRecyclerView(null);
}
@Override
public long getItemId(int position) {
String.format(Locale.US, groupNoText, header.getDateMonthMatchGroup(),
getMatchGroupText(header.getDateMonthMatchGroup())));
}
- b.templateDetailsMonthSourceLabel.setOnClickListener(v -> selectHeaderDetailSource(v,
- HeaderDetail.DATE_MONTH));
- b.templateDetailsMonthSource.setOnClickListener(v -> selectHeaderDetailSource(v,
- HeaderDetail.DATE_MONTH));
+ b.templateDetailsMonthSourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_MONTH));
+ b.templateDetailsMonthSource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_MONTH));
if (header.hasLiteralDateDay()) {
b.templateDetailsDaySource.setText(R.string.template_details_source_literal);
final Integer dateDay = header.getDateDay();
- b.templateDetailsDateDay.setText((dateDay == null) ? null : String.valueOf(dateDay));
+ b.templateDetailsDateDay.setText(
+ (dateDay == null) ? null : String.valueOf(dateDay));
b.templateDetailsDateDayLayout.setVisibility(View.VISIBLE);
}
else {
String.format(Locale.US, groupNoText, header.getDateDayMatchGroup(),
getMatchGroupText(header.getDateDayMatchGroup())));
}
- b.templateDetailsDaySourceLabel.setOnClickListener(v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
- b.templateDetailsDaySource.setOnClickListener(v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
+ b.templateDetailsDaySourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
+ b.templateDetailsDaySource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
if (header.hasLiteralTransactionDescription()) {
- b.templateTransactionDescriptionSource.setText(R.string.template_details_source_literal);
+ b.templateTransactionDescriptionSource.setText(
+ R.string.template_details_source_literal);
b.transactionDescription.setText(header.getTransactionDescription());
b.transactionDescriptionLayout.setVisibility(View.VISIBLE);
}
getMatchGroupText(header.getTransactionDescriptionMatchGroup())));
}
- b.templateTransactionDescriptionSourceLabel.setOnClickListener(v -> selectHeaderDetailSource(v, HeaderDetail.DESCRIPTION));
- b.templateTransactionDescriptionSource.setOnClickListener(v -> selectHeaderDetailSource(v, HeaderDetail.DESCRIPTION));
+ b.templateTransactionDescriptionSourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DESCRIPTION));
+ b.templateTransactionDescriptionSource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DESCRIPTION));
if (header.hasLiteralTransactionComment()) {
- b.templateTransactionCommentSource.setText(R.string.template_details_source_literal);
+ b.templateTransactionCommentSource.setText(
+ R.string.template_details_source_literal);
b.transactionComment.setText(header.getTransactionComment());
b.transactionCommentLayout.setVisibility(View.VISIBLE);
}
b.templateDetailsAccountAmount.setText(Data.formatNumber(amt));
});
- b.negateAmountSwitch.setOnCheckedChangeListener(
- (buttonView, isChecked) -> getItem().setNegateAmount(isChecked));
+ b.negateAmountSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ getItem().setNegateAmount(isChecked);
+ b.templateDetailsNegateAmountText.setText(
+ isChecked ? R.string.template_account_change_amount_sign
+ : R.string.template_account_keep_amount_sign);
+ });
+ final View.OnClickListener negLabelClickListener =
+ (view) -> b.negateAmountSwitch.toggle();
+ b.templateDetailsNegateAmountLabel.setOnClickListener(negLabelClickListener);
+ b.templateDetailsNegateAmountText.setOnClickListener(negLabelClickListener);
+ b.patternAccountLabel.setOnTouchListener((v, event) -> {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ itemTouchHelper.startDrag(this);
+ }
+ return false;
+ });
}
@Override
void bind(TemplateDetailsItem item) {
b.templateDetailsAccountAmount.setText((amt == null) ? null : String.format(
Data.locale.getValue(), "%,4.2f", (accRow.getAmount())));
b.negateAmountSwitch.setVisibility(View.GONE);
+ b.templateDetailsNegateAmountLabel.setVisibility(View.GONE);
+ b.templateDetailsNegateAmountText.setVisibility(View.GONE);
}
else {
b.templateDetailsAccountAmountSource.setText(
b.templateDetailsAccountAmountLayout.setVisibility(View.GONE);
b.negateAmountSwitch.setVisibility(View.VISIBLE);
b.negateAmountSwitch.setChecked(accRow.isNegateAmount());
+ b.templateDetailsNegateAmountText.setText(
+ accRow.isNegateAmount() ? R.string.template_account_change_amount_sign
+ : R.string.template_account_keep_amount_sign);
+ b.templateDetailsNegateAmountLabel.setVisibility(View.VISIBLE);
+ b.templateDetailsNegateAmountText.setVisibility(View.VISIBLE);
}
b.templateAccountNameSourceLabel.setOnClickListener(