package com.poi.poiandroid;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import net.pbdavey.awt.Graphics2D;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.usermodel.SlideShow;
import and.awt.Dimension;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private ViewPager mViewPager;
private PagerAdapter mPagerAdapter;
private GestureDetector mGestureDetector;
private ScaleGestureDetector mScaleGestureDetector;
private boolean mPaused;
private boolean mOnScale = false;
private boolean mOnPagerScoll = false;
private int slideCount = 0;
private Slide[] slide;
private SlideShow ppt;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.activity_main);
setProgressBarVisibility(true);
setProgressBarIndeterminate(true);
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setPageMargin(10);
mViewPager.setPageMarginDrawable(new ColorDrawable(Color.BLACK));
mViewPager.setOffscreenPageLimit(1);
mViewPager.setOnPageChangeListener(mPageChangeListener);
setupOnTouchListeners(mViewPager);
String path = null;
Intent i = getIntent();
if (i != null) {
Uri uri = i.getData();
if (uri != null) {
Log.d(TAG, "uri.getPath: " + uri.getPath());
path = uri.getPath();
} else {
path = "/sdcard/socket.ppt";
File demoFile = new File(path);
if (!demoFile.exists()) {
InputStream inputStream = getResources().openRawResource(
R.raw.socket);
try {
FileOutputStream fos = new FileOutputStream(path);
byte[] buffer = new byte[512 * 1024];
int count;
while ((count = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, count);
}
fos.flush();
fos.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
try {
setTitle(path);
ppt2png(path);
} catch (IOException e) {
e.printStackTrace();
}
}
private void ppt2png(String path) throws IOException {
final long cur = System.currentTimeMillis();
ppt = new SlideShow(new File(path));
final Dimension pgsize = ppt.getPageSize();
slide = ppt.getSlides();
slideCount = slide.length;
Log.d("TIME", "new SlideShow: " + (System.currentTimeMillis() - cur));
final ExecutorService es = Executors.newSingleThreadExecutor();
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mViewPager == null) {
return;
}
switch (msg.what) {
case 0: {
Log.d(TAG, "draw finish");
View v = (View) msg.obj;
v.invalidate();
int position = msg.arg1;
if (position == mViewPager.getCurrentItem()) {
setProgress(10000);
}
}
break;
case 1: {
int progress = msg.arg1;
int max = msg.arg2;
int p = (int) ((float) progress / max * 10000);
int position = (Integer) msg.obj;
Log.d(TAG, "update progress: " + progress + ", max: " + max
+ ", p: " + p + ", position: " + position);
if (position == 1) {
setProgressBarIndeterminate(false);
}
if (position == mViewPager.getCurrentItem()) {
if (position != 0 && progress == 0) {
setProgressBarIndeterminate(false);
}
setProgress(p);
}
}
break;
default:
break;
}
}
};
mPagerAdapter = new PagerAdapter() {
@Override
public boolean isViewFromObject(View view, Object object) {
return view == ((ImageView) object);
}
@Override
public int getCount() {
return slide.length;
}
@Override
public void startUpdate(View container) {
}
@Override
public Object instantiateItem(View container, final int position) {
if (position == mViewPager.getCurrentItem()) {
setProgressBarIndeterminate(true);
}
final ImageViewTouch imageView = new ImageViewTouch(
MainActivity.this);
imageView.setLayoutParams(new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
imageView.setBackgroundColor(Color.BLACK);
imageView.setFocusableInTouchMode(true);
String title = slide[position].getTitle();
System.out.println("Rendering slide " + (position + 1)
+ (title == null ? "" : ": " + title));
System.out.println("pgsize.width: " + pgsize.getWidth()
+ ", pgsize.height: " + pgsize.getHeight());
Bitmap bmp = Bitmap.createBitmap((int) pgsize.getWidth(),
(int) pgsize.getHeight(), Config.RGB_565);
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setColor(android.graphics.Color.WHITE);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
canvas.drawPaint(paint);
final Graphics2D graphics2d = new Graphics2D(canvas);
final AtomicBoolean isCanceled = new AtomicBoolean(false);
// render
Runnable runnable = new Runnable() {
@Override
public void run() {
slide[position].draw(graphics2d, isCanceled, handler,
position);
handler.sendMessage(Message.obtain(handler, 0,
position, 0, imageView));
}
};
Future<?> task = es.submit(runnable);
imageView.setTag(task);
imageView.setIsCanceled(isCanceled);
imageView.setImageBitmapResetBase(bmp, true);
((ViewGroup) container).addView(imageView);
mCache.put(position, imageView);
return imageView;
}
@Override
public void destroyItem(View container, int position, Object object) {
ImageViewTouch view = (ImageViewTouch) object;
view.getCanceled().set(true);
Future<?> task = (Future<?>) view.getTag();
task.cancel(false);
((ViewGroup) container).removeView(view);
BitmapDrawable bitmapDrawable = (BitmapDrawable) view
.getDrawable();
if (!bitmapDrawable.getBitmap().isRecycled()) {
bitmapDrawable.getBitmap().recycle();
}
mCache.remove(position);
}
@Override
public void finishUpdate(View container) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
};
mViewPager.setAdapter(mPagerAdapter);
}
HashMap<Integer, View> mCache = new HashMap<Integer, View>();
public View getView(int position) {
return mCache.get(position);
}
Toast mPreToast;
ViewPager.OnPageChangeListener mPageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position, int prePosition) {
ImageViewTouch preImageView = (ImageViewTouch) getView(prePosition);
if (preImageView != null) {
preImageView.setImageBitmapResetBase(
preImageView.mBitmapDisplayed.getBitmap(), true);
}
Log.d(TAG, "onPageSelected: " + position);
if (mPreToast == null) {
mPreToast = Toast.makeText(MainActivity.this,
String.format("%d/%d", position + 1, slideCount),
Toast.LENGTH_SHORT);
} else {
mPreToast.cancel();
mPreToast.setText(String.format("%d/%d", position + 1,
slideCount));
mPreToast.setDuration(Toast.LENGTH_SHORT);
}
mPreToast.show();
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
mOnPagerScoll = true;
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
mOnPagerScoll = true;
} else if (state == ViewPager.SCROLL_STATE_SETTLING) {
mOnPagerScoll = false;
} else {
mOnPagerScoll = false;
}
}
};
public ImageViewTouch getCurrentImageView() {
return (ImageViewTouch) getView(mViewPager.getCurrentItem());
}
private class MyGestureListener extends
GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// Logger.d(TAG, "gesture onScroll");
if (mOnScale) {
return true;
}
if (mPaused) {
return false;
}
ImageViewTouch imageView = getCurrentImageView();
if (imageView != null) {
imageView.panBy(-distanceX, -distanceY);
// 超出边界效果去掉这个
imageView.center(true, true);
}
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
if (mPaused) {
return false;
}
ImageViewTouch imageView = getCurrentImageView();
// Switch between the original scale and 3x scale.
if (imageView.mBaseZoom < 1) {
if (imageView.getScale() > 2F) {
imageView.zoomTo(1f);
} else {
imageView.zoomToPoint(3f, e.getX(), e.getY());
}
} else {
if (imageView.getScale() > (imageView.mMinZoom + imageView.mMaxZoom) / 2f) {
imageView.zoomTo(imageView.mMinZoom);
} else {
imageView.zoomToPoint(imageView.mMaxZoom, e.getX(),
e.getY());
}
}
return true;
}
}
private class MyOnScaleGestureListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
float currentScale;
float currentMiddleX;
float currentMiddleY;
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
final ImageViewTouch imageView = getCurrentImageView();
Log.d(TAG, "currentScale: " + currentScale + ", maxZoom: "
+ imageView.mMaxZoom);
if (currentScale > imageView.mMaxZoom) {
imageView
.zoomToNoCenterWithAni(currentScale
/ imageView.mMaxZoom, 1, currentMiddleX,
currentMiddleY);
currentScale = imageView.mMaxZoom;
imageView.zoomToNoCenterValue(currentScale, currentMiddleX,
currentMiddleY);
} else if (currentScale < imageView.mMinZoom) {
// imageView.zoomToNoCenterWithAni(currentScale,
// imageView.mMinZoom, currentMiddleX, currentMiddleY);
currentScale = imageView.mMinZoom;
imageView.zoomToNoCenterValue(currentScale, currentMiddleX,
currentMiddleY);
} else {
imageView.zoomToNoCenter(currentScale, currentMiddleX,
currentMiddleY);
}
imageView.center(true, true);
// NOTE: 延迟修正缩放后可能移动问题
imageView.postDelayed(new Runnable() {
@Override
public void run() {
mOnScale = false;
}
}, 300);
// Logger.d(TAG, "gesture onScaleEnd");
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
// Logger.d(TAG, "gesture onScaleStart");
mOnScale = true;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector, float mx, float my) {
// Logger.d(TAG, "gesture onScale");
ImageViewTouch imageView = getCurrentImageView();
float ns = imageView.getScale() * detector.getScaleFactor();
currentScale = ns;
currentMiddleX = mx;
currentMiddleY = my;
if (detector.isInProgress()) {
imageView.zoomToNoCenter(ns, mx, my);
}
return true;
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent m) {
if (mPaused)
return true;
return super.dispatchTouchEvent(m);
}
private void setupOnTouchListeners(View rootView) {
mGestureDetector = new GestureDetector(this, new MyGestureListener(),
null, true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR_MR1) {
mScaleGestureDetector = new ScaleGestureDetector(this,
new MyOnScaleGestureListener());
}
OnTouchListener rootListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// NOTE: gestureDetector may handle onScroll..
if (!mOnScale) {
if (!mOnPagerScoll) {
try {
mGestureDetector.onTouchEvent(event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR_MR1) {
if (!mOnPagerScoll) {
mScaleGestureDetector.onTouchEvent(event);
}
}
ImageViewTouch imageView = getCurrentImageView();
if (!mOnScale && imageView != null
&& imageView.mBitmapDisplayed != null
&& imageView.mBitmapDisplayed.getBitmap() != null) {
Matrix m = imageView.getImageViewMatrix();
RectF rect = new RectF(0, 0, imageView.mBitmapDisplayed
.getBitmap().getWidth(), imageView.mBitmapDisplayed
.getBitmap().getHeight());
m.mapRect(rect);
// Logger.d(TAG, "rect.right: " + rect.right +
// ", rect.left: "
// + rect.left + ", imageView.getWidth(): "
// + imageView.getWidth());
// 图片超出屏幕范围后移动
if (!(rect.right > imageView.getWidth() + 0.1 && rect.left < -0.1)) {
try {
mViewPager.onTouchEvent(event);
} catch (Exception e) {
// why?
e.printStackTrace();
}
}
}
// We do not use the return value of
// mGestureDetector.onTouchEvent because we will not receive
// the "up" event if we return false for the "down" event.
return true;
}
};
rootView.setOnTouchListener(rootListener);
}
@Override
public void onStart() {
super.onStart();
mPaused = false;
}
@Override
public void onStop() {
super.onStop();
mPaused = true;
}
@Override
protected void onDestroy() {
super.onDestroy();
ImageViewTouch imageView = getCurrentImageView();
if (imageView != null) {
imageView.mBitmapDisplayed.recycle();
imageView.clear();
}
ppt = null;
slide = null;
mPagerAdapter = null;
mViewPager = null;
}
}