package edu.mit.mobile.android.locast.ver2.casts;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import android.R.attr;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.location.LocationListener;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.provider.MediaStore.MediaColumns;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v4_map.app.LoaderManager;
import android.support.v4_map.app.LoaderManager.LoaderCallbacks;
import android.support.v4_map.app.MapFragmentActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.stackoverflow.ArrayUtils;
import edu.mit.mobile.android.content.ProviderUtils;
import edu.mit.mobile.android.imagecache.ImageCache;
import edu.mit.mobile.android.imagecache.ImageLoaderAdapter;
import edu.mit.mobile.android.locast.accounts.AuthenticationService;
import edu.mit.mobile.android.locast.accounts.Authenticator;
import edu.mit.mobile.android.locast.data.Cast;
import edu.mit.mobile.android.locast.data.CastMedia;
import edu.mit.mobile.android.locast.data.Locatable;
import edu.mit.mobile.android.locast.data.MediaProvider;
import edu.mit.mobile.android.locast.data.TaggableItem;
import edu.mit.mobile.android.locast.maps.CastLocationOverlay;
import edu.mit.mobile.android.locast.ver2.R;
import edu.mit.mobile.android.locast.widget.TagList;
import edu.mit.mobile.android.locast.widget.TagList.OnTagListChangeListener;
import edu.mit.mobile.android.utils.ResourceUtils;
import edu.mit.mobile.android.widget.CheckableTabWidget;
public class CastEdit extends MapFragmentActivity implements OnClickListener,
OnTabChangeListener, LocationListener, LoaderCallbacks<Cursor> {
private static final String TAG = CastEdit.class.getSimpleName();
/////////////////////
// stateful
private Uri mCast;
private boolean mIsDraft = true;
private boolean mIsEditable = false;
private GeoPoint mLocation;
private boolean mRecenterMapOnCurrentLocation = true;
private boolean mFirstLoad = true;
// when creating media (on some devices), you need to first create the filename, save it, and then use it when the camera returns.
private Uri mCreateMediaUri;
/////////////////////
// stateless
// general
private Uri mCastBase; // the base URI that the cast will be inserted into
private TabHost mTabHost;
private EditText mTitleView;
private CheckableTabWidget mTabWidget;
// media
private ListView mCastMediaView;
private EditableCastMediaAdapter mCastMediaAdapter;
// location
private ImageButton mSetLocation;
private MapView mMapView;
private MapController mMapController;
private MyLocationOverlay mMyLocationOverlay;
private CastLocationOverlay mCastLocationOverlay;
// details
private EditText mDescriptionView;
private TagList mTags;
//////////////////////
// constants
private static final String
TAB_LOCATION = "location",
TAB_MEDIA = "media",
TAB_DETAILS = "details";
private static final int
REQUEST_NEW_PHOTO = 100,
REQUEST_NEW_VIDEO = 101,
REQUEST_PICK_MEDIA = 102;
private static final int
DIALOG_PICK_MEDIA = 200;
private static final int
LOADER_CAST = 300,
LOADER_CASTMEDIA = 301;
private static final String
RS_NS = "edu.mit.mobile.android.locast.",
RUNTIME_STATE_CAST_URI = RS_NS + "CAST_URI",
RUNTIME_STATE_FIRST_LOAD = RS_NS + "FIRST_LOAD",
RUNTIME_STATE_CURRENT_TAB = RS_NS + "CURRENT_TAB",
RUNTIME_STATE_IS_DRAFT = RS_NS + "IS_DRAFT",
RUNTIME_STATE_LOCATION = RS_NS + "LOCATION",
RUNTIME_STATE_CREATE_MEDIA_URI = RS_NS + "CREATE_MEDIA_URI";
private static final String[]
CAST_MEDIA_FROM = new String[]{CastMedia._TITLE, CastMedia._THUMB_LOCAL, CastMedia._THUMBNAIL},
CAST_MEDIA_PROJECTION = ArrayUtils.concat(new String[]{CastMedia._ID}, CAST_MEDIA_FROM);
private static final int[]
CAST_MEDIA_TO = new int[]{R.id.cast_media_title, R.id.media_thumbnail, R.id.media_thumbnail};
private static final int[]
STATE_ACTIVE_LOCATION_SET = new int[]{attr.state_active, attr.state_checked},
STATE_INACTIVE_LOCATION_SET = new int[]{attr.state_checked},
STATE_LOCATION_NOT_SET = new int[]{};
///////////////////////////////////////////////////////////
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cast_edit);
// configure tabs
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabWidget = (CheckableTabWidget) findViewById(android.R.id.tabs);
mTabHost.setup();
mTabHost.addTab(mTabHost
.newTabSpec(TAB_LOCATION)
.setIndicator(
getTabIndicator(R.layout.tab_indicator_left,
getString(R.string.tab_location),
R.drawable.ic_tab_location))
.setContent(R.id.cast_edit_location));
mTabHost.addTab(mTabHost
.newTabSpec(TAB_MEDIA)
.setIndicator(
getTabIndicator(R.layout.tab_indicator_middle,
getString(R.string.tab_media),
R.drawable.ic_tab_media))
.setContent(R.id.cast_edit_media));
mTabHost.addTab(mTabHost
.newTabSpec(TAB_DETAILS)
.setIndicator(
getTabIndicator(R.layout.tab_indicator_right,
getString(R.string.tab_details),
R.drawable.ic_tab_details))
.setContent(R.id.cast_edit_details));
mTabHost.setOnTabChangedListener(this);
// find the other widgets
mTitleView = (EditText) findViewById(R.id.cast_title);
// cast media
mCastMediaView = (ListView) findViewById(android.R.id.list);
mCastMediaView.setEmptyView(findViewById(android.R.id.empty));
mCastMediaView.setItemsCanFocus(true);
mCastMediaAdapter = new EditableCastMediaAdapter(this, R.layout.cast_media_editable, null, CAST_MEDIA_FROM, CAST_MEDIA_TO, new int[]{R.id.media_thumbnail}, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
mCastMediaAdapter.addOnClickListener(R.id.remove, new OnClickListener() {
@Override
public void onClick(View v) {
final CastMediaAdapter adapter = (CastMediaAdapter) v.getTag(R.id.viewtag_item_adapter);
final int position = (Integer) v.getTag(R.id.viewtag_item_position);
final Uri castMediaUri = ContentUris.withAppendedId(Cast.getCastMediaUri(mCast), adapter.getItemId(position));
getContentResolver().delete(castMediaUri, null, null);
}
});
/*
* XXX doesn't work.
*
* mCastMediaAdapter.addOnFocusChangeListener(R.id.cast_media_title, new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
final CastMediaAdapter adapter = (CastMediaAdapter) v.getTag(R.id.viewtag_item_adapter);
final int position = (Integer) v.getTag(R.id.viewtag_item_position);
final Uri castMediaUri = ContentUris.withAppendedId(Cast.getCastMediaUri(mCast), adapter.getItemId(position));
final ContentValues cv = new ContentValues();
cv.put(CastMedia._TITLE, ((EditText)v).getText().toString());
getContentResolver().update(castMediaUri, cv, null, null);
}
}
});*/
mCastMediaView.setOnItemClickListener(mCastMediaOnItemClickListener);
mCastMediaView.setAdapter(new ImageLoaderAdapter(this, mCastMediaAdapter,
ImageCache.getInstance(this),
new int[] { R.id.media_thumbnail }, 100, 100,
ImageLoaderAdapter.UNIT_DIP));
mDescriptionView = (EditText) findViewById(R.id.description);
mDescriptionView.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {}
@Override
public void afterTextChanged(Editable s) {
updateDetailsTab();
}
});
mTags = (TagList) findViewById(R.id.tags);
mTags.setOnTagListChangeListener(new OnTagListChangeListener() {
@Override
public void onTagListChange(TagList v) {
updateDetailsTab();
}
});
////////////////
// initialize map
mSetLocation = (ImageButton) findViewById(R.id.set_current_location);
mMapView = (MapView) findViewById(R.id.map);
mMapController = mMapView.getController();
mMapController.setZoom(7);
mMapView.setBuiltInZoomControls(true);
mCastLocationOverlay = new CastLocationOverlay(this);
mMyLocationOverlay = new MyLocationOverlay(this, mMapView);
//mMyLocationOverlay.setDrawAccuracyEnabled(true);
final List<Overlay> overlays = mMapView.getOverlays();
overlays.add(mMyLocationOverlay);
overlays.add(mCastLocationOverlay);
// hook in buttons
findViewById(R.id.save).setOnClickListener(this);
mSetLocation.setOnClickListener(this);
findViewById(R.id.center_on_current_location).setOnClickListener(this);
findViewById(R.id.new_photo).setOnClickListener(this);
findViewById(R.id.new_video).setOnClickListener(this);
findViewById(R.id.pick_media).setOnClickListener(this);
//mIncrementalLocator = new IncrementalLocator(this);
/////////////
// process intents
final Intent intent = getIntent();
final String action = intent.getAction();
/////////////
// restore any existing state
final LoaderManager lm = getSupportLoaderManager();
if (savedInstanceState != null){
mCast = savedInstanceState.getParcelable(RUNTIME_STATE_CAST_URI);
mFirstLoad = savedInstanceState.getBoolean(RUNTIME_STATE_FIRST_LOAD, true);
mTabHost.setCurrentTab(savedInstanceState.getInt(RUNTIME_STATE_CURRENT_TAB, 0));
setLocation((GeoPoint)savedInstanceState.getParcelable(RUNTIME_STATE_LOCATION));
mIsDraft = savedInstanceState.getBoolean(RUNTIME_STATE_IS_DRAFT, true);
mCreateMediaUri = savedInstanceState.getParcelable(RUNTIME_STATE_CREATE_MEDIA_URI);
}
if (Intent.ACTION_EDIT.equals(action)){
if (mCast == null){
mCast = intent.getData();
}
mCastBase = ProviderUtils.removeLastPathSegment(mCast);
}else if (Intent.ACTION_INSERT.equals(action)){
setTitleFromIntent(intent);
mCastBase = intent.getData();
}
if (mCast != null){
lm.initLoader(LOADER_CAST, null, this);
}else{
// XXX put on thread
setEditable(true);
mCast = save(); // create a new, blank cast
}
lm.initLoader(LOADER_CASTMEDIA, null, this);
}
protected void updateDetailsTab() {
final boolean descriptionComplete = mDescriptionView.length() > 0;
final boolean tagsComplete = mTags.getTags().size() > 0;
mTabWidget.setTabChecked(2, descriptionComplete || tagsComplete);
}
@Override
protected void onPause() {
super.onPause();
if (mCast != null){
save();
}
stopUpdatingLocation();
mMyLocationOverlay.disableMyLocation();
}
@Override
protected void onResume() {
super.onResume();
if (TAB_LOCATION.equals(mTabHost.getCurrentTabTag())) {
startUpdatingLocation();
}
mMyLocationOverlay.enableMyLocation();
//getSupportLoaderManager().restartLoader(arg0, arg1, arg2)
}
@Override
public void onBackPressed() {
if (mLocation == null && mTitleView.getText().length() == 0 && mCastMediaAdapter.getCount() == 0 && mDescriptionView.getText().length() == 0){
Log.d(TAG, "cast "+mCast+" seems to be empty, so deleting it");
final ContentResolver cr = getContentResolver();
cr.delete(Cast.getCastMediaUri(mCast), null, null);
cr.delete(mCast, null, null);
mCast = null;
}
super.onBackPressed();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.save:
if (saveButton()){
// this isn't necessary, but could be helpful for integration
setResult(RESULT_OK, new Intent().setData(mCast));
finish();
}
break;
case R.id.center_on_current_location:
centerOnCurrentLocation();
break;
case R.id.set_current_location:
setCurrentLocation();
break;
case R.id.new_photo:{
final Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
mCreateMediaUri = createNewMedia("jpg");
i.putExtra(MediaStore.EXTRA_OUTPUT, mCreateMediaUri);
startActivityForResult(i, REQUEST_NEW_PHOTO);
}break;
case R.id.new_video:{
final Intent i = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
mCreateMediaUri = createNewMedia("mp4");
i.putExtra(MediaStore.EXTRA_OUTPUT, mCreateMediaUri);
startActivityForResult(i, REQUEST_NEW_VIDEO);
}break;
case R.id.pick_media:
showDialog(DIALOG_PICK_MEDIA);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_CANCELED){
Log.d(TAG, "media adding cancelled");
mCreateMediaUri = null;
return;
}
// Log.d(TAG, "onActivityResult: " + data);
// if (data == null || data.getData() == null){
// Toast.makeText(this, R.string.cast_edit_error_camera_did_not_return_image, Toast.LENGTH_LONG).show();
// return;
// }
switch(requestCode){
case REQUEST_NEW_PHOTO:{
addMedia(mCreateMediaUri);
mCreateMediaUri = null;
}break;
case REQUEST_NEW_VIDEO:{
addMedia(mCreateMediaUri);
mCreateMediaUri = null;
}break;
case REQUEST_PICK_MEDIA:{
final Uri media = data.getData();
if (media != null){
addMedia(media);
}
}
}
}
@Override
public void onTabChanged(String tabId) {
if (TAB_LOCATION.equals(tabId)) {
startUpdatingLocation();
} else {
stopUpdatingLocation();
}
}
@Override
public void onLocationChanged(Location location) {
if (mRecenterMapOnCurrentLocation) {
if (mMapView.getZoomLevel() < 10) {
mMapController.setZoom(15);
}
mMapController.animateTo(new GeoPoint((int)(location.getLatitude() * 1E6), (int)(location.getLongitude() * 1E6)));
}
}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
protected Dialog onCreateDialog(int id) {
switch (id){
case DIALOG_PICK_MEDIA:
return new AlertDialog.Builder(this)
.setTitle(R.string.cast_edit_select_media_type)
.setItems(R.array.cast_edit_pick, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final Intent i = new Intent();
i.setAction(Intent.ACTION_GET_CONTENT);
switch (which){
case 0:
i.setType("video/*");
break;
case 1:
i.setType("image/*");
break;
}
startActivityForResult(i, REQUEST_PICK_MEDIA);
}
}).create();
default:
return super.onCreateDialog(id);
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id){
case LOADER_CAST:
return new CursorLoader(this, mCast, Cast.PROJECTION, null, null, null);
case LOADER_CASTMEDIA:
return new CursorLoader(this, Cast.getCastMediaUri(mCast), CAST_MEDIA_PROJECTION, null, null, CastMedia._CREATED_DATE + " DESC");
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
switch (loader.getId()){
case LOADER_CAST:
// XXX hack. This is done as the cast is notified that it should reload when cast media is added. Obviously, it shouldn't.
if (mFirstLoad && c.moveToFirst()){
loadFromCursor(c);
}
break;
case LOADER_CASTMEDIA:
mCastMediaAdapter.swapCursor(c);
mTabWidget.setTabChecked(1, c.getCount() != 0);
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
ProviderUtils.dumpCursorToLog(c, CAST_MEDIA_PROJECTION);
}
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()){
case LOADER_CAST:
break;
case LOADER_CASTMEDIA:
mCastMediaAdapter.swapCursor(null);
break;
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(RUNTIME_STATE_CAST_URI, mCast);
outState.putBoolean(RUNTIME_STATE_FIRST_LOAD, mFirstLoad);
outState.putInt(RUNTIME_STATE_CURRENT_TAB, mTabHost.getCurrentTab());
if (mLocation instanceof GeoPoint){
// XXX outState.putParcelable(RUNTIME_STATE_LOCATION, (GeoPoint)mLocation);
}
outState.putBoolean(RUNTIME_STATE_IS_DRAFT, mIsDraft);
outState.putParcelable(RUNTIME_STATE_CREATE_MEDIA_URI, mCreateMediaUri);
}
// //////////////////////////////////////////////////////////////////////////
// non-handlers
private Uri createNewMedia(String extension){
final File outfile = new File("/sdcard/locast/", System.currentTimeMillis() + "." + extension);
outfile.getParentFile().mkdirs();
return Uri.fromFile(outfile);
}
private void loadFromCursor(Cursor c){
mTitleView.setText(c.getString(c.getColumnIndexOrThrow(Cast._TITLE)));
mDescriptionView.setText(c.getString(c.getColumnIndexOrThrow(Cast._DESCRIPTION)));
final Location l = Locatable.toLocation(c);
if (l != null){
mRecenterMapOnCurrentLocation = false;
setLocation(new GeoPoint((int)(l.getLatitude() * 1E6), (int)(l.getLongitude() * 1E6))); // XXX optimize
}
mTags.clearAllTags();
mTags.addTags(TaggableItem.getTags(getContentResolver(), mCast));
if (mFirstLoad){
mTabHost.setCurrentTab(mTabWidget.getNextUncheckedTab());
mFirstLoad = false;
}
final int draftCol = c.getColumnIndexOrThrow(Cast._DRAFT);
mIsDraft = !c.isNull(draftCol) && c.getInt(draftCol) != 0;
setEditable(Cast.canEdit(this, c));
updateDetailsTab();
}
private void setEditable(boolean isEditable){
mIsEditable = isEditable;
findViewById(R.id.cast_title).setEnabled(isEditable);
findViewById(R.id.save).setEnabled(isEditable);
// location
mSetLocation.setEnabled(isEditable);
// media
findViewById(R.id.new_photo).setEnabled(isEditable);
findViewById(R.id.new_video).setEnabled(isEditable);
findViewById(R.id.pick_media).setEnabled(isEditable);
// details
mTags.setEnabled(isEditable);
mDescriptionView.setEnabled(isEditable);
}
private void startUpdatingLocation() {
mMyLocationOverlay.enableMyLocation();
}
private void stopUpdatingLocation() {
mMyLocationOverlay.disableMyLocation();
}
private boolean mMapCenterIsLocation = false;
private void mapHasMoved(){
if (mMapCenterIsLocation){
if (mLocation != null){
if (mLocation instanceof GeoPoint){
// XXX mMapCenterIsLocation = mLocation.distanceTo(mMapView.getMapCenter()) <= 0.1;
if (!mMapCenterIsLocation){
mSetLocation.setImageState(STATE_INACTIVE_LOCATION_SET, false);
}else{
mSetLocation.setImageState(STATE_ACTIVE_LOCATION_SET, false);
}
}
}else{
mSetLocation.setImageState(STATE_LOCATION_NOT_SET, false);
mMapCenterIsLocation = false;
}
mSetLocation.postInvalidate();
}
// XXX this doesn't work as this function gets called even if the map is moved programatically
mRecenterMapOnCurrentLocation = false;
}
private View getTabIndicator(int layout, CharSequence title, int drawable) {
final LayoutInflater inflater = getLayoutInflater();
final TextView ind = (TextView) inflater.inflate(layout, mTabHost,
false);
ind.setCompoundDrawablesWithIntrinsicBounds(0, drawable, 0, 0);
ind.setText(title);
return ind;
}
private void setTitleFromIntent(Intent intent) {
final Uri data = intent.getData();
final String parentType = getContentResolver().getType(
ProviderUtils.removeLastPathSegment(data));
if (MediaProvider.TYPE_ITINERARY_ITEM.equals(parentType)) {
setTitle(ResourceUtils.getText(this, R.string.add_cast_to_x,
parentType));
} else if (MediaProvider.TYPE_CAST_DIR.equals(parentType)) {
setTitle(getString(R.string.edit_cast));
}
}
@Override
public void setTitle(int titleId) {
((TextView) findViewById(android.R.id.title)).setText(titleId);
super.setTitle(titleId);
}
@Override
public void setTitle(CharSequence title) {
((TextView) findViewById(android.R.id.title)).setText(title);
super.setTitle(title);
}
/**
* Reads from the UI and stateful variables, saving to a ContentValues. CastMedia and tags need to be saved separately.
*
* @return
*/
public ContentValues toContentValues() {
final ContentValues cv = new ContentValues();
cv.put(Cast._TITLE, mTitleView.getText().toString());
cv.put(Cast._DRAFT, mIsDraft);
cv.put(Cast._DESCRIPTION, mDescriptionView.getText().toString());
cv.put(Cast._MODIFIED_DATE, System.currentTimeMillis());
if(mLocation != null){
Locatable.toContentValues(cv, mLocation);
}
return cv;
}
public void addMedia(Uri content){
final Uri castMedia = Cast.getCastMediaUri(mCast);
final ContentValues cv = new ContentValues();
final long now = System.currentTimeMillis();
cv.put(CastMedia._MODIFIED_DATE, now);
cv.put(CastMedia._CREATED_DATE, now);
cv.put(CastMedia._TITLE, content.getLastPathSegment());
String mimeType = getContentResolver().getType(content);
if (mimeType == null){
mimeType = CastMedia.guessMimeTypeFromUrl(content.toString());
}
cv.put(CastMedia._MIME_TYPE, mimeType);
String mediaPath = null;
if ("content".equals(content.getScheme())){
final Cursor c = getContentResolver().query(content, new String[]{MediaColumns._ID, MediaColumns.DATA, MediaColumns.TITLE, Media.LATITUDE, Media.LONGITUDE}, null, null, null);
try {
if (c.moveToFirst()){
cv.put(CastMedia._TITLE, c.getString(c.getColumnIndexOrThrow(MediaColumns.TITLE)));
mediaPath = "file://" + c.getString(c.getColumnIndexOrThrow(MediaColumns.DATA));
// if the current location is null, infer it from the first media that's added.
if (mLocation == null){
final int latCol = c.getColumnIndex(Media.LATITUDE);
final int lonCol = c.getColumnIndex(Media.LONGITUDE);
final double lat = c.getDouble(latCol);
final double lon = c.getDouble(lonCol);
final boolean isInArmpit = lat == 0 && lon == 0; // Sorry, people in boats off the coast of Ghana, but you're an unfortunate edge case...
if (!c.isNull(latCol) && !c.isNull(lonCol) && ! isInArmpit){
setLocation(new GeoPoint((int)(c.getDouble(latCol) * 1E6), (int)(c.getDouble(lonCol) * 1E6)));
}
}
}
}finally{
c.close();
}
}else{
mediaPath = content.toString();
}
if (mediaPath == null){
Log.e(TAG, "couldn't add media from uri "+content);
return;
}
cv.put(CastMedia._THUMB_LOCAL, mediaPath);
cv.put(CastMedia._LOCAL_URI, mediaPath);
Log.d(TAG, "addMedia("+castMedia+", "+cv+")");
getContentResolver().insert(castMedia, cv);
}
private boolean validateEntries() {
if (mTitleView.getText().toString().trim().length() == 0) {
mTitleView.setError(getText(R.string.error_please_enter_a_title));
return false;
}
if (mLocation == null) {
// focus tab on location
return false;
}
return true;
}
/**
* request that the map be centered on the user's current location
*/
private void centerOnCurrentLocation() {
final Location curLoc = mMyLocationOverlay.getLastFix();
//final Location curLoc = mIncrementalLocator.getLastKnownLocation();
if (curLoc != null) {
if (mMapView.getZoomLevel() < 10) {
mMapController.setZoom(15);
}
mMapController.animateTo(new GeoPoint((int)(curLoc.getLatitude() * 1E6), (int)(curLoc.getLongitude() * 1E6)));
}else{
Toast.makeText(this, R.string.notice_finding_your_location, Toast.LENGTH_SHORT).show();
}
mRecenterMapOnCurrentLocation = true;
}
private void setLocation(GeoPoint location) {
mLocation = location;
final boolean hasLocation = mLocation != null;
mRecenterMapOnCurrentLocation = false;
mTabWidget.setTabChecked(0, hasLocation);
//mSetLocation.setImageState(STATE_ACTIVE_LOCATION_SET, false);
//mSetLocation.postInvalidate();
mMapCenterIsLocation = hasLocation;
if (hasLocation){
mCastLocationOverlay.setLocation(new GeoPoint(location.getLatitudeE6(), location.getLongitudeE6()));
mMapController.setCenter(location);
}
mMapView.postInvalidate();
}
private void setCurrentLocation() {
setLocation(mMapView.getMapCenter());
}
/**
* Validates the entries and marks the cast as non-draft if it passes validation.
*
* @return
*/
public boolean saveButton() {
boolean savedSuccessfully = false;
if (validateEntries()) {
mIsDraft = false;
mCast = save();
savedSuccessfully = mCast != null;
}
return savedSuccessfully;
}
/**
* Saves the current state of the cast entry (ignoring validation).
*
* @return the new URI of the cast
*/
private Uri save(){
if (!mIsEditable){
return mCast;
}
Uri newCast;
final ContentResolver cr = getContentResolver();
final ContentValues cv = toContentValues();
if (mCast == null){
// only add in credentials on inserts
final Account me = Authenticator.getFirstAccount(this);
final AccountManager am = AccountManager.get(this);
cv.put(Cast._AUTHOR, am.getUserData(me, AuthenticationService.USERDATA_DISPLAY_NAME));
cv.put(Cast._AUTHOR_URI, am.getUserData(me, AuthenticationService.USERDATA_USER_URI));
Log.d(TAG, "inserting "+cv+" into "+ mCastBase);
newCast = cr.insert(mCastBase, cv);
}else{
Log.d(TAG, "updating "+mCast+" with "+ cv);
if (cr.update(mCast, cv, null, null) != 1){
throw new RuntimeException("error updating cast " + mCast);
}
newCast = mCast;
}
Log.d(TAG, "cast URI is" + newCast);
if (newCast != null){
TaggableItem.putTags(cr, newCast, mTags.getTags());
}
if (mCast != null){
// XXX hack to fix possibly empty cast media. This is only called when there's existing data.
final ContentValues cvCastMediaDefaultTitle = new ContentValues();
cvCastMediaDefaultTitle.put(CastMedia._TITLE, "untitled");
cr.update(Cast.getCastMediaUri(mCast), cvCastMediaDefaultTitle, CastMedia._TITLE + " IS NULL", null);
}
return newCast;
}
private final OnItemClickListener mCastMediaOnItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapter, View v, int position,
long id) {
final Uri castMedia = ContentUris.withAppendedId(Cast.getCastMediaUri(mCast), id);
final Cursor c = (Cursor) adapter.getItemAtPosition(position);
CastMedia.showMedia(CastEdit.this, c, castMedia);
}
};
private class EditableCastMediaAdapter extends CastMediaAdapter{
private final HashMap<Integer, OnClickListener> mClickListeners = new HashMap<Integer, AdapterView.OnClickListener>();
private final HashMap<Integer, OnFocusChangeListener> mFocusChangeListeners = new HashMap<Integer, OnFocusChangeListener>();
public EditableCastMediaAdapter(Context context, int layout, Cursor c,
String[] from, int[] to, int[] imageIDs, int flags) {
super(context, layout, c, from, to, imageIDs, flags);
}
public void addOnClickListener(int viewID, OnClickListener onClickListener){
mClickListeners.put(viewID, onClickListener);
}
// TODO fix cast media title editing
public void addOnFocusChangeListener(int viewID, OnFocusChangeListener onFocusChangeListener){
mFocusChangeListeners.put(viewID, onFocusChangeListener);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View v = super.getView(position, convertView, parent);
for (final int viewID : mClickListeners.keySet()){
final View targetView = v.findViewById(viewID);
if (targetView == null){
continue;
}
targetView.setOnClickListener(mClickListeners.get(viewID));
targetView.setTag(R.id.viewtag_item_position, position);
targetView.setTag(R.id.viewtag_item_adapter, this);
}
// TODO inefficient, but works
for (final int viewID : mFocusChangeListeners.keySet()){
final View targetView = v.findViewById(viewID);
if (targetView == null){
continue;
}
targetView.setOnFocusChangeListener(mFocusChangeListeners.get(viewID));
targetView.setTag(R.id.viewtag_item_position, position);
targetView.setTag(R.id.viewtag_item_adapter, this);
}
return v;
}
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}