/*
* Copyright 2015 Lafayette College
*
* This file is part of OpenCVTour.
*
* OpenCVTour is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenCVTour is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenCVTour. If not, see <http://www.gnu.org/licenses/>.
*/
package alicrow.opencvtour;
import android.app.Activity;
import android.content.Intent;
import android.app.Fragment;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.eyeem.recyclerviewtools.adapter.WrapAdapter;
import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.decoration.ItemShadowDecorator;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableItemViewHolder;
import java.util.ArrayList;
import java.util.List;
/**
* Fragment to display the list of TourItems in a Tour.
*/
public class TourItemListFragment extends Fragment implements View.OnClickListener, com.eyeem.recyclerviewtools.adapter.OnItemClickListenerDetector.OnItemClickListener {
private static final String TAG = "TourItemListFragment";
private Tour _tour;
private TourItemAdapter _adapter;
/**
* Adapter to display TourItems in our list
*/
public class TourItemAdapter extends RecyclerView.Adapter<TourItemAdapter.ViewHolder> implements DraggableItemAdapter<TourItemAdapter.ViewHolder>
{
private final List<TourItem> _items;
final int INVALID_ID = -1;
public class ViewHolder extends AbstractDraggableItemViewHolder implements View.OnClickListener {
public final TextView _name;
public final TextView _description;
public final ImageView _thumbnail;
public final RelativeLayout _container;
public ViewHolder(RelativeLayout v) {
super(v);
_name = (TextView) v.findViewById(R.id.tour_item_name);
_description = (TextView) v.findViewById(R.id.tour_item_description);
_thumbnail = (ImageView) v.findViewById(R.id.tour_item_thumbnail);
_container = (RelativeLayout) v.findViewById(R.id.container);
v.findViewById(R.id.delete_tour_item).setOnClickListener(this);
}
@Override
public void onClick(View view) {
int position = getAdapterPosition();
switch(view.getId()) {
case R.id.delete_tour_item:
if (position != RecyclerView.NO_POSITION) {
_adapter.getList().remove(position);
_adapter.notifyDataSetChanged();
}
break;
}
}
}
public TourItemAdapter(List<TourItem> items) {
_items = items;
setHasStableIds(true);
}
@Override
public void onMoveItem(int fromPosition, int toPosition) {
Log.d(TAG, "onMoveItem(fromPosition = " + fromPosition + ", toPosition = " + toPosition + ")");
if (fromPosition == toPosition)
return;
TourItem removed = _items.remove(fromPosition);
_items.add(toPosition, removed);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public boolean onCheckCanStartDrag(ViewHolder holder, int position, int x, int y) {
return true;
}
@Override
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder, int position) {
// no drag-sortable range specified
return null;
}
// Create new views (invoked by the layout manager)
@Override
public TourItemAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.tour_item_line, parent, false);
// set the view's size, margins, paddings and layout parameters
return new ViewHolder((RelativeLayout) v);
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
TourItem item = _items.get(position);
holder._name.setText(item.getName());
holder._description.setText(item.getDescription());
if(item.getDescription().equals(""))
holder._description.setVisibility(View.GONE);
else
holder._description.setVisibility(View.VISIBLE);
if(item.hasMainImage()) {
String image_filepath = item.getMainImageFilepath();
ImageView image_view = holder._thumbnail;
Utilities.loadBitmap(image_view, image_filepath, Utilities.dp_to_px(40), Utilities.dp_to_px(40), getActivity());
} else
holder._thumbnail.setImageResource(R.drawable.default_thumbnail);
// set background resource (target view ID: container)
final int dragState = holder.getDragStateFlags();
if (((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_UPDATED) != 0)) {
int bgResId;
if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_IS_ACTIVE) != 0) {
bgResId = R.drawable.bg_item_dragging_active_state;
} else if ((dragState & RecyclerViewDragDropManager.STATE_FLAG_DRAGGING) != 0) {
bgResId = R.drawable.bg_item_dragging_state;
} else {
bgResId = R.drawable.bg_item_normal_state;
}
holder._container.setBackgroundResource(bgResId);
}
}
@Override
public int getItemCount() {
return _items.size();
}
@Override
public long getItemId(int position) {
if (position < 0 || position >= _items.size()) {
return INVALID_ID;
}
return _items.get(position).getId();
}
public List<TourItem> getList() {
return _items;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_tour_item_list, container, false);
v.findViewById(R.id.fab).setOnClickListener(this);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
_tour = Tour.getCurrentTour();
RecyclerView recycler_view = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
recycler_view.setLayoutManager(new LinearLayoutManager(getActivity()));
ArrayList<TourItem> tour_items = _tour.getTourItems();
_adapter = new TourItemAdapter(tour_items);
/// We're using two different RecyclerView adapter libraries, which were not designed to work together. CrazyWrapAdapter provides a WrapAdapter from eyeem's library that also implements DraggableItemAdapter from h6ah4i's library (by passing to the TourItemAdapter that actually handles that stuff).
class CrazyWrapAdapter extends WrapAdapter implements DraggableItemAdapter<TourItemAdapter.ViewHolder> {
public CrazyWrapAdapter(RecyclerView.Adapter wrappedAdapter) {
super(wrappedAdapter);
}
@Override public void onMoveItem(int fromPosition, int toPosition) {
((DraggableItemAdapter) wrapped).onMoveItem(fromPosition, toPosition);
}
@Override public boolean onCheckCanStartDrag(TourItemAdapter.ViewHolder holder, int position, int x, int y) {
return ((DraggableItemAdapter) wrapped).onCheckCanStartDrag(holder, position, x, y);
}
@Override public ItemDraggableRange onGetItemDraggableRange(TourItemAdapter.ViewHolder holder, int position) {
return ((DraggableItemAdapter) wrapped).onGetItemDraggableRange(holder, position);
}
}
CrazyWrapAdapter wrap_adapter = new CrazyWrapAdapter(_adapter);
wrap_adapter.setOnItemClickListener(recycler_view, this);
wrap_adapter.addFooter(getActivity().getLayoutInflater().inflate(R.layout.empty_list_footer, recycler_view, false));
/// Stuff for drag and drop functionality:
RecyclerViewDragDropManager drag_drop_manager = new RecyclerViewDragDropManager();
drag_drop_manager.setInitiateOnLongPress(true);
//noinspection deprecation
drag_drop_manager.setDraggingItemShadowDrawable((NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z3));
RecyclerView.Adapter drag_drop_adapter = drag_drop_manager.createWrappedAdapter(wrap_adapter); // wrap for dragging
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
recycler_view.setAdapter(drag_drop_adapter); // requires *wrapped* adapter
recycler_view.setItemAnimator(animator);
// Shadow for pre-Lollipop devices (Lollipop has built-in elevation stuff)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
//noinspection deprecation
recycler_view.addItemDecoration(new ItemShadowDecorator((NinePatchDrawable) getResources().getDrawable(R.drawable.material_shadow_z1)));
}
drag_drop_manager.attachRecyclerView(recycler_view);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.fab:
addNewTourItem();
break;
}
}
@Override
public void onItemClick(RecyclerView parent, View v, int position, long id) {
editTourItem(position);
}
/**
* Launches EditTourItemActivity for the TourItem specified
* @param position_in_list position of the TourItem in the Tour's list
*/
private void editTourItem(int position_in_list) {
Intent intent = new Intent(getActivity(), EditTourItemActivity.class);
Bundle bundle = new Bundle();
bundle.putShort("position", (short) position_in_list);
intent.putExtras(bundle);
startActivityForResult(intent, EditTourItemActivity.EDIT_TOUR_ITEM_REQUEST);
}
private void addNewTourItem() {
_tour.addNewTourItem();
_adapter.notifyDataSetChanged();
editTourItem(_tour.getTourItems().size() - 1);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == Activity.RESULT_OK && requestCode == EditTourItemActivity.EDIT_TOUR_ITEM_REQUEST) {
/// EditTourItemActivity has returned. We may need to update our RecyclerView with the item's new properties.
_adapter.notifyDataSetChanged();
}
}
}