/* * Copyright (C) 2012 Simon Robinson * * This file is part of Com-Me. * * Com-Me is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Com-Me 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 Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with Com-Me. * If not, see <http://www.gnu.org/licenses/>. */ package ac.robinson.mediatablet.provider; import ac.robinson.mediatablet.MediaTablet; import ac.robinson.mediatablet.R; import ac.robinson.mediatablet.activity.MediaBrowserActivity; import ac.robinson.mediatablet.view.MediaViewHolder; import ac.robinson.util.ImageCacheUtilities; import ac.robinson.view.CrossFadeDrawable; import ac.robinson.view.FastBitmapDrawable; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.CursorAdapter; import android.widget.Filter; import android.widget.FilterQueryProvider; import android.widget.Filterable; import android.widget.ImageView; import android.widget.ProgressBar; public class MediaAdapter extends CursorAdapter implements FilterQueryProvider { private final int mInternalIdIndex; private final int mParentIdIndex; private final int mTypeIndex; private final int mVisibilityIndex; private final MediaBrowserActivity mActivity; private final LayoutInflater mInflater; private final Bitmap mDefaultIconBitmap; private final FastBitmapDrawable mDefaultIcon; private final Filter mFilter; private final String mSelectionPublic; private final String mSelectionPrivate; private final String mSelectionId; private String mSelectionType; private String mSelection; private int mVisibilityFilter = MediaItem.MEDIA_PRIVATE; // *crucial* to clone for restarting activity (until proper state saving...) private int[] mMediaTypeFilter = MediaTabletProvider.NO_MEDIA_TYPES.clone(); private StringBuilder mTypeFilterBuilder = new StringBuilder(); private String mOwnerFilter = null; private final String[] mFilterArguments0 = new String[0]; private final String[] mFilterArguments1 = new String[1]; public MediaAdapter(MediaBrowserActivity activity, String ownerId, int mediaVisibility) { super(activity, activity.managedQuery(MediaItem.CONTENT_URI, MediaItem.PROJECTION_ALL, "1=?", new String[] { "0" }, null), true); // hack to show no data initially mActivity = activity; mInflater = LayoutInflater.from(activity); mFilter = ((Filterable) this).getFilter(); final Cursor c = getCursor(); mInternalIdIndex = c.getColumnIndexOrThrow(MediaItem.INTERNAL_ID); mParentIdIndex = c.getColumnIndexOrThrow(MediaItem.PARENT_ID); mTypeIndex = c.getColumnIndexOrThrow(MediaItem.TYPE); mVisibilityIndex = c.getColumnIndexOrThrow(MediaItem.VISIBILITY); // alternative (without frame): Bitmap.createBitmap(1, 1, // ImageCacheUtilities.mBitmapFactoryOptions.inPreferredConfig); mDefaultIconBitmap = PersonItem.loadTemporaryIcon(activity.getResources(), false); mDefaultIcon = new FastBitmapDrawable(mDefaultIconBitmap); final StringBuilder selection = new StringBuilder(); selection.append(MediaItem.VISIBILITY); selection.append("="); selection.append(MediaItem.MEDIA_PUBLIC); selection.append(" AND "); selection.append(MediaItem.DELETED); selection.append("=0 AND "); selection.append(MediaItem.TYPE); selection.append(" IN ("); mSelectionPublic = selection.toString(); selection.setLength(0); selection.append(MediaItem.TYPE); selection.append(" IN ("); mSelectionPrivate = selection.toString(); selection.setLength(0); selection.append(") AND "); selection.append("("); selection.append(MediaItem.DELETED); selection.append("=0 AND "); selection.append(MediaItem.PARENT_ID); selection.append("=?"); selection.append(")"); mSelectionId = selection.toString(); setFilterQueryProvider(this); mVisibilityFilter = mediaVisibility; buildMediaFilter(); setOwnerFilter(ownerId); } public FastBitmapDrawable getDefaultIcon() { return mDefaultIcon; } private void reFilter() { mFilter.filter(null); } public void setOwnerFilter(String ownerFilter) { mOwnerFilter = ownerFilter; if (mOwnerFilter == null) { mVisibilityFilter = MediaItem.MEDIA_PUBLIC; // only public media if no owner specified } reFilter(); } public void enableMediaFilters(int... filtersToEnable) { for (int i = 0, n = mMediaTypeFilter.length; i < n; i++) { mMediaTypeFilter[i] = 0; } for (int i = 0, n = filtersToEnable.length; i < n; i++) { mMediaTypeFilter[filtersToEnable[i] - 1] = filtersToEnable[i]; } buildMediaFilter(); reFilter(); } public void disableMediaFilters(int... filtersToDisable) { for (int i = 0, n = filtersToDisable.length; i < n; i++) { mMediaTypeFilter[filtersToDisable[i] - 1] = 0; } buildMediaFilter(); reFilter(); } public void setMediaFilters(boolean enable, int... filterValues) { if (enable) { enableMediaFilters(filterValues); } else { disableMediaFilters(filterValues); } } public void disableAllMediaFilters() { mMediaTypeFilter = MediaTabletProvider.NO_MEDIA_TYPES.clone(); buildMediaFilter(); reFilter(); } public void setVisibilityFilter(int visibilityFilter) { if (mOwnerFilter == null && visibilityFilter == MediaItem.MEDIA_PRIVATE) { // TODO: throw exception or alert user - can't view private when in all public view } else { mVisibilityFilter = visibilityFilter; } reFilter(); } public int getVisibilityFilter() { return mVisibilityFilter; } private void buildMediaFilter() { boolean allEnabled = true; for (int i = 0, n = mMediaTypeFilter.length; i < n; i++) { if (mMediaTypeFilter[i] > 0) { allEnabled = false; break; } } mTypeFilterBuilder.setLength(0); for (int i = 0, n = MediaTabletProvider.ALL_MEDIA_TYPES.length; i < n; i++) { if (allEnabled) { mTypeFilterBuilder.append(MediaTabletProvider.ALL_MEDIA_TYPES[i]); } else { mTypeFilterBuilder.append(mMediaTypeFilter[i]); } mTypeFilterBuilder.append(','); } mTypeFilterBuilder.setLength(mTypeFilterBuilder.length() - 1); mSelectionType = mTypeFilterBuilder.toString(); } public View newView(Context context, Cursor cursor, ViewGroup parent) { final View view = mInflater.inflate(R.layout.grid_image_item, parent, false); MediaViewHolder holder = new MediaViewHolder(); holder.display = (ImageView) view.findViewById(R.id.grid_image_view_image); holder.loader = (ProgressBar) view.findViewById(R.id.grid_image_view_progress); holder.overlay = (ImageView) view.findViewById(R.id.grid_image_view_overlay); view.setTag(holder); final CrossFadeDrawable transition = new CrossFadeDrawable(mDefaultIconBitmap, null); transition.setCallback(view); transition.setCrossFadeEnabled(true); holder.transition = transition; return view; } // setBackgroundDrawable is deprecated from API 16+ (Jelly Bean), but we still want to target earlier versions; // since this is purely a name change, there's no real reason to do anything platform-independent @SuppressWarnings("deprecation") public void bindView(View view, Context context, Cursor c) { MediaViewHolder holder = (MediaViewHolder) view.getTag(); holder.mediaInternalId = c.getString(mInternalIdIndex); holder.mediaOwnerId = c.getString(mParentIdIndex); holder.mediaType = c.getInt(mTypeIndex); holder.mediaVisibility = c.getInt(mVisibilityIndex); final MediaBrowserActivity activity = mActivity; int iconVisibility = mOwnerFilter == null ? MediaItem.MEDIA_PUBLIC : MediaItem.MEDIA_PRIVATE; if (activity.getScrollState() == AbsListView.OnScrollListener.SCROLL_STATE_FLING || activity.isPendingIconsUpdate()) { holder.loader.setVisibility(View.VISIBLE); holder.display.setImageDrawable(mDefaultIcon); holder.queryIcon = true; } else { // if the icon has gone missing (recently imported or cache deletion), regenerate it // this will happen on every new person, but we check for the file before generation, so not too bad String mediaCacheId = MediaItem.getCacheId(holder.mediaInternalId, iconVisibility); FastBitmapDrawable cachedIcon = ImageCacheUtilities.getCachedIcon(MediaTablet.DIRECTORY_THUMBS, mediaCacheId, ImageCacheUtilities.NULL_DRAWABLE); if (ImageCacheUtilities.NULL_DRAWABLE.equals(cachedIcon)) { MediaManager.reloadMediaIcon(mActivity.getResources(), mActivity.getContentResolver(), holder.mediaInternalId, iconVisibility); cachedIcon = ImageCacheUtilities .getCachedIcon(MediaTablet.DIRECTORY_THUMBS, mediaCacheId, mDefaultIcon); } holder.display.setImageDrawable(cachedIcon); holder.loader.setVisibility(View.GONE); holder.queryIcon = false; } if (mOwnerFilter != null && holder.mediaVisibility == MediaItem.MEDIA_PUBLIC) { holder.overlay.setBackgroundResource(R.drawable.item_public); holder.overlay.setPadding(0, 0, 0, 0); } else { holder.overlay.setBackgroundDrawable(null); } } @Override public void changeCursor(Cursor cursor) { final Cursor oldCursor = getCursor(); if (oldCursor != null) mActivity.stopManagingCursor(oldCursor); super.changeCursor(cursor); } public Cursor runQuery(CharSequence constraint) { final StringBuilder buffer = new StringBuilder(); if (mVisibilityFilter == MediaItem.MEDIA_PRIVATE) { buffer.append(mSelectionPrivate); } else { buffer.append(mSelectionPublic); } buffer.append(mSelectionType); final String[] filterArguments; if (mOwnerFilter != null) { buffer.append(mSelectionId); filterArguments = mFilterArguments1; filterArguments[0] = mOwnerFilter; } else { buffer.append(")"); // hack! filterArguments = mFilterArguments0; } mSelection = buffer.toString(); // buffer.append('%') // wildcard // TODO: sort out projection to only return necessary columns return mActivity.managedQuery(MediaItem.CONTENT_URI, MediaItem.PROJECTION_ALL, mSelection, filterArguments, MediaItem.DEFAULT_SORT_ORDER); } }