/*
* #%L
* Wheelmap - App
* %%
* Copyright (C) 2011 - 2012 Michal Harakal - Michael Kroez - Sozialhelden e.V.
* %%
* Wheelmap App based on the Wheelmap Service by Sozialhelden e.V.
*
* 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.
* #L%
*/
package org.wheelmap.android.activity;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.Animator.AnimatorListener;
import com.nineoldandroids.animation.ObjectAnimator;
import org.mapsforge.android.maps.GeoPoint;
import org.wheelmap.android.activity.listeners.Progress;
import org.wheelmap.android.activity.profile.ProfileActivity;
import org.wheelmap.android.analytics.AnalyticsTrackingManager;
import org.wheelmap.android.app.WheelmapApp;
import org.wheelmap.android.fragment.CombinedWorkerFragment;
import org.wheelmap.android.fragment.DisplayFragmentListener;
import org.wheelmap.android.fragment.ErrorDialogFragment;
import org.wheelmap.android.fragment.POIDetailFragment;
import org.wheelmap.android.fragment.POIDetailFragment.OnPOIDetailListener;
import org.wheelmap.android.fragment.POIsListFragment;
import org.wheelmap.android.fragment.POIsOsmdroidFragment;
import org.wheelmap.android.fragment.SearchDialogCombinedFragment;
import org.wheelmap.android.fragment.SearchDialogFragment;
import org.wheelmap.android.fragment.WheelchairAccessibilityStateFragment;
import org.wheelmap.android.fragment.WheelchairToiletStateFragment;
import org.wheelmap.android.fragment.WorkerFragmentListener;
import org.wheelmap.android.manager.MyLocationManager;
import org.wheelmap.android.model.Extra;
import org.wheelmap.android.model.MapModeType;
import org.wheelmap.android.model.PrepareDatabaseHelper;
import org.wheelmap.android.model.Request;
import org.wheelmap.android.model.WheelchairFilterState;
import org.wheelmap.android.model.Wheelmap.POIs;
import org.wheelmap.android.modules.AppProperties;
import org.wheelmap.android.modules.IAppProperties;
import org.wheelmap.android.modules.UserCredentials;
import org.wheelmap.android.online.R;
import org.wheelmap.android.popup.FilterWindow;
import org.wheelmap.android.service.RestServiceException;
import org.wheelmap.android.service.RestServiceHelper;
import org.wheelmap.android.utils.MapActivityUtils;
import org.wheelmap.android.utils.PressSelector;
import org.wheelmap.android.utils.SmoothInterpolator;
import android.animation.LayoutTransition;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.content.res.Configuration;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.Interpolator;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.LayoutParams;
import de.akquinet.android.androlog.Log;
import de.keyboardsurfer.android.widget.crouton.Crouton;
import de.keyboardsurfer.android.widget.crouton.Style;
import hotchemi.android.rate.AppRate;
public class MainMultiPaneActivity extends MapActivity implements
DisplayFragmentListener, WorkerFragmentListener, OnPOIDetailListener,
OnClickListener , Progress.Provider{
private static final String TAG = MainMultiPaneActivity.class
.getSimpleName();
IAppProperties appProperties;
private POIsListFragment mListFragment;
private POIsOsmdroidFragment mMapFragment;
private POIDetailFragment mDetailFragment;
private CombinedWorkerFragment mWorkerFragment;
private ViewGroup mMovableLayout;
private ImageButton mResizeButton;
private static final Interpolator SMOOTH_INTERPOLATOR = new SmoothInterpolator();
private static final long MOVABLE_ANIMATION_DURATION = 800;
private boolean mMovableVisible;
private boolean mMovableAnimationRunning;
Long poiIdSelected = Extra.ID_UNKNOWN;
private MapModeType mapModeType;
private WheelmapApp app;
private String address = null;
private boolean onRefresh = false;
/**
* used for testCases
*/
Progress.Listener mProgressListener;
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
requestWindowFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
appProperties = new AppProperties(WheelmapApp.getApp());
Log.d(TAG, "onCreate");
setProgressBarIndeterminate(true);
setSupportProgressBarIndeterminateVisibility(false);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setHomeButtonEnabled(false);
setContentView(R.layout.activity_multipane);
mMovableLayout = (ViewGroup) findViewById(R.id.movable_layout);
mResizeButton = (ImageButton) findViewById(R.id.button_movable_resize);
ViewGroup g = (ViewGroup) findViewById(R.id.layout_multi);
if (Build.VERSION.SDK_INT > 16) {
g.getLayoutTransition().disableTransitionType(LayoutTransition.APPEARING);
}
if (savedInstanceState != null) {
executeState(savedInstanceState);
} else {
executeDefaultInstanceState();
}
Bundle extras = getIntent().getExtras();
if (extras.containsKey(Extra.MAP_MODE_ENGAGE)) {
mapModeType = MapModeType.MAP_MODE_ENGAGE;
} else {
mapModeType = MapModeType.MAP_MODE_NORMAL;
}
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(false);
mResizeButton.setOnClickListener(this);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction t = fm.beginTransaction();
mWorkerFragment = (CombinedWorkerFragment) fm
.findFragmentByTag(CombinedWorkerFragment.TAG);
if (mWorkerFragment == null) {
mWorkerFragment = new CombinedWorkerFragment();
t.add(mWorkerFragment, CombinedWorkerFragment.TAG);
}
mListFragment = (POIsListFragment) fm
.findFragmentById(R.id.list_layout);
if (mListFragment == null) {
mListFragment = POIsListFragment.newInstance(false, true);
t.add(R.id.list_layout, mListFragment, POIsListFragment.TAG);
}
mMapFragment = (POIsOsmdroidFragment) fm
.findFragmentById(R.id.map_layout);
if (mMapFragment == null) {
mMapFragment = POIsOsmdroidFragment.newInstance(false, true);
t.add(R.id.map_layout, mMapFragment, POIsOsmdroidFragment.TAG);
}
mDetailFragment = (POIDetailFragment) fm
.findFragmentById(R.id.detail_layout);
if (mDetailFragment == null) {
mDetailFragment = POIDetailFragment.newInstance();
t.add(R.id.detail_layout, mDetailFragment);
}
t.commit();
WheelmapApp.checkForUpdates(this);
app = (WheelmapApp) this.getApplication();
String uri = null;
try {
address = app.getAddressString();
} catch (Exception ex) {}
if (address != null) {
showSearch();
}
// Show a dialog if meets conditions
AppRate.showRateDialogIfMeetsConditions(this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "onNewIntent");
setIntent(intent);
}
@Override
protected void onResume() {
super.onResume();
if (getIntent() != null) {
executeIntent(getIntent());
setIntent(null);
}
WheelmapApp.checkForCrashes(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
private void executeIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (extras == null) {
return;
}
executeState(extras);
}
private void executeState(Bundle state) {
mMovableVisible = state.getBoolean(Extra.MOVABLE_VISIBLE);
if (!mMovableVisible) {
setMovableGone();
}
}
private void executeDefaultInstanceState() {
setMovableGone();
AnalyticsTrackingManager.trackScreen(AnalyticsTrackingManager.TrackableScreensName.MAPSCREEN);
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
AnalyticsTrackingManager.trackScreen(AnalyticsTrackingManager.TrackableScreensName.NEARBYSCREEN);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(Extra.MOVABLE_VISIBLE, mMovableVisible);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
ActionBar bar = getSupportActionBar();
if(bar == null){
return true;
}
LayoutInflater inflater = LayoutInflater.from(this);
View customView = inflater.inflate(R.layout.actionbar_tablet,
null);
bar.setCustomView(customView, new ActionBar.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
Gravity.CENTER_VERTICAL | Gravity.END));
boolean isPortraitMode = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (isPortraitMode) {
ImageView addItem = (ImageView) customView.findViewById(R.id.menu_new_poi);
addItem.setVisibility(View.VISIBLE);
OnClickListener addClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
createNewPoi();
}
};
addItem.setOnClickListener(addClickListener);
LinearLayout l = (LinearLayout) findViewById(R.id.actionbar_bottom);
for (int i = 0; i < l.getChildCount(); i++) {
l.getChildAt(i).setOnTouchListener(new PressSelector());
}
bar.setDisplayShowCustomEnabled(true);
View v = findViewById(R.id.menu_filter);
MapActivityUtils.setAccessFilterOptionDrawable(this, null, v);
View filterWc = findViewById(R.id.menu_wc);
MapActivityUtils.setWcFilterOptionsDrawable(this, null, filterWc);
UserCredentials credentials = new UserCredentials(getApplicationContext());
ImageView image = (ImageView) findViewById(R.id.menu_login);
image.setImageResource(credentials.isLoggedIn()
? R.drawable.start_icon_logged_in
: R.drawable.start_icon_login);
} else {
MenuInflater inflaterMenu = getMenuInflater();
inflaterMenu.inflate(R.menu.ab_multi_activity, menu);
MenuItem item = menu.findItem(R.id.menu_filter);
MapActivityUtils.setAccessFilterOptionDrawable(this, item, null);
item = menu.findItem(R.id.menu_wc);
MapActivityUtils.setWcFilterOptionsDrawable(this, item, null);
}
if (mapModeType == MapModeType.MAP_MODE_ENGAGE) {
MenuItem itemFilterWheelChairs = menu.findItem(R.id.menu_filter);
itemFilterWheelChairs.setEnabled(false);
//TODO Disable it - doesn't work yet
}
ImageView listMapToggle = (ImageView)findViewById(R.id.switch_view);
if(listMapToggle != null) {
listMapToggle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
toggleMovableResize();
}
});
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean b = onOptionItemClicked(item.getItemId(), item.getActionView(), item);
return b ? b : super.onOptionsItemSelected(item);
}
public void onOptionItemBottomClicked(View v) {
onOptionItemClicked(v.getId(), v, null);
}
/*
* combined method to handle actionbar menu and custom bottom menu
*/
public boolean onOptionItemClicked(int id, View v, MenuItem item) {
switch (id) {
case R.id.menu_search:
if (mWorkerFragment.isSearchMode()) {
mWorkerFragment.setSearchMode(false);
mWorkerFragment.requestUpdate(null);
} else {
showSearch();
}
return true;
case R.id.menu_filter_kategorie:
showFilterCategories();
return true;
case R.id.menu_filter:
case R.id.menu_wc:
View anchor = v;
if (anchor == null) {
anchor = item.getActionView();
}
showFilterSettings(item, v, anchor);
return true;
case R.id.menu_about:
showInfo();
return true;
case R.id.menu_new_poi:
createNewPoi();
return true;
case android.R.id.home:
finish();
return true;
case R.id.menu_login:
showAccount();
return true;
case R.id.menu_news:
showNews();
return true;
default:
return false;
}
}
private void showNews() {
Intent intent = new Intent(this, WebViewNewsActivity.class);
startActivity(intent);
}
private void showAccount() {
Intent intent = new Intent(this, ProfileActivity.class);
startActivityForResult(intent, Request.REQUEST_CODE_LOGIN);
}
private void showSearch() {
FragmentManager fm = getSupportFragmentManager();
SearchDialogCombinedFragment searchDialog = SearchDialogCombinedFragment
.newInstance();
searchDialog.setTargetFragment(mWorkerFragment, 0);
searchDialog.show(fm, SearchDialogFragment.TAG);
}
private void showInfo() {
Intent intent = new Intent(this, InfoActivity.class);
startActivity(intent);
}
private void showFilterCategories() {
Intent intent = new Intent(this, FilterActivity.class);
intent.putExtra(Extra.FILTER_CATEGORIES, true);
startActivity(intent);
}
private void showFilterSettings(MenuItem menuItem, View menuView, View anchor) {
FilterWindow filter = new FilterWindow(this, null, menuView);
filter.showAsDropDown(anchor);
}
private long insertNewPoi() {
Location location = MyLocationManager.getLastLocation();
String name = getString(R.string.poi_new_default_name);
long id = PrepareDatabaseHelper.insertNew(getContentResolver(), name,
location.getLatitude(), location.getLongitude());
return id;
}
private void createNewPoi() {
long poiId = insertNewPoi();
Intent i = new Intent(this, POIDetailEditableActivity.class);
i.putExtra(Extra.POI_ID, poiId);
startActivity(i);
}
@Override
public void onError(RestServiceException e) {
if (e.isNetworkError()) {
String error = getString(R.string.error_network_failure);
try {
error = getString(e.getRessourceString());
} catch (Exception ex) {
}
Crouton.makeText(this, error, Style.ALERT).show();
return;
}
FragmentManager fm = getSupportFragmentManager();
ErrorDialogFragment errorDialog = ErrorDialogFragment.newInstance(e,
Extra.UNKNOWN);
if (errorDialog == null) {
return;
}
errorDialog.show(fm, ErrorDialogFragment.TAG);
}
@Override
public void onShowDetail(Fragment fragment, ContentValues values) {
long copyId = PrepareDatabaseHelper.createCopyFromContentValues(
getContentResolver(), values, true);
poiIdSelected = copyId;
if (!mMovableVisible) {
toggleMovableResize();
}
mDetailFragment.showDetail(poiIdSelected);
if (fragment == mListFragment) {
mMapFragment.markItem(values, true);
}
if (fragment == mMapFragment) {
mListFragment.markItem(values, false);
}
}
@Override
public void onRefreshing(boolean isRefreshing) {
Log.d(TAG, "onRefreshing isRefreshing = " + isRefreshing);
onRefresh = isRefreshing;
if (mProgressListener != null && isRefreshing) {
mProgressListener.onProgressChanged(true);
}
if(isRefreshing) {
if (getSupportActionBar() != null && getSupportActionBar().getCustomView() != null) {
View progress = getSupportActionBar().getCustomView().findViewById(R.id.progress);
if (progress.getVisibility() != View.VISIBLE) {
progress.setVisibility(View.VISIBLE);
checkProgressHide();
}
}
}
}
@Override
protected void onPause() {
super.onPause();
onRefresh = false;
}
private void checkProgressHide(){
if(!onRefresh) {
if (getSupportActionBar() != null && getSupportActionBar().getCustomView() != null) {
getSupportActionBar().getCustomView().findViewById(R.id.progress).setVisibility(View.INVISIBLE);
}
if (mProgressListener != null) {
mProgressListener.onProgressChanged(false);
}
} else {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
checkProgressHide();
}
}, 500);
}
}
@Override
public void onSearchModeChange(boolean isSearchMode) {
Log.d(TAG, "onSearchModeChange: showing custom view in actionbar");
getSupportActionBar().setDisplayShowCustomEnabled(true);
}
@Override
public void onEdit(long poiId, int focus) {
Intent intent = new Intent(this, POIDetailEditableActivity.class);
intent.putExtra(Extra.POI_ID, poiId);
intent.putExtra("Focus", focus);
startActivity(intent);
}
@Override
public void onEditWheelchairState(WheelchairFilterState wState) {
Intent intent = new Intent(this, WheelchairStateActivity.class);
intent.putExtra(Extra.WHEELCHAIR_STATE, wState.getId());
startActivityForResult(intent, Request.SELECT_WHEELCHAIRSTATE);
}
@Override
public void onEditWheelchairToiletState(WheelchairFilterState wState) {
Intent intent = new Intent(this, WheelchairStateActivity.class);
intent.putExtra(Extra.WHEELCHAIR_TOILET_STATE, wState.getId());
startActivityForResult(intent, Request.SELECT_WHEELCHAIRSTATE);
}
@Override
public void onShowLargeMapAt(GeoPoint point) {
// noop
}
@Override
public void dismissDetailView() {
toggleMovableResize();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult: requestCode = " + requestCode
+ " resultCode = " + resultCode);
if (requestCode == Request.SELECT_WHEELCHAIRSTATE && resultCode == RESULT_OK && data != null) {
if (data.hasExtra(WheelchairAccessibilityStateFragment.TAG)) {
WheelchairFilterState state = WheelchairFilterState
.valueOf(data.getIntExtra(WheelchairAccessibilityStateFragment.TAG, Extra.UNKNOWN));
if (state != null) {
updateDatabase(poiIdSelected, POIs.WHEELCHAIR, state);
}
} else if (data.hasExtra(WheelchairToiletStateFragment.TAG)) {
WheelchairFilterState state = WheelchairFilterState
.valueOf(data.getIntExtra(WheelchairToiletStateFragment.TAG, Extra.UNKNOWN));
if (state != null) {
updateDatabase(poiIdSelected, POIs.WHEELCHAIR_TOILET, state);
}
} else {
return;
}
Log.d(TAG, "starting RestServiceHelper.executeUpdateServer");
RestServiceHelper.executeUpdateServer(this, null);
}
if (requestCode == Request.REQUEST_CODE_LOGIN) {
ImageView image = (ImageView) findViewById(R.id.menu_login);
if (image != null) {
image.setImageResource(resultCode == RESULT_OK
? R.drawable.start_icon_logged_in
: R.drawable.start_icon_login);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void updateDatabase(long id, String poiColumnName, WheelchairFilterState state) {
if (id == Extra.ID_UNKNOWN || state == null) {
return;
}
Log.d(TAG,
"updating id = " + id + " state = "
+ state.asRequestParameter());
ContentValues values = new ContentValues();
values.put(poiColumnName, state.getId());
values.put(POIs.DIRTY, POIs.DIRTY_STATE);
PrepareDatabaseHelper.editCopy(getContentResolver(), id, values);
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.button_movable_resize:
toggleMovableResize();
}
}
private AnimatorListener mMovableAnimatorListener = new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mMapFragment.setHeightFull(!mMovableVisible);
if (mMovableVisible) {
mMovableLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void onAnimationEnd(Animator animation) {
if (!mMovableVisible) {
mMovableLayout.setVisibility(View.GONE);
}
mMovableAnimationRunning = false;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
};
private void setCollapseButtonImage(boolean toCollapse) {
int buttonDrawableRes;
if (toCollapse) {
buttonDrawableRes = R.drawable.ic_detail_collapse;
} else {
buttonDrawableRes = R.drawable.ic_detail_expand;
}
mResizeButton.setImageResource(buttonDrawableRes);
}
private void setMovableGone() {
mMovableVisible = false;
Log.d(TAG, "setMovableGone height = " + (-mMovableLayout.getHeight()));
mMovableLayout.setVisibility(View.INVISIBLE);
}
private void toggleMovableResize() {
if (mMovableAnimationRunning) {
return;
}
mMovableAnimationRunning = true;
setCollapseButtonImage(!mMovableVisible);
boolean land = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
String change = land ? "translationX" : "translationY";
float startValue;
float endValue;
if (mMovableVisible) {
startValue = 0.0f;
if (land) {
endValue = -mMovableLayout.getWidth();
} else {
endValue = -mMovableLayout.getHeight();
}
mMovableVisible = false;
} else {
if (land) {
startValue = -mMovableLayout.getWidth();
} else {
startValue = -mMovableLayout.getHeight();
AnalyticsTrackingManager.trackScreen(AnalyticsTrackingManager.TrackableScreensName.NEARBYSCREEN);
}
endValue = 0.0f;
mMovableVisible = true;
}
ObjectAnimator anim = ObjectAnimator.ofFloat(mMovableLayout,
change, startValue, endValue);
anim.setInterpolator(SMOOTH_INTERPOLATOR);
anim.setDuration(MOVABLE_ANIMATION_DURATION);
anim.addListener(mMovableAnimatorListener);
anim.start();
}
@Override
public void onRefreshEnabled(boolean refreshEnabled) {
}
@Override
public void refreshRegisterList(ListView listView) {
}
@Override
public void onBackPressed() {
WheelmapApp app = (WheelmapApp) this.getApplicationContext();
if (app.isSaved()) {
app.setSaved(false);
mWorkerFragment.setSearchMode(false);
mWorkerFragment.requestUpdate(null);
} else {
if (mMovableVisible && !mMovableAnimationRunning) {
toggleMovableResize();
return;
}
super.onBackPressed();
}
}
@Override
public void addProgressListener(Progress.Listener listener) {
mProgressListener = listener;
}
}