diff options
Diffstat (limited to 'main/src')
40 files changed, 817 insertions, 717 deletions
diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java index f46a5a6..5bf0f06 100644 --- a/main/src/cgeo/geocaching/AboutActivity.java +++ b/main/src/cgeo/geocaching/AboutActivity.java @@ -87,7 +87,6 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> @InjectView(R.id.website) protected TextView website; @InjectView(R.id.facebook) protected TextView facebook; @InjectView(R.id.twitter) protected TextView twitter; - @InjectView(R.id.nutshellmanual) protected TextView nutshellmanual; @InjectView(R.id.market) protected TextView market; @InjectView(R.id.faq) protected TextView faq; @@ -99,7 +98,6 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> setClickListener(website, "http://www.cgeo.org/"); setClickListener(facebook, "http://www.facebook.com/pages/cgeo/297269860090"); setClickListener(twitter, "http://twitter.com/android_gc"); - setClickListener(nutshellmanual, "http://manual.cgeo.org/"); setClickListener(faq, "http://faq.cgeo.org/"); market.setOnClickListener(new View.OnClickListener() { diff --git a/main/src/cgeo/geocaching/AbstractDialogFragment.java b/main/src/cgeo/geocaching/AbstractDialogFragment.java index 1c8d089..84a20ea 100644 --- a/main/src/cgeo/geocaching/AbstractDialogFragment.java +++ b/main/src/cgeo/geocaching/AbstractDialogFragment.java @@ -106,7 +106,6 @@ public abstract class AbstractDialogFragment extends DialogFragment implements C public void onStart() { super.onStart(); geocode = getArguments().getString(GEOCODE_ARG); - init(); } diff --git a/main/src/cgeo/geocaching/AbstractLoggingActivity.java b/main/src/cgeo/geocaching/AbstractLoggingActivity.java index 3b0f78d..bca5db1 100644 --- a/main/src/cgeo/geocaching/AbstractLoggingActivity.java +++ b/main/src/cgeo/geocaching/AbstractLoggingActivity.java @@ -7,13 +7,10 @@ import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCSmiliesProvider; import cgeo.geocaching.connector.gc.GCSmiliesProvider.Smiley; import cgeo.geocaching.connector.trackable.TravelBugConnector; -import cgeo.geocaching.settings.Settings; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate; -import org.apache.commons.lang3.StringUtils; - import android.view.Menu; import android.view.MenuItem; import android.view.SubMenu; @@ -26,7 +23,7 @@ public abstract class AbstractLoggingActivity extends AbstractActionBarActivity getMenuInflater().inflate(R.menu.abstract_logging_activity, menu); final SubMenu menuLog = menu.findItem(R.id.menu_templates).getSubMenu(); - for (final LogTemplate template : LogTemplateProvider.getTemplates()) { + for (final LogTemplate template : LogTemplateProvider.getTemplatesWithSignature()) { menuLog.add(0, template.getItemId(), 0, template.getResourceId()); } @@ -39,10 +36,7 @@ public abstract class AbstractLoggingActivity extends AbstractActionBarActivity } @Override - public boolean onPrepareOptionsMenu(Menu menu) { - final boolean signatureAvailable = StringUtils.isNotBlank(Settings.getSignature()); - menu.findItem(R.id.menu_signature).setVisible(signatureAvailable); - + public boolean onPrepareOptionsMenu(final Menu menu) { boolean smileyVisible = false; final Geocache cache = getLogContext().getCache(); if (cache != null && ConnectorFactory.getConnector(cache).equals(GCConnector.getInstance())) { @@ -59,14 +53,9 @@ public abstract class AbstractLoggingActivity extends AbstractActionBarActivity } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(final MenuItem item) { final int id = item.getItemId(); - if (id == R.id.menu_signature) { - insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), getLogContext()), true); - return true; - } - final LogTemplate template = LogTemplateProvider.getTemplate(id); if (template != null) { insertIntoLog(template.getValue(getLogContext()), true); @@ -79,12 +68,12 @@ public abstract class AbstractLoggingActivity extends AbstractActionBarActivity return true; } - return false; + return super.onOptionsItemSelected(item); } protected abstract LogContext getLogContext(); - protected void insertIntoLog(String newText, final boolean moveCursor) { + protected void insertIntoLog(final String newText, final boolean moveCursor) { final EditText log = (EditText) findViewById(R.id.log); ActivityMixin.insertAtPosition(log, newText, moveCursor); } diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 8672847..f5871e3 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -84,6 +84,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.FragmentManager; +import android.support.v7.view.ActionMode; import android.text.Editable; import android.text.Html; import android.text.Spannable; @@ -97,6 +98,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; @@ -336,49 +338,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc super.onCreateContextMenu(menu, view, info); final int viewId = view.getId(); switch (viewId) { - case R.id.value: // coordinates, gc-code, name - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - final CharSequence itemTitle = ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); - buildDetailsContextMenu(menu, clickedItemText, itemTitle, true); - break; - case R.id.shortdesc: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_description), false); - break; - case R.id.longdesc: - assert view instanceof TextView; - // combine short and long description - final String shortDesc = cache.getShortDescription(); - if (StringUtils.isBlank(shortDesc)) { - clickedItemText = ((TextView) view).getText(); - } else { - clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText(); - } - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_description), false); - break; - case R.id.personalnote: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_personal_note), true); - break; - case R.id.hint: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_hint), false); - break; - case R.id.log: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_logs), false); - break; - case R.id.date: // event date - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_event), true); - menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar()); - break; case R.id.waypoint: menu.setHeaderTitle(selectedWaypoint.getName() + " (" + res.getString(R.string.waypoint) + ")"); getMenuInflater().inflate(R.menu.waypoint_options, menu); @@ -405,9 +364,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public boolean onContextItemSelected(MenuItem item) { - if (onClipboardItemSelected(item, clickedItemText)) { - return true; - } switch (item.getItemId()) { // waypoints case R.id.menu_waypoint_edit: @@ -599,9 +555,9 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // action bar: title and icon if (StringUtils.isNotBlank(cache.getName())) { - getSupportActionBar().setTitle(cache.getName() + " (" + cache.getGeocode() + ')'); + setTitle(cache.getName() + " (" + cache.getGeocode() + ')'); } else { - getSupportActionBar().setTitle(cache.getGeocode()); + setTitle(cache.getGeocode()); } getSupportActionBar().setIcon(getResources().getDrawable(cache.getType().markerId)); @@ -913,10 +869,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc span.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - registerForContextMenu(details.add(R.string.cache_name, span)); + addContextMenu(details.add(R.string.cache_name, span)); details.add(R.string.cache_type, cache.getType().getL10n()); details.addSize(cache); - registerForContextMenu(details.add(R.string.cache_geocode, cache.getGeocode())); + addContextMenu(details.add(R.string.cache_geocode, cache.getGeocode())); details.addCacheState(cache); details.addDistance(cache, cacheDistanceView); @@ -950,7 +906,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // hidden or event date final TextView hiddenView = details.addHiddenDate(cache); if (hiddenView != null) { - registerForContextMenu(hiddenView); + addContextMenu(hiddenView); } // cache location @@ -962,7 +918,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (cache.getCoords() != null) { final TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString()); valueView.setOnClickListener(new CoordinatesFormatSwitcher(cache.getCoords())); - registerForContextMenu(valueView); + addContextMenu(valueView); } // cache attributes @@ -1422,7 +1378,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // cache personal note setPersonalNote(personalNoteView, cache.getPersonalNote()); personalNoteView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - registerForContextMenu(personalNoteView); + addContextMenu(personalNoteView); final Button personalNoteEdit = (Button) view.findViewById(R.id.edit_personalnote); personalNoteEdit.setOnClickListener(new View.OnClickListener() { @Override @@ -1473,7 +1429,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc hintView.setOnClickListener(new DecryptTextClickListener(hintView)); hintBoxView.setOnClickListener(new DecryptTextClickListener(hintView)); hintBoxView.setClickable(true); - registerForContextMenu(hintView); + addContextMenu(hintView); } else { hintView.setVisibility(View.GONE); hintView.setClickable(false); @@ -1643,7 +1599,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); fixTextColor(descriptionString); descriptionView.setVisibility(View.VISIBLE); - registerForContextMenu(descriptionView); + addContextMenu(descriptionView); } } @@ -1807,7 +1763,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } }); - registerForContextMenu(rowView); + addContextMenu(rowView); rowView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -1896,6 +1852,86 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc context.startActivity(cachesIntent); } + public void addContextMenu(final View view) { + view.setOnLongClickListener(new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + startSupportActionMode(new ActionMode.Callback() { + + @Override + public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { + switch (view.getId()) { + case R.id.value: // coordinates, gc-code, name + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + final CharSequence itemTitle = ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, itemTitle, true); + return true; + case R.id.shortdesc: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_description), false); + return true; + case R.id.longdesc: + assert view instanceof TextView; + // combine short and long description + final String shortDesc = cache.getShortDescription(); + if (StringUtils.isBlank(shortDesc)) { + clickedItemText = ((TextView) view).getText(); + } else { + clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText(); + } + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_description), false); + return true; + case R.id.personalnote: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_personal_note), true); + return true; + case R.id.hint: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_hint), false); + return true; + case R.id.log: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_logs), false); + return true; + case R.id.date: // event date + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_event), true); + menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar()); + return true; + } + return false; + } + + @Override + public void onDestroyActionMode(ActionMode actionMode) { + // do nothing + } + + @Override + public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { + actionMode.getMenuInflater().inflate(R.menu.details_context, menu); + + // Return true so that the action mode is shown + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { + return onClipboardItemSelected(actionMode, menuItem, clickedItemText); + } + }); + return false; + } + }); + } + public static void startActivityGuid(final Context context, final String guid, final String cacheName) { final Intent cacheIntent = new Intent(context, CacheDetailActivity.class); cacheIntent.putExtra(Intents.EXTRA_GUID, guid); diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java index 333dfb7..21ff113 100644 --- a/main/src/cgeo/geocaching/CacheListActivity.java +++ b/main/src/cgeo/geocaching/CacheListActivity.java @@ -85,13 +85,10 @@ import android.support.v7.app.ActionBar; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; @@ -260,14 +257,14 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } } - private static String getCacheNumberString(Resources res, int count) + static String getCacheNumberString(Resources res, int count) { return res.getQuantityString(R.plurals.cache_counts, count, count); } protected void updateTitle() { - getSupportActionBar().setTitle(title); + setTitle(title); final ArrayList<String> numbers = new ArrayList<String>(); if (adapter.isFiltered()) { @@ -446,68 +443,13 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } - static class CacheArrayAdapter extends ArrayAdapter<AbstractList> { - - static class ViewHolder { - TextView title; - TextView subtitle; - } - - private final Context mContext; - - public CacheArrayAdapter(Context context, int resource) { - super(context, resource); - mContext = context; - } - - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - return getCustomView(position, convertView, parent); - } - - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - return getCustomView(position, convertView, parent); - } - - public View getCustomView(final int position, final View convertView, final ViewGroup parent) { - - View resultView = convertView; - LayoutInflater inflater = - (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - - ViewHolder holder; - if (resultView == null) { - resultView = inflater.inflate(R.layout.cachelist_spinneritem, parent, false); - holder = new ViewHolder(); - holder.title = (TextView) resultView.findViewById(android.R.id.text1); - holder.subtitle = (TextView) resultView.findViewById(android.R.id.text2); - - resultView.setTag(holder); - } else { - holder = (ViewHolder) resultView.getTag(); - } - - AbstractList list = getItem(position); - holder.title.setText(list.getTitle()); - if (list.getCount() >= 0) { - holder.subtitle.setVisibility(View.VISIBLE); - holder.subtitle.setText(getCacheNumberString(mContext.getResources(),list.getCount())); - } else { - holder.subtitle.setVisibility(View.GONE); - } - - return resultView; - } - } - - CacheArrayAdapter mCacheListSpinnerAdapter; + /** + * Action bar spinner adapter. {@code null} for list types that don't allow switching (search results, ...). + */ + CacheListSpinnerAdapter mCacheListSpinnerAdapter; private void initActionBarSpinner() { - mCacheListSpinnerAdapter = new CacheArrayAdapter(this, R.layout.support_simple_spinner_dropdown_item); + mCacheListSpinnerAdapter = new CacheListSpinnerAdapter(this, R.layout.support_simple_spinner_dropdown_item); getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); getSupportActionBar().setDisplayShowTitleEnabled(false); getSupportActionBar().setListNavigationCallbacks(mCacheListSpinnerAdapter, new ActionBar.OnNavigationListener() { @@ -647,7 +589,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA setVisible(menu, R.id.menu_refresh_stored, !isEmpty && (isConcrete || type != CacheListType.OFFLINE)); setVisible(menu, R.id.menu_drop_caches, !isEmpty && isOffline); setVisible(menu, R.id.menu_drop_caches_and_list, isConcrete && !isEmpty && isOffline); - setVisible(menu, R.id.menu_delete_events, isConcrete && !isEmpty && containsEvents()); + setVisible(menu, R.id.menu_delete_events, isConcrete && !isEmpty && containsPastEvents()); setVisible(menu, R.id.menu_move_to_list, isOffline && !isEmpty); setVisible(menu, R.id.menu_export, !isEmpty && (isHistory || isOffline)); setVisible(menu, R.id.menu_remove_from_history, !isEmpty && isHistory); @@ -689,9 +631,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA return true; } - private boolean containsEvents() { + private boolean containsPastEvents() { for (final Geocache cache : adapter.getCheckedOrAllCaches()) { - if (cache.isEventCache()) { + if (DateUtils.isPastEvent(cache)) { return true; } } @@ -1739,7 +1681,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA loader = new PocketGeocacheListLoader(app, guid); break; } - setTitle(title); + updateTitle(); showProgress(true); showFooterLoadingCaches(); @@ -1774,6 +1716,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } showProgress(false); hideLoading(); + invalidateOptionsMenuCompatible(); } @Override diff --git a/main/src/cgeo/geocaching/CacheListSpinnerAdapter.java b/main/src/cgeo/geocaching/CacheListSpinnerAdapter.java new file mode 100644 index 0000000..5ace70e --- /dev/null +++ b/main/src/cgeo/geocaching/CacheListSpinnerAdapter.java @@ -0,0 +1,68 @@ +package cgeo.geocaching; + +import cgeo.geocaching.list.AbstractList; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +class CacheListSpinnerAdapter extends ArrayAdapter<AbstractList> { + + static class ViewHolder { + TextView title; + TextView subtitle; + } + + private final Context mContext; + + public CacheListSpinnerAdapter(Context context, int resource) { + super(context, resource); + mContext = context; + } + + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + return getCustomView(position, convertView, parent); + } + + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + return getCustomView(position, convertView, parent); + } + + public View getCustomView(final int position, final View convertView, final ViewGroup parent) { + + View resultView = convertView; + LayoutInflater inflater = + (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + + CacheListSpinnerAdapter.ViewHolder holder; + if (resultView == null) { + resultView = inflater.inflate(R.layout.cachelist_spinneritem, parent, false); + holder = new ViewHolder(); + holder.title = (TextView) resultView.findViewById(android.R.id.text1); + holder.subtitle = (TextView) resultView.findViewById(android.R.id.text2); + + resultView.setTag(holder); + } else { + holder = (CacheListSpinnerAdapter.ViewHolder) resultView.getTag(); + } + + AbstractList list = getItem(position); + holder.title.setText(list.getTitle()); + if (list.getCount() >= 0) { + holder.subtitle.setVisibility(View.VISIBLE); + holder.subtitle.setText(CacheListActivity.getCacheNumberString(mContext.getResources(),list.getCount())); + } else { + holder.subtitle.setVisibility(View.GONE); + } + + return resultView; + } +}
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/CompassActivity.java b/main/src/cgeo/geocaching/CompassActivity.java index e5c38a3..1d86c49 100644 --- a/main/src/cgeo/geocaching/CompassActivity.java +++ b/main/src/cgeo/geocaching/CompassActivity.java @@ -217,7 +217,7 @@ public class CompassActivity extends AbstractActionBarActivity { return true; } } - return false; + return super.onOptionsItemSelected(item); } private void setTitle() { diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index 0000fcc..6084762 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -81,10 +81,6 @@ import java.util.regex.Pattern; /** * Internal c:geo representation of a "cache" */ -/** - * @author kep9fe - * - */ public class Geocache implements ICache, IWaypoint { private static final int OWN_WP_PREFIX_OFFSET = 17; diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java index 5149dbc..1f77113 100644 --- a/main/src/cgeo/geocaching/LogCacheActivity.java +++ b/main/src/cgeo/geocaching/LogCacheActivity.java @@ -34,12 +34,13 @@ import android.util.SparseArray; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; -import android.view.SubMenu; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.LinearLayout; +import android.widget.RatingBar; +import android.widget.RatingBar.OnRatingBarChangeListener; import android.widget.TextView; import java.util.ArrayList; @@ -51,7 +52,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia static final String EXTRAS_GEOCODE = "geocode"; static final String EXTRAS_ID = "id"; - private static final int SUBMENU_VOTE = 3; private static final String SAVED_STATE_RATING = "cgeo.geocaching.saved_state_rating"; private static final String SAVED_STATE_TYPE = "cgeo.geocaching.saved_state_type"; private static final String SAVED_STATE_DATE = "cgeo.geocaching.saved_state_date"; @@ -67,7 +67,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private String text = null; private List<LogType> possibleLogTypes = new ArrayList<LogType>(); private List<TrackableLog> trackables = null; - private Button postButton = null; private CheckBox tweetCheck = null; private LinearLayout tweetBox = null; private LinearLayout logPasswordBox = null; @@ -83,6 +82,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private String imageCaption; private String imageDescription; private Uri imageUri; + private boolean sendButtonEnabled; public void onLoadFinished() { @@ -122,7 +122,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private void initializeTrackablesAction() { if (Settings.isTrackableAutoVisit()) { - for (TrackableLog trackable : trackables) { + for (final TrackableLog trackable : trackables) { trackable.action = LogTypeTrackable.VISITED; tbChanged = true; } @@ -141,8 +141,8 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory); inventoryView.removeAllViews(); - for (TrackableLog tb : trackables) { - LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.logcache_trackable_item, null); + for (final TrackableLog tb : trackables) { + final LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.logcache_trackable_item, null); ((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode); ((TextView) inventoryItem.findViewById(R.id.name)).setText(tb.name); @@ -153,7 +153,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia actionButton.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { + public void onClick(final View view) { selectTrackableAction(view); } }); @@ -163,7 +163,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia inventoryItem.findViewById(R.id.info).setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { + public void onClick(final View view) { final Intent trackablesIntent = new Intent(LogCacheActivity.this, TrackableActivity.class); trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, tbCode); startActivity(trackablesIntent); @@ -183,7 +183,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia changeButton.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { + public void onClick(final View view) { selectAllTrackablesAction(); } }); @@ -192,33 +192,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } } - private void enablePostButton(boolean enabled) { - postButton.setEnabled(enabled); - if (enabled) { - postButton.setOnClickListener(new PostListener()); - } - else { - postButton.setOnTouchListener(null); - postButton.setOnClickListener(null); - } - updatePostButtonText(); - } - - private void updatePostButtonText() { - postButton.setText(getPostButtonText()); - } - - private String getPostButtonText() { - if (!postButton.isEnabled()) { - return res.getString(R.string.log_post_not_possible); - } - if (!GCVote.isVotingPossible(cache)) { - return res.getString(R.string.log_post); - } - if (GCVote.isValidRating(rating)) { - return res.getString(R.string.log_post_rate) + " " + GCVote.getRatingText(rating) + "*"; - } - return res.getString(R.string.log_post_no_rate); + private void enablePostButton(final boolean enabled) { + sendButtonEnabled = enabled; + invalidateOptionsMenuCompatible(); } @Override @@ -238,6 +214,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } cache = DataStore.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); + invalidateOptionsMenuCompatible(); possibleLogTypes = cache.getPossibleLogTypes(); if (StringUtils.isNotBlank(cache.getName())) { @@ -247,11 +224,13 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } // Get ids for later use - postButton = (Button) findViewById(R.id.post); tweetBox = (LinearLayout) findViewById(R.id.tweet_box); tweetCheck = (CheckBox) findViewById(R.id.tweet); logPasswordBox = (LinearLayout) findViewById(R.id.log_password_box); + final RatingBar ratingBar = (RatingBar) findViewById(R.id.gcvoteRating); + initializeRatingBar(ratingBar); + // initialize with default values setDefaultValues(); @@ -276,8 +255,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache, null)), false); } } - updatePostButtonText(); - updateImageButton(); enablePostButton(false); final Button typeButton = (Button) findViewById(R.id.type); @@ -285,7 +262,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia typeButton.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { + public void onClick(final View view) { selectLogType(); } }); @@ -304,36 +281,29 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia updateTweetBox(typeSelected); updateLogPasswordBox(typeSelected); - final Button imageButton = (Button) findViewById(R.id.image_btn); - imageButton.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View view) { - selectImage(); - } - }); - - final Button saveButton = (Button) findViewById(R.id.save); - saveButton.setOnClickListener(new View.OnClickListener() { + loggingManager = cache.getLoggingManager(this); - @Override - public void onClick(View v) { - saveLog(true); - } - }); + loggingManager.init(); + } - final Button clearButton = (Button) findViewById(R.id.clear); - clearButton.setOnClickListener(new View.OnClickListener() { + private void initializeRatingBar(final RatingBar ratingBar) { + final TextView label = (TextView) findViewById(R.id.gcvoteLabel); + if (GCVote.isVotingPossible(cache)) { + ratingBar.setVisibility(View.VISIBLE); + label.setVisibility(View.VISIBLE); + } + ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() { @Override - public void onClick(View v) { - clearLog(); + public void onRatingChanged(final RatingBar ratingBar, final float stars, final boolean fromUser) { + // 0.5 is not a valid rating, therefore we must limit + rating = GCVote.isValidRating(stars) ? stars : 0; + if (rating < stars) { + ratingBar.setRating(rating); + } + label.setText(GCVote.getDescription(rating)); } }); - - loggingManager = cache.getLoggingManager(this); - - loggingManager.init(); } private void setDefaultValues() { @@ -363,8 +333,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia final EditText logPasswordView = (EditText) findViewById(R.id.log_password); logPasswordView.setText(StringUtils.EMPTY); - updateImageButton(); - showToast(res.getString(R.string.info_log_cleared)); } @@ -381,53 +349,6 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } @Override - public boolean onCreateOptionsMenu(final Menu menu) { - super.onCreateOptionsMenu(menu); - - final SubMenu menuStars = menu.addSubMenu(0, SUBMENU_VOTE, 0, res.getString(R.string.log_rating)).setIcon(R.drawable.ic_menu_sort_by_size); - menuStars.add(0, 10, 0, res.getString(R.string.log_no_rating)); - menuStars.add(0, 19, 0, res.getString(R.string.log_stars_5) + " (" + res.getString(R.string.log_stars_5_description) + ")"); - menuStars.add(0, 18, 0, res.getString(R.string.log_stars_45) + " (" + res.getString(R.string.log_stars_45_description) + ")"); - menuStars.add(0, 17, 0, res.getString(R.string.log_stars_4) + " (" + res.getString(R.string.log_stars_4_description) + ")"); - menuStars.add(0, 16, 0, res.getString(R.string.log_stars_35) + " (" + res.getString(R.string.log_stars_35_description) + ")"); - menuStars.add(0, 15, 0, res.getString(R.string.log_stars_3) + " (" + res.getString(R.string.log_stars_3_description) + ")"); - menuStars.add(0, 14, 0, res.getString(R.string.log_stars_25) + " (" + res.getString(R.string.log_stars_25_description) + ")"); - menuStars.add(0, 13, 0, res.getString(R.string.log_stars_2) + " (" + res.getString(R.string.log_stars_2_description) + ")"); - menuStars.add(0, 12, 0, res.getString(R.string.log_stars_15) + " (" + res.getString(R.string.log_stars_15_description) + ")"); - menuStars.add(0, 11, 0, res.getString(R.string.log_stars_1) + " (" + res.getString(R.string.log_stars_1_description) + ")"); - - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - - menu.findItem(SUBMENU_VOTE).setVisible(GCVote.isVotingPossible(cache)); - - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (super.onOptionsItemSelected(item)) { - return true; - } - - final int id = item.getItemId(); - if (id >= 10 && id <= 19) { - rating = (id - 9) / 2.0f; - if (!GCVote.isValidRating(rating)) { - rating = GCVote.NO_RATING; - } - updatePostButtonText(); - return true; - } - - return false; - } - - @Override protected void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); outState.putDouble(SAVED_STATE_RATING, rating); @@ -439,14 +360,14 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } @Override - public void setDate(Calendar dateIn) { + public void setDate(final Calendar dateIn) { date = dateIn; final Button dateButton = (Button) findViewById(R.id.date); dateButton.setText(Formatter.formatShortDateVerbally(date.getTime().getTime())); } - public void setType(LogType type) { + public void setType(final LogType type) { final Button typeButton = (Button) findViewById(R.id.type); typeSelected = type; @@ -460,11 +381,9 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia updateTweetBox(type); updateLogPasswordBox(type); - - updatePostButtonText(); } - private void updateTweetBox(LogType type) { + private void updateTweetBox(final LogType type) { if (type == LogType.FOUND_IT && Settings.isUseTwitter() && Settings.isTwitterLoginValid()) { tweetBox.setVisibility(View.VISIBLE); } else { @@ -472,7 +391,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } } - private void updateLogPasswordBox(LogType type) { + private void updateLogPasswordBox(final LogType type) { if (type == LogType.FOUND_IT && cache.isLogPasswordRequired()) { logPasswordBox.setVisibility(View.VISIBLE); } else { @@ -483,23 +402,13 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private class DateListener implements View.OnClickListener { @Override - public void onClick(View arg0) { + public void onClick(final View arg0) { final DateDialog dateDialog = DateDialog.getInstance(date); dateDialog.setCancelable(true); dateDialog.show(getSupportFragmentManager(), "date_dialog"); } } - private class PostListener implements View.OnClickListener { - @Override - public void onClick(View arg0) { - final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ? - R.string.log_saving : - R.string.log_saving_and_uploading); - new Poster(LogCacheActivity.this, message).execute(currentLogText(), currentLogPassword()); - } - } - private class Poster extends AsyncTaskWithProgress<String, StatusCode> { public Poster(final Activity activity, final String progressMessage) { @@ -522,7 +431,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia DataStore.saveChangedCache(cache); // update logs in DB - ArrayList<LogEntry> newLogs = new ArrayList<LogEntry>(cache.getLogs()); + final ArrayList<LogEntry> newLogs = new ArrayList<LogEntry>(cache.getLogs()); final LogEntry logNow = new LogEntry(date.getTimeInMillis(), typeSelected, log); logNow.friend = true; newLogs.add(0, logNow); @@ -541,7 +450,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } if (StringUtils.isNotBlank(imageUri.getPath())) { - ImageResult imageResult = loggingManager.postLogImage(logResult.getLogId(), imageCaption, imageDescription, imageUri); + final ImageResult imageResult = loggingManager.postLogImage(logResult.getLogId(), imageCaption, imageDescription, imageUri); final String uploadedImageUrl = imageResult.getImageUri(); if (StringUtils.isNotEmpty(uploadedImageUrl)) { logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription)); @@ -552,7 +461,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } return logResult.getPostLogResult(); - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Log.e("VisitCacheActivity.Poster.doInBackgroundInternal", e); } @@ -601,15 +510,15 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } private void selectAllTrackablesAction() { - Builder alert = new AlertDialog.Builder(this); + final Builder alert = new AlertDialog.Builder(this); alert.setTitle(res.getString(R.string.log_tb_changeall)); - String[] tbLogTypes = getTBLogTypes(); + final String[] tbLogTypes = getTBLogTypes(); alert.setItems(tbLogTypes, new OnClickListener() { @Override - public void onClick(DialogInterface dialog, int position) { + public void onClick(final DialogInterface dialog, final int position) { final LogTypeTrackable logType = LogTypeTrackable.values()[position]; - for (TrackableLog tb : trackables) { + for (final TrackableLog tb : trackables) { tb.action = logType; } tbChanged = true; @@ -622,7 +531,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private static String[] getTBLogTypes() { final LogTypeTrackable[] logTypeValues = LogTypeTrackable.values(); - String[] logTypes = new String[logTypeValues.length]; + final String[] logTypes = new String[logTypeValues.length]; for (int i = 0; i < logTypes.length; i++) { logTypes[i] = logTypeValues[i].getLabel(); } @@ -633,15 +542,15 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia // use a local copy of the possible types, as that one might be modified in the background by the loader final ArrayList<LogType> possible = new ArrayList<LogType>(possibleLogTypes); - Builder alert = new AlertDialog.Builder(this); - String[] choices = new String[possible.size()]; + final Builder alert = new AlertDialog.Builder(this); + final String[] choices = new String[possible.size()]; for (int i = 0; i < choices.length; i++) { choices[i] = possible.get(i).getL10n(); } alert.setSingleChoiceItems(choices, possible.indexOf(typeSelected), new OnClickListener() { @Override - public void onClick(DialogInterface dialog, int position) { + public void onClick(final DialogInterface dialog, final int position) { setType(possible.get(position)); dialog.dismiss(); } @@ -649,16 +558,16 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia alert.create().show(); } - private void selectTrackableAction(View view) { + private void selectTrackableAction(final View view) { final int realViewId = view.getId(); - Builder alert = new AlertDialog.Builder(this); + final Builder alert = new AlertDialog.Builder(this); final TrackableLog trackableLog = actionButtons.get(realViewId); alert.setTitle(trackableLog.name); - String[] tbLogTypes = getTBLogTypes(); + final String[] tbLogTypes = getTBLogTypes(); alert.setItems(tbLogTypes, new OnClickListener() { @Override - public void onClick(DialogInterface dialog, int position) { + public void onClick(final DialogInterface dialog, final int position) { final LogTypeTrackable logType = LogTypeTrackable.values()[position]; tbChanged = true; trackableLog.action = logType; @@ -671,7 +580,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } private void selectImage() { - Intent selectImageIntent = new Intent(this, ImageSelectActivity.class); + final Intent selectImageIntent = new Intent(this, ImageSelectActivity.class); selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_CAPTION, imageCaption); selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_DESCRIPTION, imageDescription); selectImageIntent.putExtra(ImageSelectActivity.EXTRAS_URI_AS_STRING, imageUri.toString()); @@ -680,7 +589,7 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (requestCode == SELECT_IMAGE) { if (resultCode == RESULT_OK) { imageCaption = data.getStringExtra(ImageSelectActivity.EXTRAS_CAPTION); @@ -690,19 +599,51 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia // Image capture failed, advise user showToast(getResources().getString(R.string.err_select_logimage_failed)); } - updateImageButton(); + } + } + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_send: + sendLog(); + return true; + case R.id.menu_image: + selectImage(); + return true; + case R.id.save: + saveLog(true); + finish(); + return true; + case R.id.clear: + clearLog(); + return true; + default: + break; } + + return super.onOptionsItemSelected(item); } - private void updateImageButton() { - final Button imageButton = (Button) findViewById(R.id.image_btn); - if (cache.supportsLogImages()) { - imageButton.setVisibility(View.VISIBLE); - imageButton.setText(StringUtils.isNotBlank(imageUri.getPath()) ? - res.getString(R.string.log_image_edit) : res.getString(R.string.log_image_attach)); - } else { - imageButton.setVisibility(View.GONE); + private void sendLog() { + if (!sendButtonEnabled) { + Dialogs.message(this, R.string.log_post_not_possible); } + else { + final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ? + R.string.log_saving : + R.string.log_saving_and_uploading); + new Poster(LogCacheActivity.this, message).execute(currentLogText(), currentLogPassword()); + } + } + + @Override + public boolean onCreateOptionsMenu(final Menu menu) { + super.onCreateOptionsMenu(menu); + menu.findItem(R.id.menu_image).setVisible(cache.supportsLogImages()); + menu.findItem(R.id.save).setVisible(true); + menu.findItem(R.id.clear).setVisible(true); + return true; } + } diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index 8de27b0..cf323bb 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -326,9 +326,8 @@ public class MainActivity extends AbstractActionBarActivity { case R.id.menu_gosearch: onSearchRequested(); return true; - default: - return super.onOptionsItemSelected(item); } + return super.onOptionsItemSelected(item); } private void startScannerApplication() { diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java index c9b1b3f..39531f1 100644 --- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java +++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java @@ -361,9 +361,8 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity implemen case R.id.menu_navigate: NavigationAppFactory.showNavigationMenu(this, null, null, coords); return true; - default: - return super.onOptionsItemSelected(item); } + return super.onOptionsItemSelected(item); } private void addToHistory(final Geopoint coords) { diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index bc8582e..f1dab50 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -38,12 +38,14 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.ActionBar; +import android.support.v7.view.ActionMode; import android.text.Html; -import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; @@ -97,9 +99,9 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi geocode = trackable.getGeocode(); if (StringUtils.isNotBlank(trackable.getName())) { - getSupportActionBar().setTitle(Html.fromHtml(trackable.getName()).toString()); + setTitle(Html.fromHtml(trackable.getName()).toString()); } else { - getSupportActionBar().setTitle(trackable.getName()); + setTitle(trackable.getName()); } invalidateOptionsMenuCompatible(); @@ -126,13 +128,17 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi }; private CharSequence clickedItemText = null; + /** + * Action mode of the current contextual action bar (e.g. for copy and share actions). + */ + private ActionMode currentActionMode; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.viewpager_activity); // set title in code, as the activity needs a hard coded title due to the intent filters - getSupportActionBar().setTitle(res.getString(R.string.trackable)); + setTitle(res.getString(R.string.trackable)); // get parameters final Bundle extras = getIntent().getExtras(); @@ -210,36 +216,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) { - super.onCreateContextMenu(menu, view, info); - final int viewId = view.getId(); - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - switch (viewId) { - case R.id.value: // name, TB-code, origin, released, distance - final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); - buildDetailsContextMenu(menu, clickedItemText, itemTitle, true); - break; - case R.id.goal: - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.trackable_goal), false); - break; - case R.id.details: - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.trackable_details), false); - break; - case R.id.log: - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_logs), false); - break; - default: - break; - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - return onClipboardItemSelected(item, clickedItemText) || onOptionsItemSelected(item); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.trackable_activity, menu); return true; @@ -254,9 +230,8 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi case R.id.menu_browser_trackable: startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl()))); return true; - default: - return false; } + return super.onOptionsItemSelected(item); } @Override @@ -410,7 +385,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } // trackable name - registerForContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown))); + addContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown))); // trackable type String tbType; @@ -422,7 +397,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi details.add(R.string.trackable_type, tbType); // trackable geocode - registerForContextMenu(details.add(R.string.trackable_code, trackable.getGeocode())); + addContextMenu(details.add(R.string.trackable_code, trackable.getGeocode())); // trackable owner final TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown)); @@ -491,17 +466,17 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi if (StringUtils.isNotBlank(trackable.getOrigin())) { final TextView origin = details.add(R.string.trackable_origin, ""); origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE); - registerForContextMenu(origin); + addContextMenu(origin); } // trackable released if (trackable.getReleased() != null) { - registerForContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime()))); + addContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime()))); } // trackable distance if (trackable.getDistance() >= 0) { - registerForContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()))); + addContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()))); } // trackable goal @@ -510,7 +485,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi goalTextView.setVisibility(View.VISIBLE); goalTextView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE); goalTextView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - registerForContextMenu(goalTextView); + addContextMenu(goalTextView); } // trackable details @@ -519,7 +494,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi detailsTextView.setVisibility(View.VISIBLE); detailsTextView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE); detailsTextView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - registerForContextMenu(detailsTextView); + addContextMenu(detailsTextView); } // trackable image @@ -550,4 +525,70 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } + public void addContextMenu(final View view) { + view.setOnLongClickListener(new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + return startContextualActionBar(view); + } + }); + + view.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + startContextualActionBar(view); + } + }); + } + + private boolean startContextualActionBar(final View view) { + if (currentActionMode != null) { + return false; + } + currentActionMode = startSupportActionMode(new ActionMode.Callback() { + + @Override + public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { + final int viewId = view.getId(); + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + switch (viewId) { + case R.id.value: // name, TB-code, origin, released, distance + final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, itemTitle, true); + return true; + case R.id.goal: + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.trackable_goal), false); + return true; + case R.id.details: + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.trackable_details), false); + return true; + case R.id.log: + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_logs), false); + return true; + } + return false; + } + + @Override + public void onDestroyActionMode(ActionMode actionMode) { + currentActionMode = null; + } + + @Override + public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { + actionMode.getMenuInflater().inflate(R.menu.details_context, menu); + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { + return onClipboardItemSelected(actionMode, menuItem, clickedItemText); + } + }); + return false; + } + } diff --git a/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java b/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java index 615a432..a732f65 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java @@ -24,4 +24,11 @@ public class AbstractActionBarActivity extends AbstractActivity { private void initUpAction() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } + + @Override + public void setTitle(CharSequence title) { + super.setTitle(title); + // reflect the title in the actionbar + ActivityMixin.setTitle(this, title); + } } diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index d542b13..e3df1f7 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -12,6 +12,7 @@ import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.TranslationUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import rx.Subscription; import rx.subscriptions.Subscriptions; @@ -26,7 +27,8 @@ import android.nfc.NfcEvent; import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; -import android.view.ContextMenu; +import android.support.v7.view.ActionMode; +import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.Window; @@ -49,11 +51,6 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs this.keepScreenOn = keepScreenOn; } - @Override - final public void goHome(final View view) { - ActivityMixin.navigateToMain(this); - } - final protected void showProgress(final boolean show) { ActivityMixin.showProgress(this, show); } @@ -83,9 +80,8 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId()== android.R.id.home) { - ActivityMixin.navigateToMain(this); - return true; + if (item.getItemId() == android.R.id.home) { + return ActivityMixin.navigateUp(this); } return super.onOptionsItemSelected(item); } @@ -160,9 +156,8 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs new Keyboard(this).show(view); } - protected void buildDetailsContextMenu(final ContextMenu menu, final CharSequence clickedItemText, final CharSequence fieldTitle, final boolean copyOnly) { - menu.setHeaderTitle(fieldTitle); - getMenuInflater().inflate(R.menu.details_context, menu); + protected void buildDetailsContextMenu(final ActionMode actionMode, final Menu menu, final CharSequence clickedItemText, final CharSequence fieldTitle, final boolean copyOnly) { + actionMode.setTitle(fieldTitle); menu.findItem(R.id.menu_translate_to_sys_lang).setVisible(!copyOnly); if (!copyOnly) { if (clickedItemText.length() > TranslationUtils.TRANSLATION_TEXT_LENGTH_WARN) { @@ -174,24 +169,28 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs menu.findItem(R.id.menu_translate_to_english).setVisible(!copyOnly && !localeIsEnglish); } - protected boolean onClipboardItemSelected(final MenuItem item, final CharSequence clickedItemText) { + protected boolean onClipboardItemSelected(@NonNull final ActionMode actionMode, final MenuItem item, final CharSequence clickedItemText) { switch (item.getItemId()) { // detail fields case R.id.menu_copy: ClipboardUtils.copyToClipboard(clickedItemText); showToast(res.getString(R.string.clipboard_copy_ok)); + actionMode.finish(); return true; case R.id.menu_translate_to_sys_lang: TranslationUtils.startActivityTranslate(this, Locale.getDefault().getLanguage(), HtmlUtils.extractText(clickedItemText)); + actionMode.finish(); return true; case R.id.menu_translate_to_english: TranslationUtils.startActivityTranslate(this, Locale.ENGLISH.getLanguage(), HtmlUtils.extractText(clickedItemText)); + actionMode.finish(); return true; case R.id.menu_cache_share_field: final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, clickedItemText.toString()); startActivity(Intent.createChooser(intent, res.getText(R.string.cache_share_field))); + actionMode.finish(); return true; default: return false; @@ -208,8 +207,9 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs } protected void initializeAndroidBeam(ActivitySharingInterface sharingInterface) { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { initializeICSAndroidBeam(sharingInterface); + } } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java index eaa8a96..eac191a 100644 --- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java @@ -5,7 +5,6 @@ import cgeo.geocaching.CgeoApplication; import android.content.res.Resources; import android.os.Bundle; import android.view.MenuItem; -import android.view.View; import android.view.Window; public abstract class AbstractListActivity extends ActionBarListActivity implements @@ -24,11 +23,6 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme this.keepScreenOn = keepScreenOn; } - @Override - final public void goHome(View view) { - ActivityMixin.navigateToMain(this); - } - final public void showProgress(final boolean show) { ActivityMixin.showProgress(this, show); } @@ -41,7 +35,7 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme public final void showToast(String text) { ActivityMixin.showToast(this, text); } - + @Override public final void showShortToast(String text) { ActivityMixin.showShortToast(this, text); @@ -56,16 +50,14 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme initUpAction(); } - protected void initUpAction() - { + protected void initUpAction() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId()== android.R.id.home) { - ActivityMixin.navigateToMain(this); - return true; + return ActivityMixin.navigateUp(this); } return super.onOptionsItemSelected(item); } diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java index c43e1bd..e2181d0 100644 --- a/main/src/cgeo/geocaching/activity/ActivityMixin.java +++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java @@ -1,15 +1,17 @@ package cgeo.geocaching.activity; -import cgeo.geocaching.MainActivity; import cgeo.geocaching.R; -import cgeo.geocaching.compatibility.Compatibility; import cgeo.geocaching.settings.Settings; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import android.app.Activity; import android.content.Intent; +import android.support.v4.app.ActivityCompat; import android.support.v4.app.NavUtils; +import android.support.v4.app.TaskStackBuilder; +import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.view.Gravity; import android.view.WindowManager; @@ -23,12 +25,14 @@ public final class ActivityMixin { return; } - if (((ActionBarActivity) activity).getSupportActionBar() != null) { - ((ActionBarActivity) activity).getSupportActionBar().setTitle(text); + if (activity instanceof ActionBarActivity) { + final ActionBar actionBar = ((ActionBarActivity) activity).getSupportActionBar(); + if (actionBar != null) { + actionBar.setTitle(text); + } } } - public static void showProgress(final ActionBarActivity activity, final boolean show) { if (activity == null) { return; @@ -84,7 +88,12 @@ public final class ActivityMixin { } public static void invalidateOptionsMenu(Activity activity) { - Compatibility.invalidateOptionsMenu(activity); + if (activity instanceof ActionBarActivity) { + ((ActionBarActivity) activity).supportInvalidateOptionsMenu(); + } + else { + ActivityCompat.invalidateOptionsMenu(activity); + } } /** @@ -114,8 +123,26 @@ public final class ActivityMixin { editText.setSelection(newCursor); } - public static void navigateToMain(Activity activity) { - final Intent main = new Intent(activity, MainActivity.class); - NavUtils.navigateUpTo(activity, main); + public static boolean navigateUp(@NonNull final Activity activity) { + // see http://developer.android.com/training/implementing-navigation/ancestral.html + Intent upIntent = NavUtils.getParentActivityIntent(activity); + if (upIntent == null) { + activity.finish(); + return true; + } + if (NavUtils.shouldUpRecreateTask(activity, upIntent)) { + // This activity is NOT part of this app's task, so create a new task + // when navigating up, with a synthesized back stack. + TaskStackBuilder.create(activity) + // Add all of this activity's parents to the back stack + .addNextIntentWithParentStack(upIntent) + // Navigate up to the closest parent + .startActivities(); + } else { + // This activity is part of this app's task, so simply + // navigate up to the logical parent activity. + NavUtils.navigateUpTo(activity, upIntent); + } + return true; } } diff --git a/main/src/cgeo/geocaching/activity/IAbstractActivity.java b/main/src/cgeo/geocaching/activity/IAbstractActivity.java index 7ca2322..4fb6a2a 100644 --- a/main/src/cgeo/geocaching/activity/IAbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/IAbstractActivity.java @@ -1,11 +1,8 @@ package cgeo.geocaching.activity; -import android.view.View; public interface IAbstractActivity { - public void goHome(View view); - public void showToast(String text); public void showShortToast(String text); diff --git a/main/src/cgeo/geocaching/apps/cache/GccApp.java b/main/src/cgeo/geocaching/apps/cache/GccApp.java deleted file mode 100644 index 4423977..0000000 --- a/main/src/cgeo/geocaching/apps/cache/GccApp.java +++ /dev/null @@ -1,28 +0,0 @@ -package cgeo.geocaching.apps.cache; - -import cgeo.geocaching.R; -import cgeo.geocaching.utils.ProcessUtils; - -import android.content.Intent; - -public class GccApp extends AbstractGeneralApp { - private static final String PACKAGE = "eisbehr.gcc"; - private static final String PACKAGE_PRO = "eisbehr.gcc.pro"; - - public GccApp() { - super(getString(R.string.cache_menu_gcc), R.id.cache_app_gcc, null); - } - - @Override - public boolean isInstalled() { - return ProcessUtils.isLaunchable(PACKAGE) || ProcessUtils.isLaunchable(PACKAGE_PRO); - } - - @Override - protected Intent getLaunchIntent() { - if (ProcessUtils.isLaunchable(PACKAGE_PRO)) { - return ProcessUtils.getLaunchIntent(PACKAGE_PRO); - } - return ProcessUtils.getLaunchIntent(PACKAGE); - } -} diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java index 3177a29..1446d8a 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java @@ -8,7 +8,6 @@ import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.apps.AbstractAppFactory; import cgeo.geocaching.apps.App; import cgeo.geocaching.apps.cache.CacheBeaconApp; -import cgeo.geocaching.apps.cache.GccApp; import cgeo.geocaching.apps.cache.WhereYouGoApp; import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationBikeApp; import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationDrivingApp; @@ -70,7 +69,6 @@ public final class NavigationAppFactory extends AbstractAppFactory { GOOGLE_MAPS_DIRECTIONS(new GoogleMapsDirectionApp(), 13, R.string.pref_navigation_menu_google_maps_directions), CACHE_BEACON(new CacheBeaconApp(), 14, R.string.pref_navigation_menu_cache_beacon), - GCC(new GccApp(), 15, R.string.pref_navigation_menu_gcc), WHERE_YOU_GO(new WhereYouGoApp(), 16, R.string.pref_navigation_menu_where_you_go), PEBBLE(new PebbleApp(), 17, R.string.pref_navigation_menu_pebble), MAPSWITHME(new MapsWithMeApp(), 22, R.string.pref_navigation_menu_mapswithme); diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java deleted file mode 100644 index a425ee5..0000000 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java +++ /dev/null @@ -1,17 +0,0 @@ -package cgeo.geocaching.compatibility; - -import android.annotation.TargetApi; -import android.app.Activity; - -/** - * Android level 11 support - */ -@TargetApi(11) -public class AndroidLevel11 implements AndroidLevel11Interface { - - @Override - public void invalidateOptionsMenu(final Activity activity) { - activity.invalidateOptionsMenu(); - } - -} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java deleted file mode 100644 index 6a23ed5..0000000 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java +++ /dev/null @@ -1,15 +0,0 @@ -package cgeo.geocaching.compatibility; - -import android.app.Activity; - -/** - * implement level 11 API using older methods - */ -public class AndroidLevel11Emulation implements AndroidLevel11Interface { - - @Override - public void invalidateOptionsMenu(final Activity activity) { - // do nothing - } - -} diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java deleted file mode 100644 index 236e92d..0000000 --- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Interface.java +++ /dev/null @@ -1,8 +0,0 @@ -package cgeo.geocaching.compatibility; - -import android.app.Activity; - -public interface AndroidLevel11Interface { - public void invalidateOptionsMenu(final Activity activity); - -} diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java index 887bb32..54e2966 100644 --- a/main/src/cgeo/geocaching/compatibility/Compatibility.java +++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java @@ -10,12 +10,10 @@ public final class Compatibility { private static final int SDK_VERSION = Build.VERSION.SDK_INT; - private static final AndroidLevel11Interface LEVEL_11; private static final AndroidLevel13Interface LEVEL_13; private static final AndroidLevel19Interface LEVEL_19; static { - LEVEL_11 = SDK_VERSION >= 11 ? new AndroidLevel11() : new AndroidLevel11Emulation(); LEVEL_13 = SDK_VERSION >= 13 ? new AndroidLevel13() : new AndroidLevel13Emulation(); LEVEL_19 = SDK_VERSION >= 19 ? new AndroidLevel19() : new AndroidLevel19Emulation(); } @@ -24,10 +22,6 @@ public final class Compatibility { // utility class } - public static void invalidateOptionsMenu(final Activity activity) { - LEVEL_11.invalidateOptionsMenu(activity); - } - public static int getDisplayWidth() { return LEVEL_13.getDisplayWidth(); } diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java index 396a589..973e65f 100644 --- a/main/src/cgeo/geocaching/files/FileParser.java +++ b/main/src/cgeo/geocaching/files/FileParser.java @@ -4,6 +4,8 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.utils.CancellableHandler; import org.apache.commons.io.IOUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -29,7 +31,7 @@ public abstract class FileParser { * @throws ParserException * if the input stream contains data not matching the file format of the parser */ - public abstract Collection<Geocache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException; + public abstract Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException; /** * Convenience method for parsing a file. @@ -49,7 +51,7 @@ public abstract class FileParser { } } - protected static StringBuilder readStream(InputStream is, CancellableHandler progressHandler) throws IOException { + protected static StringBuilder readStream(@NonNull final InputStream is, @Nullable final CancellableHandler progressHandler) throws IOException { final StringBuilder buffer = new StringBuilder(); ProgressInputStream progressInputStream = new ProgressInputStream(is); final BufferedReader input = new BufferedReader(new InputStreamReader(progressInputStream, "UTF-8")); @@ -66,7 +68,7 @@ public abstract class FileParser { } } - protected static void showProgressMessage(final CancellableHandler handler, final int bytesRead) { + protected static void showProgressMessage(@Nullable final CancellableHandler handler, final int bytesRead) { if (handler != null) { if (handler.isCancelled()) { throw new CancellationException(); diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java index 6161088..f3cd326 100644 --- a/main/src/cgeo/geocaching/files/GPXParser.java +++ b/main/src/cgeo/geocaching/files/GPXParser.java @@ -25,6 +25,8 @@ import cgeo.geocaching.utils.SynchronizedDateFormat; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.xml.sax.Attributes; import org.xml.sax.SAXException; @@ -270,7 +272,7 @@ public abstract class GPXParser extends FileParser { } @Override - public Collection<Geocache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException { + public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException { resetCache(); final RootElement root = new RootElement(namespace, "gpx"); final Element waypoint = root.getChild(namespace, "wpt"); diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java index 3d01c1b..223fb5a 100644 --- a/main/src/cgeo/geocaching/files/LocParser.java +++ b/main/src/cgeo/geocaching/files/LocParser.java @@ -12,6 +12,8 @@ import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import java.io.IOException; import java.io.InputStream; @@ -116,9 +118,9 @@ public final class LocParser extends FileParser { } @Override - public Collection<Geocache> parse(InputStream stream, CancellableHandler progressHandler) throws IOException, ParserException { - // TODO: progress reporting happens during reading stream only, not during parsing - String streamContent = readStream(stream, progressHandler).toString(); + public Collection<Geocache> parse(@NonNull final InputStream stream, @Nullable final CancellableHandler progressHandler) throws IOException, ParserException { + final String streamContent = readStream(stream, null).toString(); + final int maxSize = streamContent.length(); final Map<String, Geocache> coords = parseCoordinates(streamContent); final List<Geocache> caches = new ArrayList<Geocache>(); for (Entry<String, Geocache> entry : coords.entrySet()) { @@ -136,6 +138,9 @@ public final class LocParser extends FileParser { cache.setListId(listId); cache.setDetailed(true); cache.store(null); + if (progressHandler != null) { + progressHandler.sendMessage(progressHandler.obtainMessage(0, maxSize * caches.size() / coords.size(), 0)); + } } Log.i("Caches found in .loc file: " + caches.size()); return caches; diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java index 0ab1fe3..d77a4e6 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVote.java +++ b/main/src/cgeo/geocaching/gcvote/GCVote.java @@ -1,6 +1,8 @@ package cgeo.geocaching.gcvote; +import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; @@ -253,7 +255,7 @@ public final class GCVote { /** * Get geocodes of all the caches, which can be used with GCVote. Non-GC caches will be filtered out. - * + * * @param caches * @return */ @@ -281,4 +283,33 @@ public final class GCVote { return Settings.isGCvoteLogin() && StringUtils.isNotBlank(cache.getGuid()) && cache.supportsGCVote(); } + public static String getDescription(final float rating) { + switch (Math.round(rating * 2f)) { + case 2: + return getString(R.string.log_stars_1_description); + case 3: + return getString(R.string.log_stars_15_description); + case 4: + return getString(R.string.log_stars_2_description); + case 5: + return getString(R.string.log_stars_25_description); + case 6: + return getString(R.string.log_stars_3_description); + case 7: + return getString(R.string.log_stars_35_description); + case 8: + return getString(R.string.log_stars_4_description); + case 9: + return getString(R.string.log_stars_45_description); + case 10: + return getString(R.string.log_stars_5_description); + default: + return getString(R.string.log_no_rating); + } + } + + private static String getString(int resId) { + return CgeoApplication.getInstance().getString(resId); + } + } diff --git a/main/src/cgeo/geocaching/maps/AbstractMap.java b/main/src/cgeo/geocaching/maps/AbstractMap.java index aff9c75..2eceadb 100644 --- a/main/src/cgeo/geocaching/maps/AbstractMap.java +++ b/main/src/cgeo/geocaching/maps/AbstractMap.java @@ -9,7 +9,6 @@ import android.os.Build; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; -import android.view.View; import android.view.Window; /** @@ -70,8 +69,6 @@ public abstract class AbstractMap { return mapActivity.superOnOptionsItemSelected(item); } - public abstract void goHome(View view); - public abstract void onSaveInstanceState(final Bundle outState); } diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index 9c67723..87d5366 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -43,6 +43,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import rx.Subscription; import rx.functions.Action0; @@ -96,7 +97,7 @@ import java.util.concurrent.TimeUnit; /** * Class representing the Map in c:geo */ -public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFactory { +public class CGeoMap extends AbstractMap implements ViewFactory { /** max. number of caches displayed in the Live Map */ public static final int MAX_CACHES = 500; @@ -175,7 +176,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private static final int[][] INSET_USERMODIFIEDCOORDS = { { 21, 28, 0, 0 }, { 19, 25, 0, 0 }, { 25, 33, 0, 0 } }; // bottom right, 12x12 / 26x26 / 35x35 private static final int[][] INSET_PERSONALNOTE = { { 0, 28, 21, 0 }, { 0, 25, 19, 0 }, { 0, 33, 25, 0 } }; // bottom left, 12x12 / 26x26 / 35x35 - private SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>(); + private final SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>(); /** Count of caches currently visible */ private int cachesCnt = 0; /** List of caches in the viewport */ @@ -190,7 +191,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto // views private CheckBox myLocSwitch = null; - /** Controls the map behaviour */ + /** Controls the map behavior */ private MapMode mapMode = null; /** Live mode enabled for map. **/ private boolean isLiveEnabled; @@ -223,7 +224,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { final int what = msg.what; final CGeoMap map = mapRef.get(); if (map == null) { @@ -268,7 +269,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final private Handler displayHandler = new DisplayHandler(this); - private void setTitle(String title) { + private void setTitle(final String title) { /* Compatibility for the old Action Bar, only used by the maps activity at the moment */ final TextView titleview = (TextView) activity.findViewById(R.id.actionbar_title); if (titleview != null) { @@ -281,7 +282,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } @TargetApi(Build.VERSION_CODES.HONEYCOMB) - private void setTitleHoneyComb(String title) { + private void setTitleHoneyComb(final String title) { activity.getActionBar().setTitle(title); } @@ -295,7 +296,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { final int what = msg.what; if (what == HIDE_PROGRESS) { @@ -308,7 +309,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } - private void showProgress(boolean show) { + private void showProgress(final boolean show) { final CGeoMap map = mapRef.get(); if (map == null) { return; @@ -334,10 +335,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final private class LoadDetailsHandler extends CancellableHandler { @Override - public void handleRegularMessage(Message msg) { + public void handleRegularMessage(final Message msg) { if (msg.what == UPDATE_PROGRESS) { if (waitDialog != null) { - int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000); + final int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000); int secondsRemaining; if (detailProgress > 0) { secondsRemaining = (detailTotal - detailProgress) * secondsElapsed / detailProgress; @@ -349,7 +350,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (secondsRemaining < 40) { waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm)); } else { - int minsRemaining = secondsRemaining / 60; + final int minsRemaining = secondsRemaining / 60; waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + minsRemaining + " " + res.getQuantityString(R.plurals.caches_eta_mins, minsRemaining)); } } @@ -372,7 +373,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final private Handler noMapTokenHandler = new Handler() { @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { if (!noMapTokenShowed) { ActivityMixin.showToast(activity, res.getString(R.string.map_token_err)); @@ -388,7 +389,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto /* Current source id */ private int currentSourceId; - public CGeoMap(MapActivityImpl activity) { + public CGeoMap(final MapActivityImpl activity) { super(activity); geoDirUpdate = new UpdateLoc(this); } @@ -423,7 +424,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // class init @@ -431,7 +432,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto activity = this.getActivity(); app = (CgeoApplication) activity.getApplication(); - int countBubbleCnt = DataStore.getAllCachesCount(); + final int countBubbleCnt = DataStore.getAllCachesCount(); caches = new LeastRecentlyUsedSet<Geocache>(MAX_CACHES + countBubbleCnt); final MapProvider mapProvider = Settings.getMapProvider(); @@ -496,7 +497,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto mapView.setBuiltInZoomControls(true); mapView.displayZoomControls(true); mapView.preLoad(); - mapView.setOnDragListener(this); + mapView.setOnDragListener(new MapDragListener(this)); // initialize overlays mapView.clearOverlays(); @@ -530,7 +531,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } - CheckBox locSwitch = (CheckBox) activity.findViewById(R.id.my_position); + final CheckBox locSwitch = (CheckBox) activity.findViewById(R.id.my_position); if (locSwitch!=null) { initMyLocationSwitchButton(locSwitch); } @@ -541,13 +542,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } - private void initMyLocationSwitchButton(CheckBox locSwitch) { + private void initMyLocationSwitchButton(final CheckBox locSwitch) { myLocSwitch = locSwitch; /* TODO: Switch back to ImageSwitcher for animations? myLocSwitch.setFactory(this); myLocSwitch.setInAnimation(activity, android.R.anim.fade_in); myLocSwitch.setOutAnimation(activity, android.R.anim.fade_out); */ - myLocSwitch.setOnClickListener(new MyLocationListener()); + myLocSwitch.setOnClickListener(new MyLocationListener(this)); switchMyLocationButton(); } @@ -563,7 +564,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private void prepareFilterBar() { // show the filter warning bar if the filter is set if (Settings.getCacheType() != CacheType.ALL) { - String cacheType = Settings.getCacheType().getL10n(); + final String cacheType = Settings.getCacheType().getL10n(); ((TextView) activity.findViewById(R.id.filter_text)).setText(cacheType); activity.findViewById(R.id.filter_bar).setVisibility(View.VISIBLE); } else { @@ -577,8 +578,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto resumeSubscription = Subscriptions.from(geoDirUpdate.start(GeoDirHandler.UPDATE_GEODIR), startTimer()); if (!CollectionUtils.isEmpty(dirtyCaches)) { - for (String geocode : dirtyCaches) { - Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + for (final String geocode : dirtyCaches) { + final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); if (cache != null) { // new collection type needs to remove first caches.remove(cache); @@ -588,7 +589,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } dirtyCaches.clear(); // Update display - displayExecutor.execute(new DisplayRunnable(mapView.getViewport())); + displayExecutor.execute(new DisplayRunnable(this)); } } @@ -608,7 +609,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override - public boolean onCreateOptionsMenu(Menu menu) { + public boolean onCreateOptionsMenu(final Menu menu) { // menu inflation happens in Google/Mapsforge specific classes super.onCreateOptionsMenu(menu); @@ -620,7 +621,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { /* if we have an Actionbar find the my position toggle */ - MenuItem item = menu.findItem(R.id.menu_toggle_mypos); + final MenuItem item = menu.findItem(R.id.menu_toggle_mypos); myLocSwitch = new CheckBox(activity); myLocSwitch.setButtonDrawable(R.drawable.ic_menu_myposition); item.setActionView(myLocSwitch); @@ -633,9 +634,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } @Override - public boolean onPrepareOptionsMenu(Menu menu) { + public boolean onPrepareOptionsMenu(final Menu menu) { super.onPrepareOptionsMenu(menu); - for (MapSource mapSource : MapProviderFactory.getMapSources()) { + for (final MapSource mapSource : MapProviderFactory.getMapSources()) { final MenuItem menuItem = menu.findItem(mapSource.getNumericalId()); if (menuItem != null) { menuItem.setVisible(mapSource.isAvailable()); @@ -694,7 +695,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto default: // DETAILED menu.findItem(R.id.menu_strategy_detailed).setChecked(true); } - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Log.e("CGeoMap.onPrepareOptionsMenu", e); } @@ -702,11 +703,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(final MenuItem item) { final int id = item.getItemId(); switch (id) { case android.R.id.home: - ActivityMixin.navigateToMain(activity); + ActivityMixin.navigateUp(activity); return true; case R.id.menu_trail_mode: Settings.setMapTrail(!Settings.isMapTrail()); @@ -817,16 +818,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final File[] themeFiles = Settings.getMapThemeFiles(); String currentTheme = StringUtils.EMPTY; - String currentThemePath = Settings.getCustomRenderThemeFilePath(); + final String currentThemePath = Settings.getCustomRenderThemeFilePath(); if (StringUtils.isNotEmpty(currentThemePath)) { - File currentThemeFile = new File(currentThemePath); + final File currentThemeFile = new File(currentThemePath); currentTheme = currentThemeFile.getName(); } - List<String> names = new ArrayList<String>(); + final List<String> names = new ArrayList<String>(); names.add(res.getString(R.string.map_theme_builtin)); int currentItem = 0; - for (File file : themeFiles) { + for (final File file : themeFiles) { if (currentTheme.equalsIgnoreCase(file.getName())) { currentItem = names.size(); } @@ -835,7 +836,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto final int selectedItem = currentItem; - AlertDialog.Builder builder = new AlertDialog.Builder(activity); + final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(R.string.map_theme_select); @@ -843,7 +844,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto new DialogInterface.OnClickListener() { @Override - public void onClick(DialogInterface dialog, int newItem) { + public void onClick(final DialogInterface dialog, final int newItem) { if (newItem != selectedItem) { // Adjust index because of <default> selection if (newItem > 0) { @@ -909,7 +910,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto activity.finish(); // prepare information to restart a similar view - Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass()); + final Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass()); mapIntent.putExtra(EXTRAS_SEARCH, searchIntent); mapIntent.putExtra(EXTRAS_GEOCODE, geocodeIntent); @@ -987,7 +988,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto */ private final WeakReference<CGeoMap> map; - public UpdateLoc(CGeoMap map) { + public UpdateLoc(final CGeoMap map) { this.map = new WeakReference<CGeoMap>(map); } @@ -1013,15 +1014,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto timeLastPositionOverlayCalculation = currentTimeMillis; try { - CGeoMap cgeoMapRef = map.get(); + final CGeoMap cgeoMapRef = map.get(); if (cgeoMapRef != null) { if (cgeoMapRef.mapView != null) { if (cgeoMapRef.overlayPositionAndScale == null) { cgeoMapRef.overlayPositionAndScale = cgeoMapRef.mapView.createAddPositionAndScaleOverlay(); } - boolean needsRepaintForDistance = needsRepaintForDistance(); - boolean needsRepaintForHeading = needsRepaintForHeading(); + final boolean needsRepaintForDistance = needsRepaintForDistance(); + final boolean needsRepaintForHeading = needsRepaintForHeading(); if (needsRepaintForDistance) { if (cgeoMapRef.followMyLocation) { @@ -1036,7 +1037,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } } - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Log.w("Failed to update location."); } } @@ -1131,16 +1132,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (moved) { map.markersInvalidated = false; - long currentTime = System.currentTimeMillis(); + final long currentTime = System.currentTimeMillis(); if (1000 < (currentTime - map.loadThreadRun)) { map.viewport = viewportNow; - loadExecutor.execute(map.new LoadRunnable(map.viewport)); + loadExecutor.execute(new LoadRunnable(map)); } } } - } catch (Exception e) { + } catch (final Exception e) { Log.w("CGeoMap.startLoadtimer.start", e); } } @@ -1170,79 +1171,87 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto * started by {@link LoadTimer} */ - private class LoadRunnable extends DoRunnable { + private static class LoadRunnable extends DoRunnable { - public LoadRunnable(final Viewport viewport) { - super(viewport); + public LoadRunnable(@NonNull final CGeoMap map) { + super(map); } @Override public void run() { - try { - showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); - loadThreadRun = System.currentTimeMillis(); - - SearchResult searchResult; - if (mapMode == MapMode.LIVE) { - searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(viewport, Settings.getCacheType())); - } else { - // map started from another activity - searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult(); - if (geocodeIntent != null) { - searchResult.addGeocode(geocodeIntent); - } - } - // live mode search result - if (isLiveEnabled) { - searchResult.addSearchResult(DataStore.loadCachedInViewport(viewport, Settings.getCacheType())); - } + final CGeoMap map = getMap(); + if (map != null) { + map.doLoadRun(); + } + } + } - downloaded = true; - Set<Geocache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS); - // update the caches - // new collection type needs to remove first - caches.removeAll(cachesFromSearchResult); - caches.addAll(cachesFromSearchResult); + private void doLoadRun() { + try { + showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); + loadThreadRun = System.currentTimeMillis(); - final boolean excludeMine = Settings.isExcludeMyCaches(); - final boolean excludeDisabled = Settings.isExcludeDisabledCaches(); - if (mapMode == MapMode.LIVE) { - CGeoMap.filter(caches); + SearchResult searchResult; + if (mapMode == MapMode.LIVE) { + searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(viewport, Settings.getCacheType())); + } else { + // map started from another activity + searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult(); + if (geocodeIntent != null) { + searchResult.addGeocode(geocodeIntent); } - countVisibleCaches(); - if (cachesCnt < Settings.getWayPointsThreshold() || geocodeIntent != null) { - // we don't want to see any stale waypoints - waypoints.clear(); - if (isLiveEnabled || mapMode == MapMode.LIVE - || mapMode == MapMode.COORDS) { - //All visible waypoints - CacheType type = Settings.getCacheType(); - Set<Waypoint> waypointsInViewport = DataStore.loadWaypoints(viewport, excludeMine, excludeDisabled, type); - waypoints.addAll(waypointsInViewport); - } - else { - //All waypoints from the viewed caches - for (Geocache c : caches.getAsList()) { - waypoints.addAll(c.getWaypoints()); - } - } + } + // live mode search result + if (isLiveEnabled) { + searchResult.addSearchResult(DataStore.loadCachedInViewport(viewport, Settings.getCacheType())); + } + + downloaded = true; + final Set<Geocache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS); + // update the caches + // new collection type needs to remove first + caches.removeAll(cachesFromSearchResult); + caches.addAll(cachesFromSearchResult); + + final boolean excludeMine = Settings.isExcludeMyCaches(); + final boolean excludeDisabled = Settings.isExcludeDisabledCaches(); + if (mapMode == MapMode.LIVE) { + CGeoMap.filter(caches); + } + countVisibleCaches(); + if (cachesCnt < Settings.getWayPointsThreshold() || geocodeIntent != null) { + // we don't want to see any stale waypoints + waypoints.clear(); + if (isLiveEnabled || mapMode == MapMode.LIVE + || mapMode == MapMode.COORDS) { + //All visible waypoints + final CacheType type = Settings.getCacheType(); + final Set<Waypoint> waypointsInViewport = DataStore.loadWaypoints(viewport, excludeMine, excludeDisabled, type); + waypoints.addAll(waypointsInViewport); } else { - // we don't want to see any stale waypoints when above threshold - waypoints.clear(); + //All waypoints from the viewed caches + for (final Geocache c : caches.getAsList()) { + waypoints.addAll(c.getWaypoints()); + } } + } + else { + // we don't want to see any stale waypoints when above threshold + waypoints.clear(); + } - //render - displayExecutor.execute(new DisplayRunnable(viewport)); + //render + displayExecutor.execute(new DisplayRunnable(this)); - if (isLiveEnabled) { - downloadExecutor.execute(new DownloadRunnable(viewport)); - } - lastSearchResult = searchResult; - } finally { - showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress + if (isLiveEnabled) { + downloadExecutor.execute(new DownloadRunnable(this)); } + lastSearchResult = searchResult; + } finally { + showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress } + } /** @@ -1250,111 +1259,125 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto * Started by {@link LoadRunnable}. */ - private class DownloadRunnable extends DoRunnable { + private static class DownloadRunnable extends DoRunnable { - public DownloadRunnable(final Viewport viewport) { - super(viewport); + public DownloadRunnable(final CGeoMap map) { + super(map); } @Override public void run() { - try { - showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); // show progress - if (Settings.isGCConnectorActive()) { - if (tokens == null) { - tokens = GCLogin.getInstance().getMapTokens(); - if (noMapTokenHandler != null && (StringUtils.isEmpty(tokens.getUserSession()) || StringUtils.isEmpty(tokens.getSessionToken()))) { - tokens = null; - noMapTokenHandler.sendEmptyMessage(0); - } + final CGeoMap map = getMap(); + if (map != null) { + map.doDownloadRun(); + } + } + } + + private void doDownloadRun() { + try { + showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); // show progress + if (Settings.isGCConnectorActive()) { + if (tokens == null) { + tokens = GCLogin.getInstance().getMapTokens(); + if (noMapTokenHandler != null && (StringUtils.isEmpty(tokens.getUserSession()) || StringUtils.isEmpty(tokens.getSessionToken()))) { + tokens = null; + noMapTokenHandler.sendEmptyMessage(0); } } - final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens); - downloaded = true; - - Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); - CGeoMap.filter(result); - // update the caches - // first remove filtered out - final Set<String> filteredCodes = searchResult.getFilteredGeocodes(); - Log.d("Filtering out " + filteredCodes.size() + " caches: " + filteredCodes.toString()); - caches.removeAll(DataStore.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY)); - DataStore.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.REMOVE_CACHE)); - // new collection type needs to remove first to refresh - caches.removeAll(result); - caches.addAll(result); - lastSearchResult = searchResult; - - //render - displayExecutor.execute(new DisplayRunnable(viewport)); - - } catch (ThreadDeath e) { - Log.d("DownloadThread stopped"); - displayHandler.sendEmptyMessage(UPDATE_TITLE); - } finally { - showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress } + final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens); + downloaded = true; + + final Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); + CGeoMap.filter(result); + // update the caches + // first remove filtered out + final Set<String> filteredCodes = searchResult.getFilteredGeocodes(); + Log.d("Filtering out " + filteredCodes.size() + " caches: " + filteredCodes.toString()); + caches.removeAll(DataStore.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY)); + DataStore.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.REMOVE_CACHE)); + // new collection type needs to remove first to refresh + caches.removeAll(result); + caches.addAll(result); + lastSearchResult = searchResult; + + //render + displayExecutor.execute(new DisplayRunnable(this)); + + } catch (final ThreadDeath e) { + Log.d("DownloadThread stopped"); + displayHandler.sendEmptyMessage(UPDATE_TITLE); + } finally { + showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress } } /** * Thread to Display (down)loaded caches. Started by {@link LoadRunnable} and {@link DownloadRunnable} */ - private class DisplayRunnable extends DoRunnable { + private static class DisplayRunnable extends DoRunnable { - public DisplayRunnable(final Viewport viewport) { - super(viewport); + public DisplayRunnable(@NonNull final CGeoMap map) { + super(map); } @Override public void run() { - try { - showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); - if (mapView == null || caches == null) { - throw new ThreadDeath(); - } + final CGeoMap map = getMap(); + if (map != null) { + map.doDisplayRun(); + } + } + } - // display caches - final List<Geocache> cachesToDisplay = caches.getAsList(); - final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints); - final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>(); + private void doDisplayRun() { + try { + showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); + if (mapView == null || caches == null) { + throw new ThreadDeath(); + } - if (!cachesToDisplay.isEmpty()) { - // Only show waypoints for single view or setting - // when less than showWaypointsthreshold Caches shown - if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) { - for (Waypoint waypoint : waypointsToDisplay) { + // display caches + final List<Geocache> cachesToDisplay = caches.getAsList(); + final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints); + final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>(); - if (waypoint == null || waypoint.getCoords() == null) { - continue; - } + if (!cachesToDisplay.isEmpty()) { + // Only show waypoints for single view or setting + // when less than showWaypointsthreshold Caches shown + if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) { + for (final Waypoint waypoint : waypointsToDisplay) { - itemsToDisplay.add(getWaypointItem(waypoint)); - } - } - for (Geocache cache : cachesToDisplay) { - - if (cache == null || cache.getCoords() == null) { + if (waypoint == null || waypoint.getCoords() == null) { continue; } - itemsToDisplay.add(getCacheItem(cache)); - } - overlayCaches.updateItems(itemsToDisplay); - displayHandler.sendEmptyMessage(INVALIDATE_MAP); + itemsToDisplay.add(getWaypointItem(waypoint)); + } + } + for (final Geocache cache : cachesToDisplay) { - } else { - overlayCaches.updateItems(itemsToDisplay); - displayHandler.sendEmptyMessage(INVALIDATE_MAP); + if (cache == null || cache.getCoords() == null) { + continue; + } + itemsToDisplay.add(getCacheItem(cache)); } - displayHandler.sendEmptyMessage(UPDATE_TITLE); - } catch (ThreadDeath e) { - Log.d("DisplayThread stopped"); - displayHandler.sendEmptyMessage(UPDATE_TITLE); - } finally { - showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); + overlayCaches.updateItems(itemsToDisplay); + displayHandler.sendEmptyMessage(INVALIDATE_MAP); + + } else { + overlayCaches.updateItems(itemsToDisplay); + displayHandler.sendEmptyMessage(INVALIDATE_MAP); } + + displayHandler.sendEmptyMessage(UPDATE_TITLE); + } catch (final ThreadDeath e) { + Log.d("DisplayThread stopped"); + displayHandler.sendEmptyMessage(UPDATE_TITLE); + } finally { + showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); } } @@ -1372,10 +1395,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private static abstract class DoRunnable implements Runnable { - final protected Viewport viewport; + private final WeakReference<CGeoMap> mapRef; + + protected DoRunnable(@NonNull final CGeoMap map) { + mapRef = new WeakReference<CGeoMap>(map); + } - protected DoRunnable(final Viewport viewport) { - this.viewport = viewport; + protected @Nullable + final CGeoMap getMap() { + return mapRef.get(); } } @@ -1385,7 +1413,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto * @param listId * the list to store the caches in */ - private void storeCaches(List<String> geocodes, int listId) { + private void storeCaches(final List<String> geocodes, final int listId) { final LoadDetailsHandler loadDetailsHandler = new LoadDetailsHandler(); waitDialog = new ProgressDialog(activity); @@ -1396,19 +1424,19 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto waitDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override - public void onCancel(DialogInterface arg0) { + public void onCancel(final DialogInterface arg0) { try { if (loadDetailsThread != null) { loadDetailsThread.stopIt(); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("CGeoMap.storeCaches.onCancel", e); } } }); - float etaTime = detailTotal * 7.0f / 60.0f; - int roundedEta = Math.round(etaTime); + final float etaTime = detailTotal * 7.0f / 60.0f; + final int roundedEta = Math.round(etaTime); if (etaTime < 0.4) { waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm)); } else { @@ -1457,7 +1485,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (!DataStore.isOffline(geocode, null)) { Geocache.storeCache(null, geocode, listId, false, handler); } - } catch (Exception e) { + } catch (final Exception e) { Log.e("CGeoMap.LoadDetails.run", e); } finally { // one more cache over @@ -1471,12 +1499,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } - private static synchronized void filter(Collection<Geocache> caches) { - boolean excludeMine = Settings.isExcludeMyCaches(); - boolean excludeDisabled = Settings.isExcludeDisabledCaches(); + private static synchronized void filter(final Collection<Geocache> caches) { + final boolean excludeMine = Settings.isExcludeMyCaches(); + final boolean excludeDisabled = Settings.isExcludeDisabledCaches(); - List<Geocache> removeList = new ArrayList<Geocache>(); - for (Geocache cache : caches) { + final List<Geocache> removeList = new ArrayList<Geocache>(); + for (final Geocache cache : caches) { if ((excludeMine && cache.isFound()) || (excludeMine && cache.isOwner()) || (excludeDisabled && cache.isDisabled()) || (excludeDisabled && cache.isArchived())) { removeList.add(cache); } @@ -1514,14 +1542,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } // move map to view results of searchIntent - private void centerMap(String geocodeCenter, final SearchResult searchCenter, final Geopoint coordsCenter, int[] mapState) { + private void centerMap(final String geocodeCenter, final SearchResult searchCenter, final Geopoint coordsCenter, final int[] mapState) { final MapControllerImpl mapController = mapView.getMapController(); if (!centered && mapState != null) { try { mapController.setCenter(mapItemFactory.getGeoPointBase(new Geopoint(mapState[0] / 1.0e6, mapState[1] / 1.0e6))); setZoom(mapState[2]); - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Log.e("centermap", e); } @@ -1545,7 +1573,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (viewport.getLatitudeSpan() != 0 && viewport.getLongitudeSpan() != 0) { mapController.zoomToSpan((int) (viewport.getLatitudeSpan() * 1e6), (int) (viewport.getLongitudeSpan() * 1e6)); } - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Log.e("centermap", e); } @@ -1554,7 +1582,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } else if (!centered && coordsCenter != null) { try { mapController.setCenter(makeGeoPoint(coordsCenter)); - } catch (Exception e) { + } catch (final Exception e) { Log.e("centermap", e); } @@ -1572,16 +1600,47 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } // set my location listener - private class MyLocationListener implements View.OnClickListener { + private static class MyLocationListener implements View.OnClickListener { + + private final WeakReference<CGeoMap> mapRef; + + public MyLocationListener(@NonNull final CGeoMap map) { + mapRef = new WeakReference<CGeoMap>(map); + } + @Override - public void onClick(View view) { - followMyLocation = !followMyLocation; - switchMyLocationButton(); + public void onClick(final View view) { + final CGeoMap map = mapRef.get(); + if (map != null) { + map.onFollowMyLocationClicked(); + } } } - @Override - public void onDrag() { + private void onFollowMyLocationClicked() { + followMyLocation = !followMyLocation; + switchMyLocationButton(); + } + + public static class MapDragListener implements OnMapDragListener { + + private final WeakReference<CGeoMap> mapRef; + + public MapDragListener(@NonNull final CGeoMap map) { + mapRef = new WeakReference<CGeoMap>(map); + } + + @Override + public void onDrag() { + final CGeoMap map = mapRef.get(); + if (map != null) { + map.onDrag(); + } + } + + } + + private void onDrag() { if (followMyLocation) { followMyLocation = false; switchMyLocationButton(); @@ -1593,15 +1652,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto return mapItemFactory.getGeoPointBase(coords); } - // close activity and open homescreen - @Override - public void goHome(View view) { - ActivityMixin.navigateToMain(activity); - } - @Override public View makeView() { - ImageView imageView = new ImageView(activity); + final ImageView imageView = new ImageView(activity); imageView.setScaleType(ScaleType.CENTER); imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); return imageView; @@ -1739,7 +1792,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto private CachesOverlayItemImpl getWaypointItem(final Waypoint waypoint) { final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(waypoint, waypoint.getWaypointType().applyDistanceRule()); - Drawable marker = getResources().getDrawable(!waypoint.isVisited() ? R.drawable.marker : R.drawable.marker_transparent); + final Drawable marker = getResources().getDrawable(!waypoint.isVisited() ? R.drawable.marker : R.drawable.marker_transparent); final Drawable[] layers = new Drawable[] { marker, getResources().getDrawable(waypoint.getWaypointType().markerId) diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java index 8a1bad6..2a29cc9 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java @@ -98,8 +98,8 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl, F } @Override - public void goHome(View view) { - ActivityMixin.navigateToMain(this); + public void navigateUp(View view) { + ActivityMixin.navigateUp(this); } @Override diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java index 094c456..ea815ab 100644 --- a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java +++ b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java @@ -38,16 +38,23 @@ public class GoogleMapView extends MapView implements MapViewImpl { public GoogleMapView(Context context, AttributeSet attrs) { super(context, attrs); - gestureDetector = new GestureDetector(context, new GestureListener()); + initialize(context); } public GoogleMapView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - gestureDetector = new GestureDetector(context, new GestureListener()); + initialize(context); } public GoogleMapView(Context context, String apiKey) { super(context, apiKey); + initialize(context); + } + + private void initialize(Context context) { + if (isInEditMode()) { + return; + } gestureDetector = new GestureDetector(context, new GestureListener()); } diff --git a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java index 08309f4..3596d5f 100644 --- a/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java +++ b/main/src/cgeo/geocaching/maps/interfaces/MapActivityImpl.java @@ -33,5 +33,5 @@ public interface MapActivityImpl { boolean superOnOptionsItemSelected(MenuItem item); - public abstract void goHome(View view); + public abstract void navigateUp(View view); } diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java index a0384b8..94213ba 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge; +import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.maps.AbstractMap; import cgeo.geocaching.maps.CGeoMap; @@ -111,10 +112,9 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl return super.onPrepareOptionsMenu(menu); } - // close activity and open homescreen @Override - public void goHome(View view) { - mapBase.goHome(view); + public void navigateUp(View view) { + ActivityMixin.navigateUp(this); } @Override diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java index fb057a4..d95cc80 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java @@ -42,6 +42,13 @@ public class MapsforgeMapView extends MapView implements MapViewImpl { public MapsforgeMapView(Context context, AttributeSet attrs) { super(context, attrs); + initialize(context); + } + + private void initialize(Context context) { + if (isInEditMode()) { + return; + } gestureDetector = new GestureDetector(context, new GestureListener()); if (Settings.isScaleMapsforgeText()) { this.setTextScale(getResources().getDisplayMetrics().density); diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java index 33ed30e..daeb2b8 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java @@ -1,5 +1,6 @@ package cgeo.geocaching.maps.mapsforge.v024; +import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.maps.AbstractMap; import cgeo.geocaching.maps.CGeoMap; @@ -111,10 +112,9 @@ public class MapsforgeMapActivity024 extends MapActivity implements MapActivityI return super.onPrepareOptionsMenu(menu); } - // close activity and open homescreen @Override - public void goHome(View view) { - mapBase.goHome(view); + public void navigateUp(View view) { + ActivityMixin.navigateUp(this); } @Override diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java index 68a03b7..8dd15fc 100644 --- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java +++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java @@ -36,6 +36,13 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl { public MapsforgeMapView024(Context context, AttributeSet attrs) { super(context, attrs); + initialize(context); + } + + private void initialize(Context context) { + if (isInEditMode()) { + return; + } gestureDetector = new GestureDetector(context, new GestureListener()); } diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java index 474558d..9de272b 100644 --- a/main/src/cgeo/geocaching/settings/Settings.java +++ b/main/src/cgeo/geocaching/settings/Settings.java @@ -374,7 +374,7 @@ public class Settings { } public static String getSignature() { - return getString(R.string.pref_signature, null); + return getString(R.string.pref_signature, StringUtils.EMPTY); } public static boolean setCookieStore(final String cookies) { diff --git a/main/src/cgeo/geocaching/settings/TemplateTextPreference.java b/main/src/cgeo/geocaching/settings/TemplateTextPreference.java index 667b02b..1f420ef 100644 --- a/main/src/cgeo/geocaching/settings/TemplateTextPreference.java +++ b/main/src/cgeo/geocaching/settings/TemplateTextPreference.java @@ -58,7 +58,7 @@ public class TemplateTextPreference extends DialogPreference { public void onClick(View button) { AlertDialog.Builder alert = new AlertDialog.Builder(TemplateTextPreference.this.getContext()); alert.setTitle(R.string.init_signature_template_button); - final ArrayList<LogTemplate> templates = LogTemplateProvider.getTemplates(); + final ArrayList<LogTemplate> templates = LogTemplateProvider.getTemplatesWithoutSignature(); String[] items = new String[templates.size()]; for (int i = 0; i < templates.size(); i++) { items[i] = settingsActivity.getResources().getString(templates.get(i).getResourceId()); diff --git a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java index cb8926a..6a2f9a5 100644 --- a/main/src/cgeo/geocaching/ui/dialog/Dialogs.java +++ b/main/src/cgeo/geocaching/ui/dialog/Dialogs.java @@ -218,7 +218,19 @@ public final class Dialogs { /** * Show a message dialog with a single "OK" button. - * + * + * @param context + * activity owning the dialog + * @param message + * message dialog content + */ + public static void message(final Activity context, final int message) { + message(context, null, getString(message)); + } + + /** + * Show a message dialog with a single "OK" button. + * * @param context * activity owning the dialog * @param title diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index 5fa0982..76400cf 100644 --- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java +++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java @@ -36,9 +36,9 @@ public final class LogTemplateProvider { private Geocache cache; private Trackable trackable; private boolean offline = false; - private LogEntry logEntry; + private final LogEntry logEntry; - public LogContext(final Geocache cache, LogEntry logEntry) { + public LogContext(final Geocache cache, final LogEntry logEntry) { this(cache, logEntry, false); } @@ -47,7 +47,7 @@ public final class LogTemplateProvider { this.logEntry = logEntry; } - public LogContext(final Geocache cache, LogEntry logEntry, final boolean offline) { + public LogContext(final Geocache cache, final LogEntry logEntry, final boolean offline) { this.cache = cache; this.offline = offline; this.logEntry = logEntry; @@ -104,8 +104,11 @@ public final class LogTemplateProvider { } } - public static ArrayList<LogTemplate> getTemplates() { - ArrayList<LogTemplate> templates = new ArrayList<LogTemplateProvider.LogTemplate>(); + /** + * @return all templates, but not the signature template itself + */ + public static ArrayList<LogTemplate> getTemplatesWithoutSignature() { + final ArrayList<LogTemplate> templates = new ArrayList<LogTemplateProvider.LogTemplate>(); templates.add(new LogTemplate("DATE", R.string.init_signature_template_date) { @Override @@ -171,11 +174,11 @@ public final class LogTemplateProvider { @Override public String getValue(final LogContext context) { - Trackable trackable = context.getTrackable(); + final Trackable trackable = context.getTrackable(); if (trackable != null) { return trackable.getOwner(); } - Geocache cache = context.getCache(); + final Geocache cache = context.getCache(); if (cache != null) { return cache.getOwnerDisplayName(); } @@ -184,12 +187,12 @@ public final class LogTemplateProvider { }); templates.add(new LogTemplate("NAME", R.string.init_signature_template_name) { @Override - public String getValue(LogContext context) { - Trackable trackable = context.getTrackable(); + public String getValue(final LogContext context) { + final Trackable trackable = context.getTrackable(); if (trackable != null) { return trackable.getName(); } - Geocache cache = context.getCache(); + final Geocache cache = context.getCache(); if (cache != null) { return cache.getName(); } @@ -199,12 +202,12 @@ public final class LogTemplateProvider { templates.add(new LogTemplate("URL", R.string.init_signature_template_url) { @Override - public String getValue(LogContext context) { - Trackable trackable = context.getTrackable(); + public String getValue(final LogContext context) { + final Trackable trackable = context.getTrackable(); if (trackable != null) { return trackable.getUrl(); } - Geocache cache = context.getCache(); + final Geocache cache = context.getCache(); if (cache != null) { return cache.getUrl(); } @@ -213,8 +216,8 @@ public final class LogTemplateProvider { }); templates.add(new LogTemplate("LOG", R.string.init_signature_template_log) { @Override - public String getValue(LogContext context) { - LogEntry logEntry = context.getLogEntry(); + public String getValue(final LogContext context) { + final LogEntry logEntry = context.getLogEntry(); if (logEntry != null) { return logEntry.getDisplayText(); } @@ -224,8 +227,26 @@ public final class LogTemplateProvider { return templates; } + /** + * @return all templates, including the signature template + */ + public static ArrayList<LogTemplate> getTemplatesWithSignature() { + final ArrayList<LogTemplate> templates = getTemplatesWithoutSignature(); + templates.add(new LogTemplate("SIGNATURE", R.string.init_signature) { + @Override + public String getValue(final LogContext context) { + final String nestedTemplate = StringUtils.defaultString(Settings.getSignature()); + if (StringUtils.contains(nestedTemplate, "SIGNATURE")) { + return "invalid signature template"; + } + return LogTemplateProvider.applyTemplates(nestedTemplate, context); + } + }); + return templates; + } + public static LogTemplate getTemplate(final int itemId) { - for (LogTemplate template : getTemplates()) { + for (final LogTemplate template : getTemplatesWithSignature()) { if (template.getItemId() == itemId) { return template; } @@ -238,7 +259,7 @@ public final class LogTemplateProvider { return StringUtils.EMPTY; } String result = signature; - for (LogTemplate template : getTemplates()) { + for (final LogTemplate template : getTemplatesWithSignature()) { result = template.apply(result, context); } return result; |
