/**
*
*/
package com.gmail.charleszq.picorner.ui;
import java.util.Comparator;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.GridView;
import android.widget.TextView;
import com.gmail.charleszq.picorner.PicornerApplication;
import com.gmail.charleszq.picorner.R;
import com.gmail.charleszq.picorner.SPUtil;
import com.gmail.charleszq.picorner.dp.IPhotosProvider;
import com.gmail.charleszq.picorner.dp.SinglePagePhotosProvider;
import com.gmail.charleszq.picorner.model.GeoLocation;
import com.gmail.charleszq.picorner.model.MediaObject;
import com.gmail.charleszq.picorner.model.MediaObjectCollection;
import com.gmail.charleszq.picorner.model.MediaSourceType;
import com.gmail.charleszq.picorner.msg.IMessageConsumer;
import com.gmail.charleszq.picorner.msg.Message;
import com.gmail.charleszq.picorner.msg.MessageBus;
import com.gmail.charleszq.picorner.ui.command.ICommand;
import com.gmail.charleszq.picorner.ui.command.ICommandDoneListener;
import com.gmail.charleszq.picorner.ui.command.PhotoListCommand;
import com.gmail.charleszq.picorner.ui.helper.OneTimeScrollListener;
import com.gmail.charleszq.picorner.ui.helper.PhotoGridAdapter;
import com.gmail.charleszq.picorner.utils.IConstants;
import com.nostra13.universalimageloader.core.assist.PauseOnScrollListener;
/**
* @author charles(charleszq@gmail.com)
*
*/
public abstract class AbstractPhotoGridFragment extends
AbstractFragmentWithImageFetcher implements OnItemClickListener {
private static String TAG = AbstractPhotoGridFragment.class.getSimpleName();
/**
* UI controls
*/
protected GridView mGridView;
protected TextView mLoadingMessageText;
/**
* Photo grid size information.
*/
protected int mImageThumbSize;
protected int mImageThumbSpacing;
/**
* The data provider to store photos.
*/
protected IPhotosProvider mPhotosProvider = new SinglePagePhotosProvider(
new MediaObjectCollection());
/**
* The photo grid adapter
*/
protected PhotoGridAdapter mAdapter;
/**
* Save the current command, so we can load more data later.
*/
protected PhotoListCommand mCurrentCommand;
/**
* m1: 'Photo of user' m2: 'Loading photos of user..."
*/
protected String mLoadingMessage;
/**
* The marker to say no more data, then we don't do loading more.
*/
protected boolean mNoMoreData = false;
protected OneTimeScrollListener mScrollListener = null;
ICommandDoneListener<MediaObjectCollection> mCommandDoneListener = new ICommandDoneListener<MediaObjectCollection>() {
@Override
public void onCommandDone(ICommand<MediaObjectCollection> command,
MediaObjectCollection t) {
if (t == null || t.getPhotos().isEmpty()) {
mNoMoreData = true;
} else {
Object comparator = command.getAdapter(Comparator.class);
mPhotosProvider.loadData(t, command, comparator);
mAdapter.notifyDataSetChanged();
}
if (mLoadingMessageText != null) {
mLoadingMessageText.setVisibility(View.GONE);
}
}
};
protected IMessageConsumer mConsumer = new IMessageConsumer() {
@Override
public boolean consumeMessage(Message msg) {
switch (msg.getMessageType()) {
case Message.LIKE_PHOTO:
for (int i = 0; i < mPhotosProvider.getCurrentSize(); i++) {
MediaObject photo = mPhotosProvider.getMediaObject(i);
if (photo.getId().equals(msg.getPhotoId())) {
photo.setUserLiked(Boolean.parseBoolean(msg
.getCoreData().toString()));
break;
}
}
return true;
case Message.VOTE_PHOTO:
for (int i = 0; i < mPhotosProvider.getCurrentSize(); i++) {
MediaObject photo = mPhotosProvider.getMediaObject(i);
if (photo.getId().equals(msg.getPhotoId())) {
photo.setUserVoted(true);
break;
}
}
return true;
case Message.GEO_INFO_FETCHED:
for (int i = 0; i < mPhotosProvider.getCurrentSize(); i++) {
MediaObject photo = mPhotosProvider.getMediaObject(i);
if (photo.getId().equals(msg.getPhotoId())) {
photo.setLocation((GeoLocation) msg.getCoreData());
break;
}
}
return true;
case Message.CANCEL_COMMAND:
if (mCurrentCommand != null
&& mCurrentCommand != msg.getCoreData()) {
mCurrentCommand.cancel();
}
if( mLoadingMessageText != null ) {
mLoadingMessageText.setVisibility(View.GONE);
}
return true;
default:
return false;
}
}
};
private int mCurrentSelectedIndex = -1;
private ActionMode mCurrentActionMode;
private View mCurrentSelectedView = null;
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
MenuItem mapItem = menu.findItem(R.id.menu_item_view_on_map);
MediaObject photo = mPhotosProvider
.getMediaObject(mCurrentSelectedIndex);
mapItem.setVisible(photo.getLocation() != null);
if (photo.getMediaSource().equals(MediaSourceType.INSTAGRAM)) {
MenuItem exifItem = menu.findItem(R.id.menu_item_view_exif);
exifItem.setVisible(false);
}
PicornerApplication app = (PicornerApplication) getActivity()
.getApplication();
boolean isMyPhoto = app.isMyOwnPhoto(photo);
if (isMyPhoto && photo.getMediaSource() == MediaSourceType.FLICKR) {
menu.setGroupVisible(R.id.group_my_flickr_photo, true);
} else {
menu.setGroupVisible(R.id.group_my_flickr_photo, false);
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mCurrentActionMode = null;
mCurrentSelectedIndex = -1;
if (mCurrentSelectedView != null) {
mCurrentSelectedView.setAlpha(1f);
mCurrentSelectedView = null;
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater mf = mode.getMenuInflater();
mf.inflate(R.menu.photo_detail_common, menu);
mf.inflate(R.menu.my_flickr_photo_menus, menu);
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_comment:
showPhotoDetailWithPage(PhotoDetailActivity.COMMENT_PAGE);
break;
case R.id.menu_item_photo_set:
showPhotoDetailWithPage(PhotoDetailActivity.MY_F_ORG_PHOTO_SET_PAGE);
break;
case R.id.menu_item_add_to_group:
showPhotoDetailWithPage(PhotoDetailActivity.MY_F_ORG_GROUP_PAGE);
break;
case R.id.menu_item_view_exif:
showPhotoDetailWithPage(PhotoDetailActivity.EXIF_PAGE);
break;
case R.id.menu_item_view_on_map:
showPhotoDetailWithPage(PhotoDetailActivity.MAP_PAGE);
break;
}
if (mCurrentSelectedView != null) {
mCurrentSelectedView.setAlpha(1f);
mCurrentSelectedView = null;
}
mode.finish();
return true;
}
private void showPhotoDetailWithPage(String pageIndex) {
Intent detailIntent = new Intent(getActivity(),
PhotoDetailActivity.class);
detailIntent.putExtra(ImageDetailActivity.DP_KEY, mPhotosProvider);
detailIntent.putExtra(ImageDetailActivity.LARGE_IMAGE_POSITION,
mCurrentSelectedIndex);
if (pageIndex != null)
detailIntent.putExtra(PhotoDetailActivity.DETAIL_PAGE_KEY,
pageIndex);
startActivity(detailIntent);
}
};
/**
*
*/
public AbstractPhotoGridFragment() {
}
void exitActionMode() {
if( mCurrentActionMode != null ) {
mCurrentActionMode.finish();
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
initialIntentData(getActivity().getIntent());
mLoadingMessage = getLoadingMessage();
if (mGridView != null) {
mGridView.setOnScrollListener(null);
}
if (mCurrentCommand != null) {
mCurrentCommand.attacheContext(getActivity());
}
this.setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.user_photo_list_fragment, null);
// layout ui controls
mGridView = (GridView) v.findViewById(R.id.grid_user_photos);
mLoadingMessageText = (TextView) v.findViewById(R.id.txt_user_info);
mImageThumbSize = getResources().getDimensionPixelSize(
R.dimen.image_thumbnail_size);
mImageThumbSpacing = getResources().getDimensionPixelSize(
R.dimen.image_thumbnail_spacing);
if (mAdapter == null) {
mAdapter = new PhotoGridAdapter(getActivity(), mPhotosProvider,
mImageFetcher);
}
mGridView.setAdapter(mAdapter);
mGridView.setOnItemClickListener(this);
mScrollListener = new GridOnScrollListener(this);
PauseOnScrollListener pauseListener = new PauseOnScrollListener(false,
true, mScrollListener);
mGridView.setOnScrollListener(pauseListener);
mGridView.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
if (mCurrentActionMode != null)
return false;
mCurrentSelectedIndex = (int) id;
mCurrentActionMode = getActivity().startActionMode(
mActionModeCallback);
mCurrentSelectedView = view;
mCurrentSelectedView.setAlpha(0.5f);
return true;
}
});
mGridView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final int numColumns = (int) Math.floor(mGridView
.getWidth()
/ (mImageThumbSize + mImageThumbSpacing));
if (numColumns > 0) {
final int columnWidth = (mGridView.getWidth() / numColumns)
- mImageThumbSpacing;
mAdapter.setNumColumns(numColumns);
mAdapter.setItemHeight(columnWidth);
}
}
});
bindData();
return v;
}
@Override
public void onResume() {
super.onResume();
if (mCurrentCommand == null) {
loadFirstPage();
}
MessageBus.addConsumer(mConsumer);
}
/*
* (non-Javadoc)
*
* @see android.support.v4.app.Fragment#onDetach()
*/
@Override
public void onDetach() {
MessageBus.removeConsumer(mConsumer);
super.onDetach();
}
/**
* The sub-classes need to handle that and hide/show message if any.
*/
protected void loadMoreData() {
int currentPhotoSize = mPhotosProvider.getCurrentSize();
Log.d(TAG, String.format(
"When loading more, there are %s photos currently", //$NON-NLS-1$
currentPhotoSize));
boolean noMoreData = mNoMoreData;
int maxSize = SPUtil.getMaxPhotoSize(getActivity());
noMoreData = noMoreData | currentPhotoSize > maxSize;
if (currentPhotoSize > 0) {
noMoreData = noMoreData
| currentPhotoSize < IConstants.DEF_MIN_PAGE_SIZE;
}
if (noMoreData) {
Log.d(TAG, "There is no more data."); //$NON-NLS-1$
mLoadingMessageText.setVisibility(View.GONE);
return;
}
Log.d(TAG, "Loading more..."); //$NON-NLS-1$
mLoadingMessageText.setVisibility(View.VISIBLE);
if (mCurrentCommand != null)
mCurrentCommand.loadNextPage();
}
/**
* Loads the first page
*/
abstract protected void loadFirstPage();
/**
* Initializes the intent data
*
* @param intent
*/
abstract protected void initialIntentData(Intent intent);
/**
* Gets the load message
*
* @return
*/
abstract protected String getLoadingMessage();
/**
* Bind data to UI, the data usually comes from the intent
*/
abstract protected void bindData();
protected static class GridOnScrollListener extends OneTimeScrollListener {
private AbstractPhotoGridFragment mFragment;
protected GridOnScrollListener(AbstractPhotoGridFragment fragment) {
this.mFragment = fragment;
}
@Override
protected void loadMoreData() {
mFragment.loadMoreData();
}
@Override
protected void showGridTitle(boolean show) {
mFragment.exitActionMode();
}
}
}