package roman10.imageviewer;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import roman10.zoomablegallery.ImageZoomView;
import roman10.zoomablegallery.MyGallery;
import roman10.zoomablegallery.PhotoAdapter;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.webkit.MimeTypeMap;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Toast;
//TODO: slideshow in random order
public class Viewer2 extends Activity implements OnGestureListener {
private MyGallery imgGallery;
public static PhotoAdapter imgAdapter;
// public static PhotoAdapter2 imgAdapter;
private ImageButton resetBtn;
private LinearLayout footbar;
private ImageButton rotateLeftBtn, rotateRightBtn, zoomInBtn, zoomOutBtn, slideShowBtn, shareBtn;
public static Viewer2 self; //not good programming style, but it's ok for single instance
private Context mContext;
private GestureDetector gestureDetector;
public static final String VIEW_TYPE = "TSVIEW_TYPE";
public static final int VIEW = 1;
public static final int SLIDESHOW = 2;
public static final int SESHARE = 3;
public static final int VIEW_SINGLE = 4;
private int mViewType = VIEW;
public static final String SHOW_STYLE = "TSSHOW_STYLE";
//0 for ordered list; 1: random
//we'll need to keep the screen on when showing images
private WakeLock mWakeLock;
private FinishListener mFinishListener;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.imageviewer_viewer2);
mContext = this.getApplicationContext();
self = this;
Intent l_intent = this.getIntent();
Bundle bundle = null;
if (l_intent!=null) {
bundle = l_intent.getExtras();
if (bundle != null) {
mViewType = bundle.getInt(Viewer2.VIEW_TYPE, Viewer2.VIEW);
}
}
if (mViewType == SLIDESHOW) {
if (bundle != null) {
mShowStyle = bundle.getInt(Viewer2.SHOW_STYLE, 0);
}
}
mFinishListener = new FinishListener(mContext);
mFinishListener.setOnFinishListener(new OnFinishListener() {
public void onReceiveFinish() {
exitApp();
}
});
imgGallery = (MyGallery) findViewById(R.id.imageviewer_viewer_img_gallery);
imgGallery.setVisibility(View.VISIBLE);
imgGallery.setSpacing(0);
imgGallery.setAnimationDuration(1000);
resetBtn = (ImageButton) this.findViewById(R.id.imageviewer_viewer_reset_btn);
//resetBtn.setBackgroundResource(R.drawable.btn_bg);
resetBtn.setVisibility(View.GONE);
resetBtn.setOnClickListener(new View.OnClickListener() {
//@Override
public void onClick(View v) {
imgGallery.resetCurrentPhoto();
resetBtn.setVisibility(View.GONE);
}
});
footbar = (LinearLayout) this.findViewById(R.id.image_viewer_footbar);
hideMenu();
rotateLeftBtn = (ImageButton) findViewById(R.id.bottom_btn1);
rotateLeftBtn.setBackgroundResource(R.drawable.btn_bg);
rotateLeftBtn.setImageResource(R.drawable.footbar_left);
rotateLeftBtn.setOnClickListener(new View.OnClickListener() {
//@Override
public void onClick(View v) {
int i = 0;
ImageZoomView izv = (ImageZoomView) imgGallery.getSelectedView();
for (; i < imageOriUpdateIndex.size(); ++i) {
if (imageOriUpdateIndex.get(i)==izv.getIndex()) {
i = -1;
break;
}
}
if (i !=-1 ) {
imageOriUpdateIndex.add(izv.getIndex());
}
int l_currOri = imageOri.get(izv.getIndex());
imageOri.set(izv.getIndex(), (l_currOri-1)%4);
Log.i("rotate-update", String.valueOf(imageOri.get(izv.getIndex())));
imgGallery.rotateLeft();
timedShowMenu();
}
});
rotateRightBtn = (ImageButton) findViewById(R.id.bottom_btn2);
rotateRightBtn.setBackgroundResource(R.drawable.btn_bg);
rotateRightBtn.setImageResource(R.drawable.footbar_right);
rotateRightBtn.setOnClickListener(new View.OnClickListener() {
//@Override
public void onClick(View v) {
int i = 0;
ImageZoomView izv = (ImageZoomView) imgGallery.getSelectedView();
for (; i < imageOriUpdateIndex.size(); ++i) {
if (imageOriUpdateIndex.get(i)==izv.getIndex()) {
i = -1;
break;
}
}
if (i !=-1 ) {
imageOriUpdateIndex.add(izv.getIndex());
}
int l_currOri = imageOri.get(izv.getIndex());
imageOri.set(izv.getIndex(), (l_currOri+1)%4);
Log.i("rotate-update", String.valueOf(imageOri.get(izv.getIndex())));
imgGallery.rotateRight();
timedShowMenu();
}
});
zoomInBtn = (ImageButton) findViewById(R.id.bottom_btn3);
zoomInBtn.setBackgroundResource(R.drawable.btn_bg);
zoomInBtn.setImageResource(R.drawable.footbar_zoomin);
zoomInBtn.setOnClickListener(new View.OnClickListener() {
//@Override
public void onClick(View v) {
imgGallery.zoomIn();
timedShowMenu();
}
});
zoomOutBtn = (ImageButton) findViewById(R.id.bottom_btn4);
zoomOutBtn.setBackgroundResource(R.drawable.btn_bg);
zoomOutBtn.setImageResource(R.drawable.footbar_zoomout);
zoomOutBtn.setOnClickListener(new View.OnClickListener() {
//@Override
public void onClick(View v) {
imgGallery.zoomOut();
timedShowMenu();
}
});
slideShowBtn = (ImageButton) findViewById(R.id.bottom_btn5);
slideShowBtn.setBackgroundResource(R.drawable.btn_bg);
slideShowBtn.setImageResource(R.drawable.footbar_slideshow);
slideShowBtn.setOnClickListener(new View.OnClickListener() {
//@Override
public void onClick(View v) {
int lCurStyle = ViewerConfigStatic.getShowStyle(getApplicationContext());
if (lCurStyle != 0) {
mShowStyle = lCurStyle;
slideShowSecrets();
} else {
//ask user to select slideshow style
Intent lIntent = new Intent();
if (lCurStyle == 0 || lCurStyle == 1) {
lCurStyle = 0;
} else if (lCurStyle == 2) {
lCurStyle = 1;
}
lIntent.putExtra(ShowStyleSelectionDialog.REQUEST_TYPE, ShowStyleSelectionDialog.REQUEST_TYPE_SHOW_STYLE);
lIntent.putExtra(ShowStyleSelectionDialog.REQUEST_DEFAULT_SET, 0);
lIntent.putExtra(ShowStyleSelectionDialog.REQUEST_DEFAULT_SEL, lCurStyle);
lIntent.setClass(getApplicationContext(), roman10reborn.topsecret.dialogs.ShowStyleSelectionDialog.class);
startActivityForResult(lIntent, REQUEST_SELECT_SHOW_STYLE);
//slideShowSecrets();
}
}
});
shareBtn = (ImageButton) findViewById(R.id.bottom_btn6);
shareBtn.setBackgroundResource(R.drawable.btn_bg);
shareBtn.setImageResource(R.drawable.footbar_share);
shareBtn.setOnClickListener(new View.OnClickListener() {
//@Override
public void onClick(View v) {
sharePhoto();
timedShowMenu();
}
});
gestureDetector = new GestureDetector(this);
refreshUI();
/*use a background service to load the pictures, orientation, and thumbnails*/
if ((mViewType == VIEW) || (mViewType == SLIDESHOW)) {
//start loading service, let it load pictures
startLoadService();
if (mViewType == SLIDESHOW) {
slideShowSecrets();
}
} else if (mViewType == VIEW_SINGLE) {
//if view a single file only, do not load files
}
}
@Override
public void onResume() {
super.onResume();
checkKeyguard();
if (mWakeLock != null) {
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
}
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Viewer");
mWakeLock.acquire();
//ask the backend service to stop cleaning
SettingsStatic.setAlarmCleanup(mContext, 0);
}
private static final int MENU_VIEWER_SETTINGS = 0;
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
menu.add(0, MENU_VIEWER_SETTINGS, 0, "Viewer Setting").setIcon(R.drawable.options_menu_viewer);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case MENU_VIEWER_SETTINGS:
Intent l_intent = new Intent();
l_intent.setClass(mContext, ViewerSettings.class);
startActivity(l_intent);
return true;
}
return false;
}
@Override
public void onPause() {
super.onPause();
if ((mViewType == VIEW) || (mViewType == SLIDESHOW)) {
startBackendService();
}
if (mWakeLock != null) {
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
mWakeLock = null;
}
}
@Override
public void onStop() {
super.onStop();
is_in_slideshow = false;
//photoCanBeCleaned = true;
//once the viewer is not visible, we destroy it so the backend can clean up
//the unencrypted picture
//comment these two lines out as we want the viewer to back once user has done share
//SettingsStatic.setAlarmCleanup(mContext, 1); //moved to onDestroy
//this.finish();
}
private void cleanUpSeShareFiles() {
if (!TopSecretCleanUpService.clean_phone_mem_in_progress) {
Intent l_intent = new Intent(mContext, TopSecretCleanUpService.class);
l_intent.putExtra(TopSecretCleanUpService.CLEAN_TYPE, TopSecretCleanUpService.CLEAN_TYPE_PHONE);
mContext.startService(l_intent);
}
}
private void unbindLists() {
//note that imgGallery.getCount() will return a huge number INT_MAX, cause freeze
if (imgAdapter!=null) {
for (int i = 0; i <= imgAdapter.getRealCount(); ++i) {
ImageZoomView lView = (ImageZoomView) imgGallery.getChildAt(i);
if (lView != null) {
lView.cleanUp();
lView = null;
}
}
System.gc();
}
}
@Override
public void onDestroy() {
//if the load service is still running, stop it
//stopLoadService();
super.onDestroy();
//let the service to stop itself properly from loading more pictures
if (ViewerLoadService.inProgress) {
ViewerLoadService.stopLoading = true;
}
unbindLists();
imgAdapter.setListItem(null);
//as phone memory is very limited, we clear it up asap
cleanUpSeShareFiles();
//allow the backend service to clean up
//SettingsStatic.setAlarmCleanup(mContext, 1);
}
private void checkKeyguard() {
// If the keyguard is being displayed, exit this activity. This returns
// the user to the activity list page, which will in turn return the user
// to the login page, requiring the user to enter his password again before
// get access again to his secrets.
KeyguardManager keyGuard = (KeyguardManager) getSystemService(
KEYGUARD_SERVICE);
if (keyGuard.inKeyguardRestrictedInputMode())
startExitApp();
}
@Override
public void onConfigurationChanged (Configuration newConfig) {
super.onConfigurationChanged(newConfig);
refreshUI();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//this block is no longer needed as we decided to show option menu instead of the footbar
// if (keyCode == KeyEvent.KEYCODE_MENU) {
// if (menu_shown == 1) {
// hideMenu();
// } else {
// timedShowMenu();
// }
// }
return super.onKeyDown(keyCode, event);
}
private void startExitApp() {
FinishEvent finishEvent = new FinishEvent(mContext, this.getApplicationContext());
finishEvent.fire();
}
private void exitApp() {
if (!TopSecretCleanUpService.clean_up_in_progress) {
Intent l_intent = new Intent(mContext, TopSecretCleanUpService.class);
l_intent.putExtra(TopSecretCleanUpService.CLEAN_TYPE, TopSecretCleanUpService.CLEAN_TYPE_ALL);
mContext.startService(l_intent);
}
this.finish();
}
private void refreshUI() {
imgAdapter = new PhotoAdapter(this);
// imgAdapter = new PhotoAdapter(this, imageList);
//imgAdapter.setNotifyOnChange(false);
imgAdapter.setListItem(imageList);
imgAdapter.setImageOriList(imageOri);
imgGallery.setAdapter(imgAdapter);
screenHeight = this.getWindowManager().getDefaultDisplay().getHeight();
int l_btnWidth = this.getWindowManager().getDefaultDisplay().getWidth()/6;
LinearLayout.LayoutParams shareParams = new LinearLayout.LayoutParams(l_btnWidth, LinearLayout.LayoutParams.FILL_PARENT);
rotateLeftBtn.setLayoutParams(shareParams);
rotateRightBtn.setLayoutParams(shareParams);
zoomInBtn.setLayoutParams(shareParams);
zoomOutBtn.setLayoutParams(shareParams);
slideShowBtn.setLayoutParams(shareParams);
shareBtn.setLayoutParams(shareParams);
}
public static void staticRefreshUI() {
//update image data for the gallery
if (imgAdapter != null) {
//imgAdapter.notifyDataSetChanged();
// imgAdapter.insert(Viewer2.imageList.get(Viewer2.imageList.size()-1), Viewer2.imgAdapter.getCount());
}
}
public int dpToPixels(float dp) {
final float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
public static List<String> imageList = new ArrayList<String>();
public static List<Integer> imageOri = new ArrayList<Integer>();
public static List<Integer> imageOriUpdateIndex = new ArrayList<Integer>();
private Handler displayHandler;
boolean mEnableReset = false;
public void enableReset() {
mEnableReset = true;
displayHandler = new Handler();
try {
Runnable mEnableTask = new Runnable() {
public void run() {
if (mEnableReset==false) {
if (resetBtn.getVisibility() == View.GONE) {
//already dismissed, no need to show the animation
} else{
Animation hideBtnAnimation =
new AlphaAnimation(1F, 0F);
hideBtnAnimation.setDuration(1000);
resetBtn.startAnimation(hideBtnAnimation);
resetBtn.setVisibility(View.GONE);
}
displayHandler.removeCallbacks(this);
return;
}
if (mEnableReset == true) {
resetBtn.setVisibility(View.VISIBLE);
mEnableReset = false;
}
//show the reset button for 3 seconds
displayHandler.postDelayed(this, 3000);
}
};
displayHandler.removeCallbacks(mEnableTask);
displayHandler.postDelayed(mEnableTask, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
private int menu_shown = 0;
private void hideMenu() {
menu_shown = 0;
footbar.setVisibility(View.GONE);
}
private Handler mMenuHandler;
private boolean mEnableMenu;
private Runnable mEnableTask = new Runnable() {
public void run() {
if (mEnableMenu==false) {
if (menu_shown == 0) {
//already dismissed, no need to show the animation
} else {
Animation hideBtnAnimation =
new AlphaAnimation(1F, 0F);
hideBtnAnimation.setDuration(1000);
footbar.startAnimation(hideBtnAnimation);
footbar.setVisibility(View.GONE);
menu_shown = 0;
}
mMenuHandler.removeCallbacks(this);
return;
}
if (mEnableMenu == true) {
if (menu_shown == 1) {
//if menu is already shown
mEnableMenu = false;
} else {
footbar.setVisibility(View.VISIBLE);
mEnableMenu = false;
menu_shown = 1;
}
}
//show the reset button for 3 seconds
mMenuHandler.postDelayed(this, 3000);
}
};
private void timedShowMenu() {
mEnableMenu = true;
if (mMenuHandler == null) {
mMenuHandler = new Handler();
}
try {
mMenuHandler.removeCallbacks(mEnableTask);
mMenuHandler.postDelayed(mEnableTask, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
private void sharePhoto() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
ImageZoomView izv = (ImageZoomView) imgGallery.getSelectedView();
String l_ext = imageList.get(izv.getIndex()).substring(
imageList.get(izv.getIndex()).lastIndexOf(".")+1).toLowerCase();
intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension(l_ext));
Uri l_fileUri = Uri.fromFile(new File(imageList.get(izv.getIndex())));
intent.putExtra(Intent.EXTRA_STREAM, l_fileUri);
intent.putExtra("TSXQ", 0); //for TS to ignore this intent
try {
startActivity(Intent.createChooser(intent, "Send Photo"));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, "no program is found to share the photo!",
Toast.LENGTH_SHORT).show();
}
}
private static int slideshow_interval = 3;
private final Animation mHidePrevImageViewAnimation =
new AlphaAnimation(1F, 0F);
private final Animation mShowNextImageViewAnimation =
new AlphaAnimation(0F, 1F);
//slideshow
private static boolean is_in_slideshow = false;
private static Handler slide_show_handler;
private static int slideshow_ani_state = 0;
private int mShowStyle = 0;
private void slideShowSecrets() {
if (imageList.size()==0) {
Toast.makeText(mContext, "No Pictures for Slide Show!", Toast.LENGTH_SHORT).show();
return;
}
slideshow_interval = ViewerConfigStatic.getShowInterval(mContext);
is_in_slideshow = true;
//if it's in slideshow, hide the menu
hideMenu();
//slideshow_interval = ViewerConfigStatic.getShowInterval(mContext);
slide_show_handler = new Handler();
try {
Runnable mUpdatePictureTask = new Runnable() {
//@Override
public void run() {
if (is_in_slideshow==false) {
slide_show_handler.removeCallbacks(this);
return;
}
if (slideshow_ani_state == 0) {
Animation a = mHidePrevImageViewAnimation;
a.setDuration(1000);
imgGallery.startAnimation(a);
}
if (slideshow_ani_state==1) {
imgGallery.showNextPhoto(mShowStyle);
Animation a = mShowNextImageViewAnimation;
a.setDuration(1000);
imgGallery.startAnimation(a);
}
if (is_in_slideshow) {
if (slideshow_ani_state == 0) {
slideshow_ani_state = 1;
slide_show_handler.postDelayed(this, 1000);
} else if (slideshow_ani_state == 1) {
slideshow_ani_state = 0;
slide_show_handler.postDelayed(this, (slideshow_interval)*1000);
}
} else {
slide_show_handler.removeCallbacks(this);
}
}
};
slide_show_handler.removeCallbacks(mUpdatePictureTask);
slide_show_handler.postDelayed(mUpdatePictureTask, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
//@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
//@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}
//@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
//@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
return false;
}
//@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
//single tap area
private static int screenHeight;
private static final int TAP_AREA_UP = 1;
private static final int TAP_AREA_CENTER = 2;
private static final int TAP_AREA_DOWN = 3;
private static int tap_area = TAP_AREA_CENTER;
@Override
public boolean dispatchTouchEvent(MotionEvent me) {
if (is_in_slideshow) {
//if it's in slideshow, a single tap will stop the slideshow
is_in_slideshow = false;
Toast.makeText(mContext, "Slideshow stopped!", Toast.LENGTH_SHORT).show();
}
float y = me.getY();
if (y < screenHeight/5.0*1.0) {
tap_area = TAP_AREA_UP;
} else if (y > screenHeight/5.0*4.0) {
tap_area = TAP_AREA_DOWN;
} else {
tap_area = TAP_AREA_CENTER;
}
gestureDetector.onTouchEvent(me);
return super.dispatchTouchEvent(me);
}
//@Override
public boolean onSingleTapUp(MotionEvent e) {
if (menu_shown==0) {
if (tap_area == TAP_AREA_CENTER) {
timedShowMenu();
}
} else {
//if menu is shown already, only when the event occurs at center area
//will cause the menu to hide
if (tap_area == TAP_AREA_CENTER) {
hideMenu();
}
}
return false;
}
private static final int REQUEST_SELECT_SHOW_STYLE = 0;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode) {
case REQUEST_SELECT_SHOW_STYLE:
if (resultCode == RESULT_OK) {
Bundle bundle = intent.getExtras();
boolean lDef = false;
if (bundle != null) {
mShowStyle = bundle.getInt(ShowStyleSelectionDialog.RESPONSE_SHOW_STYLE, 0);
lDef = bundle.getBoolean(ShowStyleSelectionDialog.RESPONSE_SHOW_STYLE_DEF, true);
}
if (lDef) {
if (mShowStyle == 0) {
ViewerConfigStatic.setShowStyle(this.getApplicationContext(), 1);
} else if (mShowStyle == 1) {
ViewerConfigStatic.setShowStyle(this.getApplicationContext(), 2);
}
}
slideShowSecrets();
}
break;
}
}
/**
* The services control
*/
private void startBackendService() {
Intent l_intent = new Intent(mContext, ViewerBackendService.class);
startService(l_intent);
}
private void stopBackendService() {
Intent l_intent = new Intent(mContext, ViewerBackendService.class);
stopService(l_intent);
}
private void startLoadService() {
Intent l_intent = new Intent(mContext, ViewerLoadService.class);
startService(l_intent);
}
private void stopLoadService() {
Intent l_intent = new Intent(mContext, ViewerLoadService.class);
stopService(l_intent);
}
}