package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.gcvote.GCVote; import cgeo.geocaching.gcvote.GCVoteRating; import cgeo.geocaching.location.Geopoint; import cgeo.geocaching.location.Units; import cgeo.geocaching.log.LoggingUI; import cgeo.geocaching.models.Geocache; import cgeo.geocaching.sensors.GeoData; import cgeo.geocaching.sensors.GeoDirHandler; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.storage.DataStore; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.utils.AndroidRxUtils; import cgeo.geocaching.utils.Log; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.app.DialogFragment; import android.support.v7.widget.PopupMenu; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import java.util.concurrent.Callable; import butterknife.ButterKnife; import io.reactivex.Maybe; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.functions.Consumer; public abstract class AbstractDialogFragment extends DialogFragment implements CacheMenuHandler.ActivityInterface, PopupMenu.OnMenuItemClickListener, MenuItem.OnMenuItemClickListener { protected Resources res = null; protected String geocode; protected CacheDetailsCreator details; private final CompositeDisposable resumeDisposables = new CompositeDisposable(); private TextView cacheDistance = null; protected static final String GEOCODE_ARG = "GEOCODE"; protected static final String WAYPOINT_ARG = "WAYPOINT"; protected Geocache cache; public static final int RESULT_CODE_SET_TARGET = Activity.RESULT_FIRST_USER; public static final int REQUEST_CODE_TARGET_INFO = 1; private final GeoDirHandler geoUpdate = new GeoDirHandler() { @Override public void updateGeoData(final GeoData geo) { try { if (cache != null && cache.getCoords() != null) { cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords()))); cacheDistance.bringToFront(); } onUpdateGeoData(geo); } catch (final RuntimeException e) { Log.w("Failed to update location", e); } } }; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); res = getResources(); setHasOptionsMenu(true); } protected void initCustomActionBar(final View v) { final ImageView defaultNavigationImageView = ButterKnife.findById(v, R.id.defaultNavigation); defaultNavigationImageView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(final View v) { startDefaultNavigation2(); return true; } }); defaultNavigationImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { navigateTo(); } }); final View setAsTargetView = v.findViewById(R.id.setAsTarget); final View setAsTargetSep = v.findViewById(R.id.setAsTargetSep); if (getActivity().getCallingActivity() != null) { setAsTargetView.setVisibility(View.VISIBLE); setAsTargetSep.setVisibility(View.VISIBLE); setAsTargetView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { setAsTarget(); } }); } else { setAsTargetView.setVisibility(View.GONE); setAsTargetSep.setVisibility(View.GONE); } final View overflowActionBar = v.findViewById(R.id.overflowActionBar); overflowActionBar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { showPopup(v); } }); } public final void setTitle(final CharSequence title) { final View view = getView(); assert view != null; final TextView titleview = ButterKnife.findById(view, R.id.actionbar_title); if (titleview != null) { titleview.setText(title); } } @Override public void onStart() { super.onStart(); geocode = getArguments().getString(GEOCODE_ARG); } protected void showPopup(final View view) { final android.widget.PopupMenu popupMenu = new android.widget.PopupMenu(getActivity(), view); CacheMenuHandler.addMenuItems(new MenuInflater(getActivity()), popupMenu.getMenu(), cache); popupMenu.setOnMenuItemClickListener( new android.widget.PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(final MenuItem item) { return AbstractDialogFragment.this.onMenuItemClick(item); } } ); popupMenu.show(); } protected void init() { cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); if (cache == null) { ((AbstractActivity) getActivity()).showToast(res.getString(R.string.err_detail_cache_find)); getActivity().finish(); return; } geocode = cache.getGeocode(); } @Override public void onResume() { super.onResume(); resumeDisposables.add(geoUpdate.start(GeoDirHandler.UPDATE_GEODATA)); init(); } @Override public void onPause() { resumeDisposables.clear(); super.onPause(); } private void acquireGCVote() { if (!Settings.isRatingWanted()) { return; } if (!cache.supportsGCVote()) { return; } AndroidRxUtils.bindActivity(getActivity(), Maybe.fromCallable(new Callable<GCVoteRating>() { @Override public GCVoteRating call() { return GCVote.getRating(cache.getGuid(), geocode); } })).subscribeOn(AndroidRxUtils.networkScheduler).subscribe(new Consumer<GCVoteRating>() { @Override public void accept(final GCVoteRating rating) { cache.setRating(rating.getRating()); cache.setVotes(rating.getVotes()); DataStore.saveChangedCache(cache); details.addRating(cache); } }); } protected final void addCacheDetails() { assert cache != null; // cache type final String cacheType = cache.getType().getL10n(); final String cacheSize = cache.showSize() ? " (" + cache.getSize().getL10n() + ")" : ""; details.add(R.string.cache_type, cacheType + cacheSize); details.add(R.string.cache_geocode, cache.getGeocode()); details.addCacheState(cache); cacheDistance = details.addDistance(cache, cacheDistance); details.addDifficulty(cache); details.addTerrain(cache); details.addEventDate(cache); // rating if (cache.getRating() > 0) { details.addRating(cache); } else { acquireGCVote(); } // favorite count details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×"); // more details final View view = getView(); assert view != null; final Button buttonMore = ButterKnife.findById(view, R.id.more_details); buttonMore.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View arg0) { CacheDetailActivity.startActivity(getActivity(), geocode); getActivity().finish(); } }); /* Only working combination as it seems */ registerForContextMenu(buttonMore); } public final void showToast(final String text) { ActivityMixin.showToast(getActivity(), text); } /** * @param geo * location */ protected void onUpdateGeoData(final GeoData geo) { // do nothing by default } /** * Set the current popup coordinates as new navigation target on map */ private void setAsTarget() { final Activity activity = getActivity(); final Intent result = new Intent(); result.putExtra(Intents.EXTRA_TARGET_INFO, getTargetInfo()); activity.setResult(RESULT_CODE_SET_TARGET, result); activity.finish(); } @Override public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); CacheMenuHandler.addMenuItems(inflater, menu, cache); } @Override public void onCreateContextMenu(final ContextMenu menu, final View v, final ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); CacheMenuHandler.addMenuItems(new MenuInflater(getActivity()), menu, cache); for (int i = 0; i < menu.size(); i++) { final MenuItem m = menu.getItem(i); m.setOnMenuItemClickListener(this); } } @Override public boolean onContextItemSelected(final MenuItem item) { return onOptionsItemSelected(item); } @Override public boolean onMenuItemClick(final MenuItem menuItem) { return onOptionsItemSelected(menuItem); } @Override public boolean onOptionsItemSelected(final MenuItem item) { if (CacheMenuHandler.onMenuItemSelected(item, this, cache)) { return true; } if (LoggingUI.onMenuItemSelected(item, getActivity(), cache, new DialogInterface.OnDismissListener() { @Override public void onDismiss(final DialogInterface dialog) { init(); } })) { return true; } return super.onOptionsItemSelected(item); } @Override public void onPrepareOptionsMenu(final Menu menu) { super.onPrepareOptionsMenu(menu); try { CacheMenuHandler.onPrepareOptionsMenu(menu, cache); LoggingUI.onPrepareOptionsMenu(menu, cache); } catch (final RuntimeException ignored) { // nothing } } protected abstract TargetInfo getTargetInfo(); protected abstract void startDefaultNavigation2(); @Override public void cachesAround() { final TargetInfo targetInfo = getTargetInfo(); if (targetInfo == null || targetInfo.coords == null) { showToast(res.getString(R.string.err_location_unknown)); return; } CacheListActivity.startActivityCoordinates((AbstractActivity) getActivity(), targetInfo.coords, cache != null ? cache.getName() : null); getActivity().finish(); } @Override public void onCancel(final DialogInterface dialog) { super.onCancel(dialog); getActivity().finish(); } public static class TargetInfo implements Parcelable { public final Geopoint coords; public final String geocode; public static final Parcelable.Creator<TargetInfo> CREATOR = new Parcelable.Creator<TargetInfo>() { @Override public TargetInfo createFromParcel(final Parcel in) { return new TargetInfo(in); } @Override public TargetInfo[] newArray(final int size) { return new TargetInfo[size]; } }; TargetInfo(final Geopoint coords, final String geocode) { this.coords = coords; this.geocode = geocode; } public TargetInfo(final Parcel in) { this.coords = in.readParcelable(Geopoint.class.getClassLoader()); this.geocode = in.readString(); } @Override public void writeToParcel(final Parcel dest, final int flags) { dest.writeParcelable(coords, PARCELABLE_WRITE_RETURN_VALUE); dest.writeString(geocode); } @Override public int describeContents() { return 0; } } }