org.mariotaku.gallery3d.app.ImageViewerGLActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.mariotaku.gallery3d.app.ImageViewerGLActivity.java

Source

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * 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 org.mariotaku.gallery3d.app;

import org.mariotaku.gallery3d.data.BitmapPool;
import org.mariotaku.gallery3d.data.DataManager;
import org.mariotaku.gallery3d.data.MediaItem;
import org.mariotaku.gallery3d.data.Path;
import org.mariotaku.gallery3d.ui.GLRoot;
import org.mariotaku.gallery3d.ui.GLRootView;
import org.mariotaku.gallery3d.ui.GLView;
import org.mariotaku.gallery3d.ui.PhotoView;
import org.mariotaku.gallery3d.ui.SynchronizedHandler;
import org.mariotaku.gallery3d.util.GalleryUtils;
import org.mariotaku.gallery3d.util.ThreadPool;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;

public final class ImageViewerGLActivity extends FragmentActivity implements Constants, View.OnClickListener,
        GalleryContext, PhotoView.Listener, OrientationManager.Listener {

    private static final String TAG = "Gallery";

    private GLRootView mGLRootView;

    private View mProgress;
    private View mControlButtons;

    protected static final int FLAG_HIDE_ACTION_BAR = 1;
    protected static final int FLAG_HIDE_STATUS_BAR = 2;

    protected Bundle mData;
    protected int mFlags;

    private GLView mContentPane;

    private static final int MSG_HIDE_BARS = 1;

    private static final int MSG_ON_FULL_SCREEN_CHANGED = 4;

    private static final int MSG_UPDATE_ACTION_BAR = 5;

    private static final int MSG_UNFREEZE_GLROOT = 6;

    private static final int MSG_WANT_BARS = 7;

    private static final int MSG_REFRESH_BOTTOM_CONTROLS = 8;

    private static final int MSG_ON_CAMERA_CENTER = 9;

    private static final int MSG_ON_PICTURE_CENTER = 10;

    private static final int MSG_REFRESH_IMAGE = 11;

    private static final int MSG_UPDATE_PHOTO_UI = 12;

    private static final int MSG_UPDATE_DEFERRED = 14;

    private static final int MSG_UPDATE_SHARE_URI = 15;

    private static final int HIDE_BARS_TIMEOUT = 3500;

    private static final int UNFREEZE_GLROOT_TIMEOUT = 250;

    public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";

    private PhotoView mPhotoView;
    private PhotoView.Model mModel;
    private Handler mHandler;
    private boolean mShowBars = true;
    private volatile boolean mActionBarAllowed = true;

    private boolean mIsMenuVisible;
    private MediaItem mCurrentPhoto = null;

    private final long mDeferUpdateUntil = Long.MAX_VALUE;
    private final GLView mRootPane = new GLView() {
        @Override
        protected void onLayout(final boolean changed, final int left, final int top, final int right,
                final int bottom) {
            mPhotoView.layout(0, 0, right - left, bottom - top);
        }
    };

    @Override
    public Context getAndroidContext() {
        return this;
    }

    @Override
    public DataManager getDataManager() {
        return ((IGalleryApplication) getApplication()).getDataManager();
    }

    public GLRoot getGLRoot() {
        return mGLRootView;
    }

    @Override
    public ThreadPool getThreadPool() {
        return ((IGalleryApplication) getApplication()).getThreadPool();
    }

    public void hideControls() {
        mControlButtons.setVisibility(View.GONE);
    }

    public void hideProgress() {
        mProgress.setVisibility(View.GONE);
    }

    @Override
    public void onActionBarAllowed(final boolean allowed) {
        mActionBarAllowed = allowed;
        mHandler.sendEmptyMessage(MSG_UPDATE_ACTION_BAR);
    }

    @Override
    public void onActionBarWanted() {
        mHandler.sendEmptyMessage(MSG_WANT_BARS);
    }

    @Override
    public void onClick(final View v) {
        switch (v.getId()) {
        case R.id.close: {
            finish();
            break;
        }
        case R.id.open_in_browser: {
            final Uri uri = getIntent().getData();
            if (uri == null)
                return;
            startActivity(new Intent(Intent.ACTION_VIEW, uri));
            break;
        }
        case R.id.share: {
            final Uri uri = getIntent().getData();
            if (uri == null) {
                break;
            }
            final Intent intent = new Intent(Intent.ACTION_SEND);
            if ("file".equals(uri.getScheme())) {
                intent.setType("image/*");
                intent.putExtra(Intent.EXTRA_STREAM, uri);
            } else {
                intent.setType("text/plain");
                intent.putExtra(Intent.EXTRA_TEXT, uri.toString());
            }
            startActivity(Intent.createChooser(intent, getString(R.string.share)));
            break;
        }
        }
    }

    @Override
    public void onContentChanged() {
        super.onContentChanged();
        mGLRootView = (GLRootView) findViewById(R.id.gl_root_view);
        mProgress = findViewById(R.id.progress);
        mControlButtons = findViewById(R.id.control_buttons);
    }

    @Override
    public void onCurrentImageUpdated() {
        getGLRoot().unfreeze();
    }

    public void onLoadFailed() {
        // TODO Auto-generated method stub
    }

    public void onLoadFinished() {
        hideProgress();
    }

    public void onLoadStart() {
        showProgress();
    }

    @Override
    public void onOrientationCompensationChanged() {
        getGLRoot().requestLayoutContentPane();
    }

    @Override
    public void onPictureCenter() {
        mPhotoView.setWantPictureCenterCallbacks(false);
        mHandler.removeMessages(MSG_ON_CAMERA_CENTER);
        mHandler.removeMessages(MSG_ON_PICTURE_CENTER);
        mHandler.sendEmptyMessage(MSG_ON_PICTURE_CENTER);
    }

    // //////////////////////////////////////////////////////////////////////////
    // Callbacks from PhotoView
    // //////////////////////////////////////////////////////////////////////////
    @Override
    public void onSingleTapUp(final int x, final int y) {
        if (mModel.getMediaItem() == null)
            return;
        toggleBars();
    }

    public void showControls() {
        mControlButtons.setVisibility(View.VISIBLE);
    }

    public void showProgress() {
        mProgress.setVisibility(View.VISIBLE);
    }

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.image_viewer_gl);

        if (savedInstanceState == null) {
            startViewAction(getIntent());
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mGLRootView.lockRenderThread();
        try {
            getGLRoot().setOrientationSource(null);

            // Remove all pending messages.
            mHandler.removeCallbacksAndMessages(null);
        } finally {
            mGLRootView.unlockRenderThread();
        }
    }

    @Override
    protected void onNewIntent(final Intent intent) {
        startViewAction(intent);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mGLRootView.onPause();
        mGLRootView.lockRenderThread();
        try {
            getGLRoot().unfreeze();
            mHandler.removeMessages(MSG_UNFREEZE_GLROOT);

            if (mModel != null) {
                mModel.pause();
            }
            mPhotoView.pause();
            mHandler.removeMessages(MSG_HIDE_BARS);
            mHandler.removeMessages(MSG_REFRESH_BOTTOM_CONTROLS);
        } finally {
            mGLRootView.unlockRenderThread();
        }
        clearBitmapPool(MediaItem.getThumbPool());

    }

    @Override
    protected void onResume() {
        super.onResume();
        mGLRootView.lockRenderThread();
        try {
            if (mModel == null) {
                finish();
                return;
            }
            getGLRoot().freeze();
            setContentPane(mRootPane);

            mModel.resume();
            mPhotoView.resume();
            if (!mShowBars) {
                hideControls();
            }
            mHandler.sendEmptyMessageDelayed(MSG_UNFREEZE_GLROOT, UNFREEZE_GLROOT_TIMEOUT);
        } finally {
            mGLRootView.unlockRenderThread();
        }
        mGLRootView.onResume();
    }

    @Override
    protected void onSaveInstanceState(final Bundle outState) {
        mGLRootView.lockRenderThread();
        try {
            super.onSaveInstanceState(outState);
        } finally {
            mGLRootView.unlockRenderThread();
        }
    }

    protected void setContentPane(final GLView content) {
        mContentPane = content;
        mContentPane.setBackgroundColor(GalleryUtils.intColorToFloatARGBArray(Color.BLACK));
        final GLRoot root = getGLRoot();
        root.setContentPane(mContentPane);
    }

    private boolean canShowBars() {
        // No bars if it's not allowed.
        if (!mActionBarAllowed)
            return false;
        return true;
    }

    private String getContentType(final Intent intent) {
        final String type = intent.getType();
        if (type != null)
            return type;

        final Uri uri = intent.getData();
        try {
            return getContentResolver().getType(uri);
        } catch (final Throwable t) {
            Log.w(TAG, "get type fail", t);
            return null;
        }
    }

    private void hideBars() {
        if (!mShowBars)
            return;
        mShowBars = false;
        hideControls();
        mHandler.removeMessages(MSG_HIDE_BARS);
    }

    private void refreshHidingMessage() {
        mHandler.removeMessages(MSG_HIDE_BARS);
        if (!mIsMenuVisible) {
            mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT);
        }
    }

    private void showBars() {
        if (mShowBars)
            return;
        mShowBars = true;
        showControls();
        refreshHidingMessage();
    }

    private void startViewAction(final Intent intent) {
        if (intent == null) {
            finish();
            return;
        }
        final Bundle data = new Bundle();
        final DataManager dm = getDataManager();
        final Uri uri = intent.getData();
        final String contentType = getContentType(intent);
        if (contentType == null) {
            // Toast.makeText(this, R.string.no_such_item,
            // Toast.LENGTH_LONG).show();
            // finish();
            // return;
        }
        if (uri == null) {
            finish();
        } else {
            final Path itemPath = dm.findPathByUri(uri, contentType);
            data.putString(KEY_MEDIA_ITEM_PATH, itemPath.toString());
            mData = data;

            mPhotoView = new PhotoView(this);
            mPhotoView.setListener(this);
            mRootPane.addComponent(mPhotoView);

            mHandler = new SynchronizedHandler(getGLRoot()) {
                @Override
                public void handleMessage(final Message message) {
                    switch (message.what) {
                    case MSG_HIDE_BARS: {
                        hideBars();
                        break;
                    }
                    case MSG_REFRESH_BOTTOM_CONTROLS: {
                        break;
                    }
                    case MSG_ON_FULL_SCREEN_CHANGED: {
                        break;
                    }
                    case MSG_UPDATE_ACTION_BAR: {
                        updateBars();
                        break;
                    }
                    case MSG_WANT_BARS: {
                        wantBars();
                        break;
                    }
                    case MSG_UNFREEZE_GLROOT: {
                        getGLRoot().unfreeze();
                        break;
                    }
                    case MSG_UPDATE_DEFERRED: {
                        final long nextUpdate = mDeferUpdateUntil - SystemClock.uptimeMillis();
                        if (nextUpdate <= 0) {
                            updateUIForCurrentPhoto();
                        } else {
                            mHandler.sendEmptyMessageDelayed(MSG_UPDATE_DEFERRED, nextUpdate);
                        }
                        break;
                    }
                    case MSG_ON_CAMERA_CENTER: {
                        boolean stayedOnCamera = false;
                        stayedOnCamera = true;

                        if (stayedOnCamera) {
                            if (null == null) {
                                /*
                                 * We got here by swiping from photo 1 to
                                 * the placeholder, so make it be the thing
                                 * that is in focus when the user presses
                                 * back from the camera app
                                 */
                            } else {
                                updateBars();
                                updateCurrentPhoto(mModel.getMediaItem());
                            }
                        }
                        break;
                    }
                    case MSG_ON_PICTURE_CENTER: {
                        break;
                    }
                    case MSG_REFRESH_IMAGE: {
                        final MediaItem photo = mCurrentPhoto;
                        mCurrentPhoto = null;
                        updateCurrentPhoto(photo);
                        break;
                    }
                    case MSG_UPDATE_PHOTO_UI: {
                        updateUIForCurrentPhoto();
                        break;
                    }
                    case MSG_UPDATE_SHARE_URI: {
                        if (mCurrentPhoto == message.obj) {
                            mCurrentPhoto.getContentUri();
                            createShareIntent(mCurrentPhoto);
                        }
                        break;
                    }
                    }
                }
            };

            // Get default media set by the URI
            final MediaItem mediaItem = getDataManager().getMediaItem(itemPath);
            mModel = new PhotoViewAdapter(this, mPhotoView, mediaItem);
            mPhotoView.setModel(mModel);
            updateCurrentPhoto(mediaItem);
        }
    }

    private void toggleBars() {
        if (mShowBars) {
            hideBars();
        } else {
            if (canShowBars()) {
                showBars();
            }
        }
    }

    private void updateBars() {
        if (!canShowBars()) {
            hideBars();
        }
    }

    private void updateCurrentPhoto(final MediaItem photo) {
        if (mCurrentPhoto == photo)
            return;
        mCurrentPhoto = photo;
        updateUIForCurrentPhoto();
    }

    private void updateUIForCurrentPhoto() {
        if (mCurrentPhoto == null)
            return;

        // If by swiping or deletion the user ends up on an action item
        // and zoomed in, zoom out so that the context of the action is
        // more clear
        if ((mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_ACTION) != 0) {
            mPhotoView.setWantPictureCenterCallbacks(true);
        }

    }

    private void wantBars() {
        if (canShowBars()) {
            showBars();
        }
    }

    private static void clearBitmapPool(final BitmapPool pool) {
        if (pool != null) {
            pool.clear();
        }
    }

    // TODO better mimetype
    private static Intent createShareIntent(final MediaItem mediaObject) {
        return new Intent(Intent.ACTION_SEND).setType("image/*")
                .putExtra(Intent.EXTRA_STREAM, mediaObject.getContentUri())
                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

}