com.ryan.ryanreader.fragments.ImageViewFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.ryan.ryanreader.fragments.ImageViewFragment.java

Source

/*******************************************************************************
 * This file is part of RedReader.
 *
 * RedReader 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.
 *
 * RedReader 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 RedReader.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

/*******************************************************************************
 * This file is part of RedReader.
 *
 * RedReader 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.
 *
 * RedReader 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 RedReader.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package com.ryan.ryanreader.fragments;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.polites.android.GestureImageView;
import com.ryan.ryanreader.account.RedditAccountManager;
import com.ryan.ryanreader.activities.BugReportActivity;
import com.ryan.ryanreader.cache.CacheManager;
import com.ryan.ryanreader.cache.CacheRequest;
import com.ryan.ryanreader.cache.RequestFailureType;
import com.ryan.ryanreader.common.Constants;
import com.ryan.ryanreader.common.General;
import com.ryan.ryanreader.common.LinkHandler;
import com.ryan.ryanreader.common.RRError;
import com.ryan.ryanreader.image.GifDecoderThread;
import com.ryan.ryanreader.reddit.prepared.RedditPreparedPost;
import com.ryan.ryanreader.reddit.things.RedditPost;
import com.ryan.ryanreader.reddit.things.RedditSubreddit;
import com.ryan.ryanreader.views.RedditPostView;
import com.ryan.ryanreader.views.bezelmenu.BezelSwipeOverlay;
import com.ryan.ryanreader.views.bezelmenu.SideToolbarOverlay;
import com.ryan.ryanreader.views.liststatus.ErrorView;
import com.ryan.ryanreader.views.liststatus.LoadingView;

import org.apache.http.StatusLine;
import org.holoeverywhere.LayoutInflater;
import org.holoeverywhere.app.Fragment;
import org.holoeverywhere.widget.FrameLayout;
import org.holoeverywhere.widget.LinearLayout;
import com.ryan.ryanreader.R;

import java.io.IOException;
import java.net.URI;
import java.util.UUID;

public class ImageViewFragment extends Fragment implements RedditPostView.PostSelectionListener {

    private URI url;

    private ImageView imageView;
    private GifDecoderThread gifThread;

    public static ImageViewFragment newInstance(final URI url, final RedditPost post) {

        final ImageViewFragment f = new ImageViewFragment();

        final Bundle bundle = new Bundle(1);
        bundle.putString("url", url.toString());
        if (post != null)
            bundle.putParcelable("post", post);
        f.setArguments(bundle);

        return f;
    }

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        // TODO load position/etc?
        super.onCreate(savedInstanceState);
        url = General.uriFromString(getArguments().getString("url"));
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
            final Bundle savedInstanceState) {

        final Context context = inflater.getContext();

        final LoadingView loadingView = new LoadingView(context, R.string.download_loading, true, false);

        final LinearLayout layout = new LinearLayout(context);
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.addView(loadingView);

        CacheManager.getInstance(context)
                .makeRequest(new CacheRequest(url, RedditAccountManager.getAnon(), null,
                        Constants.Priority.IMAGE_VIEW, 0, CacheRequest.DownloadType.IF_NECESSARY,
                        Constants.FileType.IMAGE, false, false, false, context) {

                    private void setContentView(View v) {
                        layout.removeAllViews();
                        layout.addView(v);
                        v.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
                        v.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
                    }

                    @Override
                    protected void onCallbackException(Throwable t) {
                        BugReportActivity.handleGlobalError(context.getApplicationContext(),
                                new RRError(null, null, t));
                    }

                    @Override
                    protected void onDownloadNecessary() {
                        loadingView.setIndeterminate(R.string.download_waiting);
                    }

                    @Override
                    protected void onDownloadStarted() {
                        loadingView.setIndeterminate(R.string.download_downloading);
                    }

                    @Override
                    protected void onFailure(final RequestFailureType type, Throwable t, StatusLine status,
                            final String readableMessage) {

                        loadingView.setDone(R.string.download_failed);
                        final RRError error = General.getGeneralErrorForFailure(context, type, t, status);

                        new Handler(Looper.getMainLooper()).post(new Runnable() {
                            public void run() {
                                // TODO handle properly
                                layout.addView(new ErrorView(getSupportActivity(), error));
                            }
                        });
                    }

                    @Override
                    protected void onProgress(long bytesRead, long totalBytes) {
                        loadingView.setProgress(R.string.download_downloading,
                                (float) ((double) bytesRead / (double) totalBytes));
                    }

                    @Override
                    protected void onSuccess(final CacheManager.ReadableCacheFile cacheFile, long timestamp,
                            UUID session, boolean fromCache, final String mimetype) {

                        if (mimetype == null || !Constants.Mime.isImage(mimetype)) {
                            revertToWeb();
                            return;
                        }

                        if (Constants.Mime.isImageGif(mimetype)) {

                            try {

                                gifThread = new GifDecoderThread(cacheFile.getInputStream(),
                                        new GifDecoderThread.OnGifLoadedListener() {

                                            public void onGifLoaded() {
                                                new Handler(Looper.getMainLooper()).post(new Runnable() {
                                                    public void run() {
                                                        imageView = new ImageView(context);
                                                        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
                                                        setContentView(imageView);
                                                        gifThread.setView(imageView);

                                                        imageView.setOnClickListener(new View.OnClickListener() {
                                                            public void onClick(View v) {
                                                                getSupportActivity().finish();
                                                            }
                                                        });
                                                    }
                                                });
                                            }

                                            public void onOutOfMemory() {
                                                General.quickToast(context, R.string.imageview_oom);
                                                revertToWeb();
                                            }

                                            public void onGifInvalid() {
                                                General.quickToast(context, R.string.imageview_invalid_gif);
                                                revertToWeb();
                                            }
                                        });

                                gifThread.start();

                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }

                        } else {

                            final Bitmap finalResult;

                            try {

                                final int maxTextureSize = 2048;
                                final Bitmap imageOrig = BitmapFactory.decodeStream(cacheFile.getInputStream());

                                if (imageOrig == null) {
                                    General.quickToast(context,
                                            "Couldn't load the image. Trying internal browser.");
                                    revertToWeb();
                                    return;
                                }

                                final int maxDim = Math.max(imageOrig.getWidth(), imageOrig.getHeight());

                                if (maxDim > maxTextureSize) {

                                    imageOrig.recycle();

                                    final double scaleFactorPowerOfTwo = Math
                                            .log((double) maxDim / (double) maxTextureSize) / Math.log(2);
                                    final int scaleFactor = (int) Math
                                            .round(Math.pow(2, Math.ceil(scaleFactorPowerOfTwo)));

                                    final BitmapFactory.Options options = new BitmapFactory.Options();
                                    options.inSampleSize = scaleFactor;
                                    finalResult = BitmapFactory.decodeStream(cacheFile.getInputStream(), null,
                                            options);
                                } else {
                                    finalResult = imageOrig;
                                }

                            } catch (IOException e) {
                                throw new RuntimeException(e);

                            } catch (OutOfMemoryError e) {
                                General.quickToast(context, "Out of memory. Trying internal browser.");
                                revertToWeb();
                                return;
                            }

                            new Handler(Looper.getMainLooper()).post(new Runnable() {
                                public void run() {
                                    imageView = new GestureImageView(context);
                                    imageView.setImageBitmap(finalResult);
                                    imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
                                    setContentView(imageView);

                                    imageView.setOnClickListener(new View.OnClickListener() {
                                        public void onClick(View v) {
                                            getSupportActivity().finish();
                                        }
                                    });
                                }
                            });
                        }
                    }
                });

        final RedditPost src_post = getArguments().getParcelable("post");
        final RedditPreparedPost post = src_post == null ? null
                : new RedditPreparedPost(context, CacheManager.getInstance(context), 0, src_post, -1, false,
                        new RedditSubreddit("/r/" + src_post.subreddit, src_post.subreddit, false), false, false,
                        false, RedditAccountManager.getInstance(context).getDefaultAccount());

        final FrameLayout outerFrame = new FrameLayout(context);
        outerFrame.addView(layout);

        if (post != null) {

            final SideToolbarOverlay toolbarOverlay = new SideToolbarOverlay(context);

            final BezelSwipeOverlay bezelOverlay = new BezelSwipeOverlay(context,
                    new BezelSwipeOverlay.BezelSwipeListener() {

                        public boolean onSwipe(BezelSwipeOverlay.SwipeEdge edge) {

                            toolbarOverlay.setContents(
                                    post.generateToolbar(context, ImageViewFragment.this, toolbarOverlay));
                            toolbarOverlay.show(edge == BezelSwipeOverlay.SwipeEdge.LEFT
                                    ? SideToolbarOverlay.SideToolbarPosition.LEFT
                                    : SideToolbarOverlay.SideToolbarPosition.RIGHT);
                            return true;
                        }

                        public boolean onTap() {

                            if (toolbarOverlay.isShown()) {
                                toolbarOverlay.hide();
                                return true;
                            }

                            return false;
                        }
                    });

            outerFrame.addView(bezelOverlay);
            outerFrame.addView(toolbarOverlay);

            bezelOverlay.getLayoutParams().width = android.widget.FrameLayout.LayoutParams.MATCH_PARENT;
            bezelOverlay.getLayoutParams().height = android.widget.FrameLayout.LayoutParams.MATCH_PARENT;

            toolbarOverlay.getLayoutParams().width = android.widget.FrameLayout.LayoutParams.MATCH_PARENT;
            toolbarOverlay.getLayoutParams().height = android.widget.FrameLayout.LayoutParams.MATCH_PARENT;

        }

        return outerFrame;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (gifThread != null)
            gifThread.stopPlaying();
        if (imageView != null && imageView instanceof GestureImageView) {
            ((GestureImageView) imageView).recycle();
        }
    }

    private void revertToWeb() {
        LinkHandler.onLinkClicked(getSupportActivity(), url.toString(), true);
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            public void run() {
                getSupportActivity().finish();
            }
        });
    }

    public void onPostSelected(final RedditPreparedPost post) {
        ((RedditPostView.PostSelectionListener) getSupportActivity()).onPostSelected(post);
    }

    public void onPostCommentsSelected(final RedditPreparedPost post) {
        ((RedditPostView.PostSelectionListener) getSupportActivity()).onPostCommentsSelected(post);
    }
}