Java tutorial
/* Copyright 2014-2016 Alan G. Downie Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing), software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package uk.org.downiesoft.slideshow; import android.app.ActionBar; import android.app.Activity; import android.app.ActivityOptions; import android.app.Fragment; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Point; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceManager; import android.support.v4.content.ContextCompat; import android.util.SparseBooleanArray; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; import android.widget.GridView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.Toast; import java.io.File; import java.util.ArrayList; import android.graphics.PointF; /** * Fragment class to manage thumbnail {@link android.widget.GridView} and associated {@link PreviewFragment} image preview pane. */ public class GridViewFragment extends Fragment implements FavouritesManager.FavouritesCallback, ThumbnailAdapter.ThumbnailAdapterListener, PreviewFragment.PreviewFragmentListener { public static final String TAG = GridViewFragment.class.getName(); /** Reference to the layout GridView. */ private GridView mGridView; /** Reference to the layout ProgressBar. */ private ProgressBar mProgressBar; /** The {@link ThumbnailAdapter} backing the GridView. */ private ThumbnailAdapter mThumbnailAdapter; /** The current source directory for the images. */ private ZFile mCurrentFile; /** The previous source directory for images (used when returning from viewing favourites). */ private ZFile mPreviousFile; /** The currently selected image (shown in preview pane). */ private int mCurrentImage; /** The current first position visible in the grid. */ private int mCurrentScrollY; /** Flag indicating if back key should be intercepted. */ private boolean mGuardBackKey = false; /** Maximumn time between back key presses to cause a "normal" back event. */ private long mBackTimestampMillis = 0; /** A reference to the fragment managing the preview frame. */ private PreviewFragment mPreview; /** The current favourites list. */ private ListPresentation mFavourites; /** Flag indicating if we are showing the current favourites list. */ private boolean mShowingFavourites; /** The application preferences. */ private SharedPreferences mSettings; /** The size of thumbnails in pixels. */ private int mThumbSize; /** The action mode triggered by a long press. */ private ActionMode mActionMode; /** * {@inheritDoc} */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SlideShowActivity.debug(1, TAG, "onCreate: %d %s", mCurrentImage, savedInstanceState == null ? "null" : savedInstanceState.toString()); mSettings = PreferenceManager.getDefaultSharedPreferences(getActivity()); mThumbSize = getThumbSizeSetting(); mCurrentScrollY = 0; } /** * {@inheritDoc} */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { SlideShowActivity.debug(1, TAG, "onCreateView: %d %s", mCurrentImage, savedInstanceState == null ? "null" : savedInstanceState.toString()); View parent = inflater.inflate(R.layout.gridview_fragment, container, false); mGridView = (GridView) parent.findViewById(R.id.gridview); mGridView.setEmptyView(parent.findViewById(R.id.emtpygridview)); mProgressBar = (ProgressBar) parent.findViewById(R.id.gridviewProgressBar); mThumbSize = getThumbSizeSetting(); mGridView.setColumnWidth(mThumbSize); mPreview = (PreviewFragment) getFragmentManager().findFragmentByTag(PreviewFragment.TAG); setHasOptionsMenu(true); // define actions to be taken when a thumbnail is clicked mGridView.setOnItemClickListener(new GridView.OnItemClickListener() { /** * {@inheritDoc} */ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (mPreview == null || mGridView.getChoiceMode() == ListView.CHOICE_MODE_NONE) { // Preview not visible so switch to slidshow view mCurrentImage = position; mGridView.setItemChecked(position, true); ActivityOptions options = ActivityOptions.makeScaleUpAnimation(mGridView, (int) view.getX(), (int) view.getY(), view.getWidth(), view.getHeight()); startSlideshow(mCurrentFile, position, false, options); } else { // Preview visible so action depends on which icon was clicked if (mCurrentImage == position) { // currently selected icon so switch to slideshow view ActivityOptions options = ActivityOptions.makeScaleUpAnimation(mGridView, (int) view.getX(), (int) view.getY(), view.getWidth(), view.getHeight()); startSlideshow(mCurrentFile, position, false, options); } else { // different icon so select it mCurrentImage = position; mCurrentScrollY = mGridView.getFirstVisiblePosition(); mGridView.setItemChecked(position, true); mPreview.setImage(mCurrentImage); } } } }); mGridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { /** * {@inheritDoc} */ @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { // begin action mode mGridView.setMultiChoiceModeListener(new GridViewMultiChoiceModeListener()); mGridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); mGridView.setItemChecked(position, true); return true; } }); if (savedInstanceState != null) { SlideShowActivity.debug(1, TAG, "savedInstance: %s", savedInstanceState.toString()); mShowingFavourites = savedInstanceState.getBoolean("showingFavourites"); mCurrentFile = new ZFile(savedInstanceState.getString("currentFile", "")); if (mCurrentFile.toString().endsWith(getString(R.string.text_images_placeholder))) { mCurrentFile = new ZFile(mCurrentFile.getParentPath()); } mCurrentImage = savedInstanceState.getInt("currentImage", 0); mPreviousFile = new ZFile(savedInstanceState.getString("previousFile")); if (mThumbnailAdapter == null) { mThumbnailAdapter = new ThumbnailAdapter(getActivity(), mCurrentFile, mCurrentImage, mThumbSize, this); } } else { String defaultPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) .toString(); mCurrentFile = new ZFile(mSettings.getString(SettingsActivity.PREFS_LASTDIR, defaultPath)); if (mCurrentFile.toString().endsWith(getString(R.string.text_images_placeholder))) { mCurrentFile = new ZFile(mCurrentFile.getParentPath()); } if (!mCurrentFile.exists()) { mCurrentFile = new ZFile(defaultPath); mCurrentImage = mSettings.getInt(SettingsActivity.PREFS_CURRENTIMAGE, 0); } mPreviousFile = mCurrentFile; mThumbnailAdapter = new ThumbnailAdapter(getActivity(), mCurrentFile, mCurrentImage, mThumbSize, this); } mFavourites = FavouritesManager.getInstance(getActivity()); if (savedInstanceState != null) { SlideShowActivity.debug(1, TAG, "onCreateView: %s", savedInstanceState.toString()); mCurrentImage = savedInstanceState.getInt("currentImage", 0); } SlideShowActivity.debug(1, TAG, "onCreateView end: %d", mCurrentImage); return parent; } /** * {@inheritDoc} */ @Override public void onViewStateRestored(Bundle outState) { super.onViewStateRestored(outState); SlideShowActivity.debug(1, TAG, "onViewStateRestored: %d %s", mCurrentImage, outState == null ? "null" : outState.toString()); if (outState != null) { mCurrentImage = outState.getInt("currentImage", 0); } else { mCurrentImage = mSettings.getInt(SettingsActivity.PREFS_CURRENTIMAGE, 0); mCurrentScrollY = mSettings.getInt(SettingsActivity.PREFS_FIRSTIMAGE, 0); } if (mThumbnailAdapter == null) { mThumbnailAdapter = new ThumbnailAdapter(getActivity(), mCurrentFile, mCurrentImage, mThumbSize, this); } if (mPreview != null) { mPreview.setPresentation(mThumbnailAdapter.getPresentation(), mCurrentImage); } mGridView.setAdapter(mThumbnailAdapter); } /** * {@inheritDoc} */ @Override public void onStart() { super.onStart(); SlideShowActivity.debug(1, TAG, "onStart: %d %d", mCurrentImage, mCurrentScrollY); int prevThumbSize = mThumbSize; // check if thumbsize has changed (e.g. if returning from settings activity) mThumbSize = getThumbSizeSetting(); mThumbnailAdapter.setThumbSize(mThumbSize); if (mThumbSize != prevThumbSize) { mGridView.setColumnWidth(mThumbSize); if (mThumbnailAdapter != null) { mThumbnailAdapter.notifyDataSetChanged(); } mGridView.invalidate(); } boolean visible = mSettings.getBoolean(getActivity().getString(R.string.PREFS_SHOW_PREVIEW), mPreview != null); mGridView.setChoiceMode( (mPreview == null || !visible) ? ListView.CHOICE_MODE_NONE : ListView.CHOICE_MODE_SINGLE); mGridView.setSelection(mCurrentImage); mGridView.setSelection(mCurrentScrollY); mGridView.setItemChecked(mCurrentImage, true); mGridView.invalidate(); setStatus(mCurrentFile); mThumbnailAdapter.resume(); } /** * {@inheritDoc} */ @Override public void onResume() { super.onResume(); SlideShowActivity.debug(1, TAG, "onResume: %d %d", mCurrentImage, mCurrentScrollY); mGuardBackKey = true; // ensure the visible scroll region is in the same place as before mGridView.setSelection(mCurrentImage); mGridView.setSelection(mCurrentScrollY); mGridView.setItemChecked(mCurrentImage, true); mGridView.invalidate(); } /** * {@inheritDoc} */ @Override public void onPause() { super.onPause(); SlideShowActivity.debug(1, TAG, "onPause: %d %d", mCurrentImage, mCurrentScrollY); mGuardBackKey = false; mCurrentScrollY = mGridView.getFirstVisiblePosition(); mFavourites.save(true); } /** * {@inheritDoc} */ @Override public void onStop() { super.onStop(); SlideShowActivity.debug(1, TAG, "onStop: %d", mCurrentImage); SharedPreferences.Editor editor = mSettings.edit(); if (!mShowingFavourites) { editor.putString(SettingsActivity.PREFS_LASTDIR, mCurrentFile.toString()); editor.putInt(SettingsActivity.PREFS_CURRENTIMAGE, mCurrentImage); editor.putInt(SettingsActivity.PREFS_FIRSTIMAGE, mCurrentScrollY); } else { editor.putInt(SettingsActivity.PREFS_FAV_CURRENTIMAGE, mCurrentImage); editor.putInt(SettingsActivity.PREFS_FAV_FIRSTIMAGE, mCurrentScrollY); } editor.apply(); if (mThumbnailAdapter != null) mThumbnailAdapter.cancel(); } /** * {@inheritDoc} */ @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("currentFile", mCurrentFile.getPath()); outState.putString("previousFile", mPreviousFile.getPath()); outState.putInt("currentImage", mCurrentImage); outState.putBoolean("showingFavourites", mShowingFavourites); SlideShowActivity.debug(1, TAG, "onSaveInstanceState: %s", outState.toString()); } /** * {@inheritDoc} */ @Override public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { super.onCreateOptionsMenu(menu, menuInflater); menuInflater.inflate(R.menu.gridfragment_menu, menu); } /** * {@inheritDoc} */ @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); if (!mShowingFavourites) { menu.setGroupVisible(R.id.menu_group_not_favourites, true); menu.setGroupVisible(R.id.menu_group_favourites, false); } else { menu.setGroupVisible(R.id.menu_group_not_favourites, false); menu.setGroupVisible(R.id.menu_group_favourites, true); } } /** * {@inheritDoc} */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_slideshow: View thumbView = mGridView.getChildAt(0); ActivityOptions options = ActivityOptions.makeScaleUpAnimation(mGridView, (int) thumbView.getX(), (int) thumbView.getY(), thumbView.getWidth(), thumbView.getHeight()); startSlideshow(mCurrentFile, 0, true, options); return true; case R.id.action_show_favourites: showFavourites(); return true; case R.id.action_save_favourites: FavouritesManager.saveFavouritesDialog(getActivity(), mFavourites, this); return true; case R.id.action_open_favourites: FavouritesManager.loadFavouritesDialog(getActivity(), this); return true; case R.id.action_refresh_gridthumbs: mThumbnailAdapter.refreshThumbs(); return true; case R.id.action_browse: Intent intent = new Intent(getActivity(), BrowserActivity.class); intent.putExtra(BrowserDialog.ARG_ZFILE, mCurrentFile.toArgs()); startActivityForResult(intent, SlideShowActivity.REQUEST_BROWSER); return true; default: return false; } } /** * {@inheritDoc} */ @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { SlideShowActivity.debug(1, TAG, "onActivityResult(%s,%s)", requestCode, resultCode); switch (requestCode) { case SlideShowActivity.REQUEST_FAVOURITES: if (resultCode == Activity.RESULT_OK) { File file = new File(data.getStringExtra("file")); onFavouritesChanged(file); } break; case SlideShowActivity.REQUEST_SLIDESHOW: if (data != null) { int image = data.getIntExtra("currentImage", mCurrentImage); SlideShowActivity.debug(1, TAG, "onActivityResult: %d %d", requestCode, image); if (image != mCurrentImage) { mCurrentImage = image; int first = mGridView.getFirstVisiblePosition(); int last = mGridView.getLastVisiblePosition(); if (image < first || image > last) { mCurrentScrollY = image; } mGridView.setSelection(mCurrentImage); if (mPreview != null) { //mPreview.setImage(mCurrentImage); } } } break; case SlideShowActivity.REQUEST_BROWSER: if (resultCode == Activity.RESULT_OK) { ZFile zfile = new ZFile(data.getBundleExtra(BrowserDialog.ARG_ZFILE)); if (!zfile.equals(mCurrentFile)) { fileChanged(zfile, 0, 0, false); } } break; default: super.onActivityResult(requestCode, resultCode, data); } } /** * Get the current thumbnail setting size. * @return The thumbnail size in pixels. */ private int getThumbSizeSetting() { int thumbSize = Integer .parseInt(mSettings.getString(getActivity().getString(R.string.PREFS_THUMBSIZE), "1")); SlideShowActivity.debug(1, TAG, "thumbsize setting: %s", thumbSize); TypedArray thumbDimens = getResources().obtainTypedArray(R.array.thumbsize_dimensions); thumbSize = thumbDimens.getDimensionPixelSize(thumbSize, getResources().getDimensionPixelSize(R.dimen.thumbsize_medium)); SlideShowActivity.debug(1, TAG, "thumbsize pixels: %s", thumbSize); thumbDimens.recycle(); return thumbSize; } /** * Switch to favourites view. */ public void showFavourites() { mFavourites.save(false); int currentImage = mSettings.getInt(SettingsActivity.PREFS_FAV_CURRENTIMAGE, 0); int currentScrollY = mSettings.getInt(SettingsActivity.PREFS_FAV_FIRSTIMAGE, 0); fileChanged(mFavourites.getRootFile(), currentImage, currentScrollY, true); getActivity().invalidateOptionsMenu(); } /** * Start the slideshow activity. * @param aFile The location of the images to be shown. * @param aPosition The position of the starting slide. * @param aAutoStart Flag indicating if the slideshow should start running immediately (true). * @param aOptions Activity transition options (e.g. scale-up transition option). */ public void startSlideshow(ZFile aFile, int aPosition, boolean aAutoStart, ActivityOptions aOptions) { Intent intent = new Intent(getActivity(), SlidesActivity.class); intent.putExtra(SlidesActivity.ARG_ZFILE, aFile.toArgs()); intent.putExtra(SlidesActivity.ARG_START_SLIDE, aPosition); intent.putExtra(SlidesActivity.ARG_AUTOSTART, aAutoStart); if (aOptions != null) { startActivityForResult(intent, SlideShowActivity.REQUEST_SLIDESHOW, aOptions.toBundle()); } else { startActivity(intent); } } /** * Change the grid to show the images in the specified location. * @param aFile The location of the images to be viewed. * @param aImage The initially selected image. * @param aFirst The first visible image in the grid view (to reinstate scroll position). * @param aIsFavourites Flag indicating if this is a favourites list. */ public void fileChanged(ZFile aFile, int aImage, int aFirst, boolean aIsFavourites) { SlideShowActivity.debug(1, TAG, "fileChanged(%s,%s,%s)", aFile.getName(), aImage, aFirst); SharedPreferences.Editor editor = mSettings.edit(); if (aIsFavourites && !mShowingFavourites) { editor.putString(SettingsActivity.PREFS_LASTDIR, mCurrentFile.toString()); editor.putInt(SettingsActivity.PREFS_CURRENTIMAGE, mCurrentImage); editor.putInt(SettingsActivity.PREFS_FIRSTIMAGE, mCurrentScrollY); } else if (mShowingFavourites) { editor.putInt(SettingsActivity.PREFS_FAV_CURRENTIMAGE, mCurrentImage); editor.putInt(SettingsActivity.PREFS_FAV_FIRSTIMAGE, mCurrentScrollY); } editor.apply(); mCurrentFile = aFile; mCurrentImage = aImage; setStatus(mCurrentFile); mCurrentScrollY = aFirst; if (mGridView != null) { if (mThumbnailAdapter != null) { mThumbnailAdapter.cancel(); } mThumbnailAdapter = new ThumbnailAdapter(getActivity(), mCurrentFile, mCurrentImage, mThumbSize, GridViewFragment.this); mGridView.clearChoices(); mGridView.setAdapter(mThumbnailAdapter); mGridView.setSelection(mCurrentImage); mGridView.setSelection(mCurrentScrollY); mGridView.setItemChecked(mCurrentImage, true); mThumbnailAdapter.resume(); } if (mPreview != null) { mPreview.setPresentation(mThumbnailAdapter.getPresentation(), mCurrentImage); } if (!aIsFavourites && !mShowingFavourites) { editor = mSettings.edit(); editor.putString(SettingsActivity.PREFS_LASTDIR, mCurrentFile.toString()); editor.putInt(SettingsActivity.PREFS_CURRENTIMAGE, mCurrentImage); editor.putInt(SettingsActivity.PREFS_FIRSTIMAGE, mCurrentScrollY); editor.commit(); } mShowingFavourites = aIsFavourites; } /** * {@inheritDoc} */ @Override public void onFavouritesChanged(File aFile) { mFavourites.importFile(aFile); mFavourites.save(true); final SharedPreferences slideshowSettings = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences.Editor editor = slideshowSettings.edit(); String name = aFile.getName().substring(0, aFile.getName().length() - FavouritesManager.FAVOURITES_EXT.length()); SlideShowActivity.debug(1, TAG, "updateFavourites: %s", name); editor.putString(SettingsActivity.PREFS_FAVOURITES, name); editor.apply(); fileChanged(mFavourites.getRootFile(), 0, 0, true); } /** * Set the title/subtitle in the ActionBar to reflect the current path/sub-path * @param aFile The current file location. */ private void setStatus(final ZFile aFile) { final ActionBar actionBar = getActivity().getActionBar(); if (actionBar != null) { String subPath = aFile.getSubPath(); String images = getString(R.string.text_images_placeholder); if (subPath.endsWith(images)) { subPath = subPath.substring(subPath.lastIndexOf(images)); if (subPath.endsWith(File.separator)) { subPath = subPath.substring(0, subPath.length() - 1); } } if (aFile.isZipFile()) { File zip = new File(aFile.getRootPath()); actionBar.setTitle(zip.getName()); if (subPath.length() == 0) { actionBar.setSubtitle(null); } else { if (subPath.length() > 30) { subPath = "\u2026" + subPath.substring(subPath.length() - 30); } actionBar.setSubtitle(subPath); } } else { actionBar.setTitle(aFile.getName()); actionBar.setSubtitle(null); } } } /** * Called from main activity when the back key is pressed to allow this fragment to perform a suitable action. * @return true if the back key event has been consumed (i.e. no further action should be taken). */ public boolean offerBackKeyEvent() { if (mShowingFavourites) { // close the favourites and return to normal view SharedPreferences.Editor editor = mSettings.edit(); editor.putInt(SettingsActivity.PREFS_FAV_CURRENTIMAGE, mCurrentImage); editor.putInt(SettingsActivity.PREFS_FAV_FIRSTIMAGE, mCurrentScrollY); editor.apply(); ZFile currentFile = new ZFile( mSettings.getString(SettingsActivity.PREFS_LASTDIR, mCurrentFile.toString())); int currentImage = mSettings.getInt(SettingsActivity.PREFS_CURRENTIMAGE, 0); int currentScrollY = mSettings.getInt(SettingsActivity.PREFS_FIRSTIMAGE, 0); fileChanged(currentFile, currentImage, currentScrollY, false); getActivity().invalidateOptionsMenu(); return true; } else if (mGuardBackKey) { // need double back key within 2 seconds to close long now = System.currentTimeMillis(); if (now - mBackTimestampMillis > 2000) { Toast.makeText(getActivity(), R.string.text_press_back_again, Toast.LENGTH_SHORT).show(); mBackTimestampMillis = now; return true; } } return false; } /** * Set the grid choice mode depending on the visibility of the preview pane. */ public void setGridChoiceMode() { boolean visible = mPreview != null && mPreview.isPreviewVisible(); mGridView.setChoiceMode( (mPreview == null || !visible) ? ListView.CHOICE_MODE_NONE : ListView.CHOICE_MODE_SINGLE); mGridView.setSelection(mCurrentImage); mGridView.setItemChecked(mCurrentImage, true); } /** * {@inheritDoc} * @see ThumbnailAdapter.ThumbnailAdapterListener */ @Override public void showProgress(int aVisibility) { if (mProgressBar != null) { mProgressBar.bringToFront(); mProgressBar.setVisibility(aVisibility); } } /** * {@inheritDoc} * @see ThumbnailAdapter.ThumbnailAdapterListener */ @Override public void onThumbnailsReady() { /* do nothing */ } /** * {@inheritDoc} * In this case we select the given slide in the grid view. * @see PreviewFragment.PreviewFragmentListener */ @Override public void onNewPreviewSlide(int aSlide) { SlideShowActivity.debug(2, TAG, "onNewPreviewSlide(%s)", aSlide); mCurrentImage = aSlide; mGridView.smoothScrollToPosition(mCurrentImage); mCurrentScrollY = mGridView.getFirstVisiblePosition(); mGridView.setItemChecked(mCurrentImage, true); mGridView.invalidate(); } /** * {@inheritDoc} * In this case we select the given slide in the grid view. * @see PreviewFragment.PreviewFragmentListener */ @Override public void onPreviewStartSlideshow() { View previewView = mPreview.getView(); if (previewView != null) { ActivityOptions options = ActivityOptions.makeScaleUpAnimation(mGridView, (int) previewView.getX(), (int) previewView.getY(), previewView.getWidth(), previewView.getHeight()); startSlideshow(mCurrentFile, mCurrentImage, false, options); } } /** * {@inheritDoc} */ @Override public boolean isFlingPermitted() { return mActionMode == null; } /** * {@inheritDoc} */ @Override public int getCurrentImage() { return mCurrentImage; } /** * {@inheritDoc} */ private class GridViewMultiChoiceModeListener implements MultiChoiceModeListener { /** Flag indicating if all items have been selected. */ private boolean mSelectAll = false; /** * {@inheritDoc} * Updates preview image to show selected slide. */ @Override public void onItemCheckedStateChanged(ActionMode actionMode, int position, long id, boolean checked) { if (mPreview != null && !mSelectAll) { mPreview.setImage(position); mCurrentImage = position; mCurrentScrollY = mGridView.getFirstVisiblePosition(); } mSelectAll &= checked; actionMode.invalidate(); } /** * {@inheritDoc} */ @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mActionMode = mode; mode.getMenuInflater().inflate(R.menu.thumbnail_popup_menu, menu); UiHider.setActionMode(true); switch (mThumbnailAdapter.mPresentation.getType()) { case Presentation.LIST_PRESENTATION: menu.removeItem(R.id.thumbnailAddToSlideshow); break; case Presentation.ZIP_PRESENTATION: case Presentation.DIR_PRESENTATION: break; } return true; } /** * {@inheritDoc} */ @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { int count = mGridView.getCheckedItemCount(); boolean isList = mThumbnailAdapter.getPresentation().getType() == Presentation.LIST_PRESENTATION; if (count == 0) { menu.setGroupVisible(R.id.thumbnail_popup_single, false); menu.setGroupVisible(R.id.thumbnail_popup_add, false); menu.setGroupVisible(R.id.thumbnail_popup_remove, false); menu.setGroupVisible(R.id.thumbnail_popup_selection, true); } else { if (isList) { menu.setGroupVisible(R.id.thumbnail_popup_remove, true); menu.setGroupVisible(R.id.thumbnail_popup_add, false); } else { menu.setGroupVisible(R.id.thumbnail_popup_remove, false); menu.setGroupVisible(R.id.thumbnail_popup_add, true); } if (count == 1) { menu.setGroupVisible(R.id.thumbnail_popup_single, true); menu.setGroupVisible(R.id.thumbnail_popup_selection, true); } else { menu.setGroupVisible(R.id.thumbnail_popup_single, false); menu.setGroupVisible(R.id.thumbnail_popup_selection, true); } } menu.setGroupVisible(R.id.thumbnail_popup_extract, mCurrentFile.isZipFile()); return true; } /** * {@inheritDoc} */ @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) { SparseBooleanArray selection = mGridView.getCheckedItemPositions(); int selectedCount = mGridView.getCheckedItemCount(); switch (item.getItemId()) { case R.id.thumbnailSetWallpaper: if (selectedCount == 1) { int i = selection.keyAt(0); BitmapManager.setWallpaper(getActivity(), mThumbnailAdapter.getPresentation(), mThumbnailAdapter.getName(i)); mThumbnailAdapter.notifyDataSetChanged(); } actionMode.finish(); return true; case R.id.thumbnailDetails: if (selectedCount == 1) { BitmapManager.displayBitmapProperties(getActivity(), mThumbnailAdapter.getPresentation(), selection.keyAt(0)); selection.clear(); mThumbnailAdapter.notifyDataSetChanged(); } actionMode.finish(); return true; case R.id.thumbnailAddToSlideshow: { for (int i = 0; i < selection.size(); i++) { if (selection.get(selection.keyAt(i))) { String path = mThumbnailAdapter.getPath(selection.keyAt(i)); mFavourites.add(path); } } Toast.makeText(getActivity(), R.string.text_added_favourite, Toast.LENGTH_SHORT).show(); selection.clear(); mThumbnailAdapter.notifyDataSetChanged(); actionMode.finish(); return true; } case R.id.thumbnailRemoveFromSlideshow: { for (int i = selection.size() - 1; i >= 0; i--) { int pos = selection.keyAt(i); if (selection.get(pos)) { String path = mThumbnailAdapter.getPath(pos); if (mThumbnailAdapter.mPresentation.getType() == Presentation.LIST_PRESENTATION) { int index = mFavourites.remove(path); SlideShowActivity.debug(1, TAG, "removeFromSlideshow: index=%d, pos=%d", index, pos); if (index >= 0) { mThumbnailAdapter.remove(pos); mCurrentImage = Math.max(0, Math.min(pos, mThumbnailAdapter.getCount() - 1)); mCurrentScrollY = mGridView.getFirstVisiblePosition(); } } } } mFavourites.save(false); mGridView.setItemChecked(mCurrentImage, true); mPreview.setImage(mCurrentImage); mGridView.invalidate(); selection.clear(); mThumbnailAdapter.notifyDataSetChanged(); actionMode.finish(); return true; } case R.id.thumbnailSelectAll: mSelectAll = true; for (int i = 0; i < mGridView.getCount(); i++) { mGridView.setItemChecked(i, true); } mSelectAll = false; actionMode.invalidate(); return true; case R.id.thumbnailExtract: ArrayList<File> names = new ArrayList<>(mGridView.getCheckedItemCount()); SparseBooleanArray checked = mGridView.getCheckedItemPositions(); for (int i = 0; i < mThumbnailAdapter.getCount(); i++) { if (checked.get(i, false)) { names.add(new File(mThumbnailAdapter.getName(i))); SlideShowActivity.debug(1, TAG, "action_extract: name %s", mThumbnailAdapter.getName(i)); } } ZFile source = new ZFile(mCurrentFile.toString()); if (source.getName().compareTo(getString(R.string.text_images_placeholder)) == 0) { source = new ZFile(source.getParentPath()); } File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), getActivity().getString(R.string.app_name)); File dest = new File(path, source.getName()); SlideShowActivity.debug(1, TAG, "action_extract: dest %s", dest.toString()); if (!dest.exists()) { if (!dest.mkdirs()) { Toast.makeText(getActivity(), R.string.text_save_failed, Toast.LENGTH_SHORT).show(); return false; } } ZipPresentation zp = (ZipPresentation) (mThumbnailAdapter.getPresentation()); int ok = zp.extract(names, dest); String message = String.format(getActivity().getString(R.string.text_extracted), ok, ok == 1 ? "s" : "", dest); Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); actionMode.finish(); return true; } return false; } /** * {@inheritDoc} */ @Override public void onDestroyActionMode(ActionMode p1) { mGridView.clearChoices(); UiHider.setActionMode(false); // need to defer the setting of choice mode because doing it here ends up with recursive calls to finish() mGridView.getHandler().post(new Runnable() { @Override public void run() { SlideShowActivity.debug(1, TAG, "mChoiceModeRunnable.run() %s %s", mCurrentImage, mCurrentScrollY); setGridChoiceMode(); if (mPreview != null) { mPreview.setImage(mCurrentImage); } mThumbnailAdapter.notifyDataSetChanged(); } }); mActionMode = null; } } }