/*
ApicAday - Everyday.. is different, your mood, your life.
Copyright (c) 2010
Oliver Selinger <oliver.selinger@autburst.com>,
Michael Greifeneder <michael.greifeneder@autburst.com>
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.autburst.picture;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CompoundButton.OnCheckedChangeListener;
public class MainActivity extends Activity implements OnItemClickListener,
OnCheckedChangeListener {
private static final String TAG = MainActivity.class.getSimpleName();
static final int DIALOG_CREATE_ALBUM_ID = 0;
static final int DIALOG_SHOW_ALBUM_ID = 1;
static final int DIALOG_CREATE_ALBUM_INPUT_ERROR = 2;
static final int DIALOG_ALBUM_NAME_ALREADY_EXIST = 3;
private ListView albumsList;
private ArrayAdapter<String> adapter;
private LayoutInflater inflater;
private ImageButton deleteButton;
private ImageButton openButton;
private List<Button> openAlbumButtons = new ArrayList<Button>();
private List<CheckBox> deleteAlbumCheckBoxes = new ArrayList<CheckBox>();
private LinearLayout deletionPanel;
private Button cancelDeletion;
private Button deleteCheckedAlbums;
private List<Integer> checkedAlbums = new ArrayList<Integer>();
// gui status for disabling or enabling the delete and open buttons
private boolean openButtonsVisible = false;
private boolean deleteCheckboxesVisible = false;
private MainActivityController controller;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "------ onCreate MainActivity ------");
setContentView(R.layout.main);
albumsList = (ListView) findViewById(R.id.albumList);
inflater = getLayoutInflater();
List<String> albumsAsList = Utilities.getAlbumsAsList();
adapter = new AlbumAdapter(inflater, this, R.layout.row, albumsAsList);
adapter.sort(Utilities.getAlbumNameComparator());
albumsList.setAdapter(adapter);
albumsList.setOnItemClickListener(this);
cancelDeletion = (Button) findViewById(R.id.cancelDeletion);
cancelDeletion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
hideDeletionPanelAndCB(MainActivityController.DELETE_BUTTON_PRESSED);
}
});
deleteCheckedAlbums = (Button) findViewById(R.id.deleteCheckedAlbums);
deleteCheckedAlbums.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
List<String> albums = Utilities.getAlbumsAsList();
Collections.sort(albums, Utilities.getAlbumNameComparator());
for (int i = 0; i < checkedAlbums.size(); i++) {
// get checked rows
int rowIndex = checkedAlbums.get(i);
String albumName = albums.get(rowIndex);
Log.d(TAG, "delete album: "
+ albumName
+ " at rowIndex: "
+ rowIndex
+ " decodedName: "
+ new String(Base64.decodeBase64(albumName
.getBytes())));
// delete albums
// remove files on sdcard
File album = Utilities.getAlbumDirectory(albumName);
File[] file = album.listFiles();
for (File file2 : file) {
file2.delete();
Log.d(TAG, "deleted file: " + file2.getName());
}
album.delete();
// remove shared preferences entry
SharedPreferences preferences = getSharedPreferences(
Utilities.PIC_STORE, 0);
Editor edit = preferences.edit();
String pref0 = albumName + ".id";
String pref1 = albumName + ".portrait";
String pref2 = albumName + ".videoId";
String pref3 = albumName + ".frameRate";
if (preferences.contains(pref0)) {
edit.remove(pref0);
Log.d(TAG, "deleted pref .id");
}
if (preferences.contains(pref1)) {
edit.remove(pref1);
Log.d(TAG, "deleted pref .portrait");
}
if (preferences.contains(pref2)) {
edit.remove(pref2);
Log.d(TAG, "deleted pref .videoId");
}
if (preferences.contains(pref3)) {
edit.remove(pref3);
Log.d(TAG, "deleted pref .frameRate");
}
edit.commit();
adapter.remove(albumName);
adapter.sort(Utilities.getAlbumNameComparator());
}
// hide deletion panel and checkboxes
hideDeletionPanelAndCB(MainActivityController.DELETED_ALBUMS);
// reload list
adapter.notifyDataSetChanged();
controller.transformGUI(MainActivityController.DELETED_ALBUMS);
}
});
deletionPanel = (LinearLayout) findViewById(R.id.deletionPanel);
deleteButton = (ImageButton) findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
controller
.transformGUI(MainActivityController.DELETE_BUTTON_PRESSED);
if (deleteCheckboxesVisible) {
// hide checkboxes
deleteCheckboxesVisible = false;
// make checkboxes invisible
for (CheckBox cbToDelete : deleteAlbumCheckBoxes) {
if (cbToDelete.getVisibility() == View.VISIBLE) {
Animation myFadeInAnimation = AnimationUtils
.loadAnimation(MainActivity.this,
R.anim.slight_left_cb);
cbToDelete.startAnimation(myFadeInAnimation);
cbToDelete.setVisibility(View.GONE);
if (cbToDelete.isChecked())
cbToDelete.setChecked(false);
Log.d(TAG, "set delete checkbox GONE");
}
}
} else {
// show checkboxes
deleteCheckboxesVisible = true;
for (CheckBox cbToDelete : deleteAlbumCheckBoxes) {
if (cbToDelete.getVisibility() == View.GONE) {
// checkboxes
Animation myFadeInAnimation = AnimationUtils
.loadAnimation(MainActivity.this,
R.anim.slight_right_cb);
cbToDelete.startAnimation(myFadeInAnimation);
cbToDelete.setVisibility(View.VISIBLE);
Log.d(TAG, "set delete checkbox visible");
}
}
}
}
});
openButton = (ImageButton) findViewById(R.id.openButton);
openButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (openButtonsVisible) {
// hide open Buttons
AnimationHelper.fadeInFromLeftToRight(MainActivity.this,
deleteButton);
// make buttons gone
for (Button openAlbum : openAlbumButtons) {
if (openAlbum.getVisibility() == View.VISIBLE) {
Animation myFadeInAnimation = AnimationUtils
.loadAnimation(MainActivity.this,
R.anim.slight_right);
openAlbum.startAnimation(myFadeInAnimation);
openAlbum.setVisibility(View.GONE);
}
}
openButtonsVisible = false;
} else {
// show open buttons
AnimationHelper.fadeOutToLeftSide(MainActivity.this,
deleteButton);
// make buttons visible
for (Button openAlbum : openAlbumButtons) {
if (openAlbum.getVisibility() == View.GONE) {
Animation myFadeInAnimation = AnimationUtils
.loadAnimation(MainActivity.this,
R.anim.slight_left);
openAlbum.startAnimation(myFadeInAnimation);
openAlbum.setVisibility(View.VISIBLE);
}
}
openButtonsVisible = true;
}
}
});
controller = new MainActivityController(this, openButton, deleteButton,
deletionPanel);
}
@Override
public void onRestart() {
super.onRestart();
Log.d(TAG, "------ onRestart MainActivity ------");
controller.reset();
}
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "------ onStart MainActivity ------");
controller.transformGUI(MainActivityController.STARTED);
}
private void hideDeletionPanelAndCB(int mainActivityCommand) {
deleteCheckboxesVisible = false;
controller.transformGUI(mainActivityCommand);
// make checkboxes invisible
for (CheckBox cbToDelete : deleteAlbumCheckBoxes) {
if (cbToDelete.getVisibility() == View.VISIBLE) {
Animation myFadeInAnimation = AnimationUtils.loadAnimation(
MainActivity.this, R.anim.slight_left_cb);
cbToDelete.startAnimation(myFadeInAnimation);
cbToDelete.setVisibility(View.GONE);
if (cbToDelete.isChecked())
cbToDelete.setChecked(false);
}
}
}
private class AlbumAdapter extends ArrayAdapter<String> {
private LayoutInflater inflater;
private List<String> albums;
public AlbumAdapter(LayoutInflater inflater, Context context,
int layout, List<String> albums) {
super(context, layout, albums);
this.inflater = inflater;
this.albums = albums;
openAlbumButtons.clear();
deleteAlbumCheckBoxes.clear();
super.setNotifyOnChange(false);
Log.d(TAG, "constructed AlbumAdapter");
}
@Override
public int getCount() {
Log.d(TAG, "getCount " + (albums.size() + 1));
return albums.size() + 1;
}
@Override
public void notifyDataSetChanged() {
Log.d(TAG, "notifyDataSetChanged");
openAlbumButtons.clear();
deleteAlbumCheckBoxes.clear();
super.notifyDataSetChanged();
super.setNotifyOnChange(false);
}
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
Log.d(TAG, "getView: " + position);
View row;
if (position == 0) {
if (null == convertView
|| convertView.getId() != R.id.createAlbumRow) {
row = inflater.inflate(R.layout.create_album_row, null);
} else
row = convertView;
Log.d(TAG, "LOAD create album row!");
} else {
final int albumListPosition = position - 1;
if (null == convertView
|| convertView.getId() == R.id.createAlbumRow) {
row = inflater.inflate(R.layout.row, null);
} else {
row = convertView;
}
int color = RowColorController.getColorId(position);
Log.d(TAG, "Color of row is: " + color + " position "
+ position);
row.setBackgroundResource(color);
ImageView firstImage = (ImageView) row
.findViewById(R.id.rowImage);
// get checkbox to delete an album
CheckBox cbToDelete = (CheckBox) row
.findViewById(R.id.cbToDelete);
cbToDelete.setTag(albumListPosition);
cbToDelete.setOnCheckedChangeListener(MainActivity.this);
addCheckBoxToDelete(cbToDelete);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 10;
options.inPurgeable = true;
File[] listFiles = Utilities.getAlbumDirectory(
this.getItem(albumListPosition)).listFiles();
if (listFiles != null && listFiles.length > 0) {
File selectedPic = listFiles[0];
Bitmap bm = null;
try {
bm = Bitmap.createBitmap(BitmapFactory.decodeFile(
selectedPic.getAbsolutePath(), options));
} catch (Exception e) {
Log
.d(
TAG,
"normal behavior; async image saver was still saving the image! So it cannot be displayed yet!");
}
firstImage.setImageBitmap(bm);
// button to open an album
Button openAlbum = (Button) row
.findViewById(R.id.openAlbum);
addOpenAlbumButton(openAlbum);
openAlbum.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// open gallery
Intent intent = new Intent(MainActivity.this,
GalleryActivity.class);
intent.putExtra("albumName",
getItem(albumListPosition));
startActivity(intent);
// set the openAlbum buttons to gone
for (Button openAlbum : openAlbumButtons)
openAlbum.setVisibility(View.GONE);
controller
.transformGUI(MainActivityController.OPEN_ALBUM);
openButtonsVisible = false;
}
});
} else
firstImage.setImageBitmap(null);
// set album name
TextView albumName = (TextView) row
.findViewById(R.id.rowAlbumName);
String decodedName = new String(Base64.decodeBase64(this
.getItem(albumListPosition).getBytes()));
albumName.setText(decodedName);
// set date of last taken picture in row
Date newestPic = null;
for (File file : listFiles) {
Date creationDate = new Date(file.lastModified());
if (newestPic == null || creationDate.after(newestPic))
newestPic = creationDate;
}
TextView albumLastPicture = (TextView) row
.findViewById(R.id.rowAlbumLastPicture);
Resources res = getResources();
if (newestPic != null) {
albumLastPicture.setText(String.format(res.getString(R.string.last_picture_from), DateFormat.format("dd.MM.yyyy kk:mm", newestPic)));
} else {
albumLastPicture.setText(String.format(res.getString(R.string.last_picture_from), ""));
}
Log.d(TAG, "LOAD ROW: " + decodedName + " encoded name: "
+ this.getItem(albumListPosition));
}
return row;
}
}
private void addCheckBoxToDelete(CheckBox cb) {
if (deleteAlbumCheckBoxes.contains(cb))
return;
else
deleteAlbumCheckBoxes.add(cb);
}
private void addOpenAlbumButton(Button button) {
if (openAlbumButtons.contains(button))
return;
else
openAlbumButtons.add(button);
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case Utilities.MSG_FINISHED_PIC_SAVING:
Log.d(TAG, "finished saving; notify dataset has changed!");
adapter.sort(Utilities.getAlbumNameComparator());
adapter.notifyDataSetChanged();
// if openbutton is disabled, because no album and pic existed
// before, -> enable it (now the first pic was taken)
controller.transformGUI(MainActivityController.PIC_SAVED);
break;
default:
break;
}
}
};
@Override
protected Dialog onCreateDialog(int id) {
final Dialog dialog;
final Context mContext = this;
switch (id) {
case DIALOG_CREATE_ALBUM_ID:
AlertDialog.Builder builder2 = new AlertDialog.Builder(this);
builder2.setTitle(R.string.new_gallery);
View view = getLayoutInflater()
.inflate(R.layout.create_album, null);
final EditText edit = (EditText) view
.findViewById(R.id.albumNameEditText);
final RadioGroup rg = (RadioGroup) view
.findViewById(R.id.formatRadioGroup);
builder2.setView(view);
builder2.setPositiveButton(R.string.save,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String name = edit.getText().toString();
Log.d(TAG, "Entered name: " + name);
// base64 encode string
String encodedName = new String(Base64
.encodeBase64(name.getBytes()));
Log.d(TAG, "base64 encoded name: " + encodedName);
// check if album with the same name already exist
if (Utilities.existsAlbumName(encodedName)) {
// fehler
showDialog(DIALOG_ALBUM_NAME_ALREADY_EXIST);
return;
}
// create folder
Utilities.getAlbumDirectory(encodedName);
// get format
int checkedRadioButtonId = rg
.getCheckedRadioButtonId();
final Boolean portrait;
if (checkedRadioButtonId == R.id.portraitRB)
portrait = true;
else
portrait = false;
SharedPreferences settings = getSharedPreferences(
Utilities.PIC_STORE, 0);
Editor edit2 = settings.edit();
edit2.putBoolean(encodedName + ".portrait",
portrait);
edit2.putFloat(encodedName + ".frameRate",
Utilities.MEDIUM_FRAME_RATE);
edit2.commit();
Log.d(TAG, "portrait: " + portrait
+ " settingsname: " + encodedName
+ ".portrait frameRate: "
+ Utilities.MEDIUM_FRAME_RATE);
// reset editView
edit.setText("");
// update table
adapter.add(encodedName);
adapter.sort(Utilities.getAlbumNameComparator());
adapter.notifyDataSetChanged();
dialog.dismiss();
controller
.transformGUI(MainActivityController.CREATED_ALBUM);
}
});
builder2.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
// reset editView
edit.setText("");
// showDialog(DIALOG_CREATE_ALBUM_ID);
}
});
AlertDialog create = builder2.create();
dialog = create;
break;
case DIALOG_ALBUM_NAME_ALREADY_EXIST:
AlertDialog.Builder builder3 = new AlertDialog.Builder(this);
builder3.setTitle(R.string.warning);
builder3
.setMessage(R.string.gallery_exists);
builder3.setNegativeButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// dialog.dismiss();
showDialog(DIALOG_CREATE_ALBUM_ID);
}
});
dialog = builder3.create();
break;
default:
dialog = null;
}
return dialog;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.mainmenu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
if (arg2 == 0) {
// open create album dialog
showDialog(DIALOG_CREATE_ALBUM_ID);
} else {
int albumListPosition = arg2 - 1;
List<String> albums = Utilities.getAlbumsAsList();
Collections.sort(albums, Utilities.getAlbumNameComparator());
Intent intent = new Intent(this, CameraActivity.class);
intent.putExtra("albumName", albums.get(albumListPosition));
startActivityForResult(intent, 0);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// handler.handleMessage(Utilities.MSG_FINISHED_PIC_SAVING);
}
@Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
Integer index = (Integer) arg0.getTag();
if (arg1) {
checkedAlbums.add(index);
Log.d(TAG, "added cbToDelete: " + index + " to list");
} else {
checkedAlbums.remove(index);
Log.d(TAG, "removed cbToDelete: " + index + " from list");
}
}
}