diff options
Diffstat (limited to 'main/src')
68 files changed, 1267 insertions, 998 deletions
diff --git a/main/src/cgeo/calendar/CalendarAddon.java b/main/src/cgeo/calendar/CalendarAddon.java index 4a672fa..5d6371d 100644 --- a/main/src/cgeo/calendar/CalendarAddon.java +++ b/main/src/cgeo/calendar/CalendarAddon.java @@ -35,7 +35,7 @@ public class CalendarAddon { ICalendar.PARAM_NAME, cache.getName(), ICalendar.PARAM_NOTE, StringUtils.defaultString(cache.getPersonalNote()), ICalendar.PARAM_HIDDEN_DATE, hiddenDate != null ? String.valueOf(hiddenDate.getTime()) : StringUtils.EMPTY, - ICalendar.PARAM_URL, StringUtils.defaultString(cache.getUrl()), + ICalendar.PARAM_URL, StringUtils.defaultString(cache.getBrowserUrl()), ICalendar.PARAM_COORDS, cache.getCoords() == null ? "" : cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECMINUTE_RAW), ICalendar.PARAM_LOCATION, StringUtils.defaultString(cache.getLocation()), ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription()), diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java index 6cda723..5bf0f06 100644 --- a/main/src/cgeo/geocaching/AboutActivity.java +++ b/main/src/cgeo/geocaching/AboutActivity.java @@ -14,6 +14,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -28,6 +29,8 @@ import java.util.Scanner; public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> { + private static final String EXTRA_ABOUT_STARTPAGE = "cgeo.geocaching.extra.about.startpage"; + class LicenseViewCreator extends AbstractCachingPageViewCreator<ScrollView> { @InjectView(R.id.license) protected TextView licenseLink; @@ -84,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; @@ -96,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() { @@ -142,7 +143,13 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState, R.layout.viewpager_activity); - createViewPager(0, null); + + int startPage = Page.VERSION.ordinal(); + Bundle extras = getIntent().getExtras(); + if (extras != null) { + startPage = extras.getInt(EXTRA_ABOUT_STARTPAGE, startPage); + } + createViewPager(startPage, null); reinitializeViewPager(); } @@ -210,4 +217,10 @@ public class AboutActivity extends AbstractViewPagerActivity<AboutActivity.Page> return result; } + public static void showChangeLog(Context fromActivity) { + final Intent intent = new Intent(fromActivity, AboutActivity.class); + intent.putExtra(EXTRA_ABOUT_STARTPAGE, Page.CHANGELOG.ordinal()); + fromActivity.startActivity(intent); + } + } 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 e42e780..ea02171 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,13 +555,23 @@ 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)); + // if we have a newer Android device setup Android Beam for easy cache sharing + initializeAndroidBeam( + new ActivitySharingInterface() { + @Override + public String getUri() { + return cache.getCgeoUrl(); + } + } + ); + // reset imagesList so Images view page will be redrawn imagesList = null; reinitializeViewPager(); @@ -615,6 +581,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc progress.dismiss(); } + /** * Tries to navigate to the {@link Geocache} of this activity. */ @@ -902,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); @@ -939,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 @@ -951,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 @@ -1411,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 @@ -1462,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); @@ -1598,7 +1565,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (unknownTagsHandler.isProblematicDetected()) { final int startPos = description.length(); final IConnector connector = ConnectorFactory.getConnector(cache); - final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>")); + final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getBrowserUrl() + "\">" + connector.getName() + "</a>")); ((Editable) description).append("\n\n").append(tableNote); ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -1632,7 +1599,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); fixTextColor(descriptionString); descriptionView.setVisibility(View.VISIBLE); - registerForContextMenu(descriptionView); + addContextMenu(descriptionView); } } @@ -1796,7 +1763,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } }); - registerForContextMenu(rowView); + addContextMenu(rowView); rowView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -1885,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 fa51137..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() { @@ -640,13 +582,14 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA setVisible(menu, R.id.menu_switch_select_mode, !isEmpty); setVisible(menu, R.id.submenu_manage, (isHistory && !isEmpty) || isOffline); - setVisible(menu, R.id.submenu_manage_lists, isOffline); + + setVisible(menu, R.id.menu_create_list, isOffline); setVisible(menu, R.id.menu_sort, !isEmpty && !isHistory); 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); @@ -676,8 +619,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA menu.findItem(R.id.menu_drop_list).setVisible(isNonDefaultList); menu.findItem(R.id.menu_rename_list).setVisible(isNonDefaultList); - final boolean multipleLists = DataStore.getLists().size() >= 2; - menu.findItem(R.id.menu_switch_list).setVisible(multipleLists); menu.findItem(R.id.menu_move_to_list).setVisible(!isEmpty); setMenuItemLabel(menu, R.id.menu_remove_from_history, R.string.cache_remove_from_history, R.string.cache_clear_history); @@ -690,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; } } @@ -771,10 +712,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA adapter.invertSelection(); invalidateOptionsMenuCompatible(); return false; - case R.id.menu_switch_list: - selectList(); - invalidateOptionsMenuCompatible(); - return false; case R.id.menu_filter: showFilterMenu(null); return true; @@ -1043,11 +980,13 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA registerForContextMenu(list); adapter = new CacheListAdapter(this, cacheList, type); - listFooter = getLayoutInflater().inflate(R.layout.cacheslist_footer, null); - listFooter.setClickable(true); - listFooter.setOnClickListener(new MoreCachesListener()); - listFooterText = (TextView) listFooter.findViewById(R.id.more_caches); - list.addFooterView(listFooter); + if (listFooter == null) { + listFooter = getLayoutInflater().inflate(R.layout.cacheslist_footer, null); + listFooter.setClickable(true); + listFooter.setOnClickListener(new MoreCachesListener()); + listFooterText = (TextView) listFooter.findViewById(R.id.more_caches); + list.addFooterView(listFooter); + } setListAdapter(adapter); adapter.forceSort(); } @@ -1413,13 +1352,6 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } } - public void selectList() { - if (!type.canSwitch) { - return; - } - new StoredList.UserInterface(this).promptForListSelection(R.string.list_title, getListSwitchingRunnable()); - } - @NonNull private Action1<Integer> getListSwitchingRunnable() { return new Action1<Integer>() { @@ -1453,6 +1385,8 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA Settings.saveLastList(listId); + initAdapter(); + showProgress(true); showFooterLoadingCaches(); DataStore.moveToList(adapter.getCheckedCaches(), listId); @@ -1747,7 +1681,7 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA loader = new PocketGeocacheListLoader(app, guid); break; } - setTitle(title); + updateTitle(); showProgress(true); showFooterLoadingCaches(); @@ -1782,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/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java index 9bc46b3..8c060e5 100644 --- a/main/src/cgeo/geocaching/EditWaypointActivity.java +++ b/main/src/cgeo/geocaching/EditWaypointActivity.java @@ -48,7 +48,7 @@ import java.util.EnumSet; import java.util.List; @EActivity -public class EditWaypointActivity extends AbstractActionBarActivity { +public class EditWaypointActivity extends AbstractActionBarActivity implements CoordinatesInputDialog.CoordinateUpdate { private static final ArrayList<WaypointType> POSSIBLE_WAYPOINT_TYPES = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL); @ViewById(R.id.buttonLatitude) protected Button buttonLat; @@ -294,17 +294,18 @@ public class EditWaypointActivity extends AbstractActionBarActivity { // button text is blank when creating new waypoint } Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); - CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(EditWaypointActivity.this, cache, gp, app.currentGeo()); + CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(cache, gp, app.currentGeo()); coordsDialog.setCancelable(true); - coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() { - @Override - public void update(final Geopoint gp) { - buttonLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); - buttonLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); - } - }); - coordsDialog.show(); + coordsDialog.show(getSupportFragmentManager(),"wpeditdialog"); } + + + } + + @Override + public void updateCoordinates(Geopoint gp) { + buttonLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); + buttonLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); } public static final int SUCCESS = 0; diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index db36740..0840d6f 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -79,10 +79,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; @@ -501,7 +497,7 @@ public class Geocache implements ICache, IWaypoint { } private String getCacheUrl() { - return getConnector().getCacheUrl(this); + return getConnector().getCacheBrowserUrl(this); } private String getBrowserCacheUrl() { @@ -722,15 +718,17 @@ public class Geocache implements ICache, IWaypoint { final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_SUBJECT, subject.toString()); - intent.putExtra(Intent.EXTRA_TEXT, getUrl()); + intent.putExtra(Intent.EXTRA_TEXT, getBrowserUrl()); return intent; } - public String getUrl() { - return getConnector().getCacheUrl(this); + public String getBrowserUrl() { + return getConnector().getCacheBrowserUrl(this); } + public String getCgeoUrl() { return getConnector().getCgeoCacheUrl(this); } + public boolean supportsGCVote() { return StringUtils.startsWithIgnoreCase(geocode, "GC"); } diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java index cccd154..1f77113 100644 --- a/main/src/cgeo/geocaching/LogCacheActivity.java +++ b/main/src/cgeo/geocaching/LogCacheActivity.java @@ -25,7 +25,6 @@ import org.apache.commons.lang3.StringUtils; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; -import android.app.Dialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; @@ -35,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; @@ -52,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"; @@ -68,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; @@ -84,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() { @@ -123,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; } @@ -142,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); @@ -154,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); } }); @@ -164,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); @@ -184,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(); } }); @@ -193,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 @@ -239,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())) { @@ -248,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(); @@ -277,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); @@ -286,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(); } }); @@ -305,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() { @@ -364,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)); } @@ -382,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); @@ -440,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; @@ -461,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 { @@ -473,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 { @@ -484,20 +402,10 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia private class DateListener implements View.OnClickListener { @Override - public void onClick(View arg0) { - final Dialog dateDialog = new DateDialog(LogCacheActivity.this, LogCacheActivity.this, date); + public void onClick(final View arg0) { + final DateDialog dateDialog = DateDialog.getInstance(date); dateDialog.setCancelable(true); - dateDialog.show(); - } - } - - 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()); + dateDialog.show(getSupportFragmentManager(), "date_dialog"); } } @@ -523,8 +431,9 @@ 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); DataStore.saveLogsWithoutTransaction(cache.getGeocode(), newLogs); @@ -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/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java index fabe391..9f1bc88 100644 --- a/main/src/cgeo/geocaching/LogTrackableActivity.java +++ b/main/src/cgeo/geocaching/LogTrackableActivity.java @@ -20,7 +20,6 @@ import cgeo.geocaching.utils.LogTemplateProvider.LogContext; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; @@ -240,9 +239,9 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat @Override public void onClick(View arg0) { - final Dialog dateDialog = new DateDialog(LogTrackableActivity.this, LogTrackableActivity.this, date); + final DateDialog dateDialog = DateDialog.getInstance(date); dateDialog.setCancelable(true); - dateDialog.show(); + dateDialog.show(getSupportFragmentManager(),"date_dialog"); } } diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index 473d870..cf323bb 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -213,6 +213,8 @@ public class MainActivity extends AbstractActionBarActivity { Log.i("Starting " + getPackageName() + ' ' + version + " a.k.a " + Version.getVersionName(this)); init(); + + checkShowChangelog(); } @Override @@ -324,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() { @@ -726,6 +727,16 @@ public class MainActivity extends AbstractActionBarActivity { } } + private void checkShowChangelog() { + int lastVersion = Settings.getLastChangelogVersion(); + int version = Version.getVersionCode(this); + Settings.setLastChangelogVersion(version); + // don't show change log after new install... + if (lastVersion > 0 && version != lastVersion) { + AboutActivity.showChangeLog(this); + } + } + /** * @param view * unused here but needed since this method is referenced from XML layout diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java index a4053dc..39531f1 100644 --- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java +++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java @@ -44,7 +44,7 @@ import android.widget.TextView; import java.util.List; -public class NavigateAnyPointActivity extends AbstractActionBarActivity { +public class NavigateAnyPointActivity extends AbstractActionBarActivity implements CoordinatesInputDialog.CoordinateUpdate { @InjectView(R.id.historyList) protected ListView historyListView; @@ -278,18 +278,17 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity { if (latButton.getText().length() > 0 && lonButton.getText().length() > 0) { gp = new Geopoint(latButton.getText().toString() + " " + lonButton.getText().toString()); } - CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(NavigateAnyPointActivity.this, null, gp, app.currentGeo()); + CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, gp, app.currentGeo()); coordsDialog.setCancelable(true); - coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() { - @Override - public void update(Geopoint gp) { - latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); - lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); - changed = true; - } - }); - coordsDialog.show(); + coordsDialog.show(getSupportFragmentManager(),"wpedit_dialog"); } + + } + @Override + public void updateCoordinates(Geopoint gp) { + latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); + lonButton.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); + changed = true; } private static class ChangeDistanceUnit implements OnItemSelectedListener { @@ -328,7 +327,7 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity { menu.findItem(R.id.menu_default_navigation).setVisible(visible); menu.findItem(R.id.menu_caches_around).setVisible(visible); - menu.findItem(R.id.menu_clear_history).setEnabled(!getHistoryOfSearchedLocations().isEmpty()); + menu.findItem(R.id.menu_clear_history).setVisible(!getHistoryOfSearchedLocations().isEmpty()); } catch (RuntimeException e) { // nothing } @@ -362,9 +361,8 @@ public class NavigateAnyPointActivity extends AbstractActionBarActivity { 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/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java index f1f09d4..81dec98 100644 --- a/main/src/cgeo/geocaching/SearchActivity.java +++ b/main/src/cgeo/geocaching/SearchActivity.java @@ -37,7 +37,7 @@ import android.widget.Button; import java.util.Locale; -public class SearchActivity extends AbstractActionBarActivity { +public class SearchActivity extends AbstractActionBarActivity implements CoordinatesInputDialog.CoordinateUpdate { @InjectView(R.id.buttonLatitude) protected Button buttonLatitude; @InjectView(R.id.buttonLongitude) protected Button buttonLongitude; @@ -290,16 +290,15 @@ public class SearchActivity extends AbstractActionBarActivity { } private void updateCoordinates() { - final CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(SearchActivity.this, null, null, app.currentGeo()); + final CoordinatesInputDialog coordsDialog = CoordinatesInputDialog.getInstance(null, null, app.currentGeo()); coordsDialog.setCancelable(true); - coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() { - @Override - public void update(final Geopoint gp) { - buttonLatitude.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); - buttonLongitude.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); - } - }); - coordsDialog.show(); + coordsDialog.show(getSupportFragmentManager(), "wpedit_dialog"); + } + + @Override + public void updateCoordinates(final Geopoint gp) { + buttonLatitude.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); + buttonLongitude.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); } private void findByCoordsFn() { diff --git a/main/src/cgeo/geocaching/Trackable.java b/main/src/cgeo/geocaching/Trackable.java index d532cda..0fe580f 100644 --- a/main/src/cgeo/geocaching/Trackable.java +++ b/main/src/cgeo/geocaching/Trackable.java @@ -38,8 +38,12 @@ public class Trackable implements ILogable { private List<LogEntry> logs = new ArrayList<LogEntry>(); private String trackingcode = null; - public String getUrl() { - return getConnector().getUrl(this); + public String getBrowserUrl() { + return getConnector().getBrowserUrl(this); + } + + public String getCgeoUrl() { + return getConnector().getCgeoUrl(this); } private TrackableConnector getConnector() { diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index 7dfc3c1..2b6808e 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -25,6 +25,7 @@ import cgeo.geocaching.utils.UnknownTagsHandler; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; + import rx.android.observables.AndroidObservable; import rx.android.observables.ViewObservable; import rx.functions.Action1; @@ -37,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; @@ -111,10 +114,24 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi if (waitDialog != null) { waitDialog.dismiss(); } + + // if we have a newer Android device setup Android Beam for easy cache sharing + initializeAndroidBeam( + new ActivitySharingInterface() { + @Override + public String getUri() { + return trackable.getCgeoUrl(); + } + } + ); } }; 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) { @@ -199,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; @@ -241,18 +228,17 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi LogTrackableActivity.startActivity(this, trackable); return true; case R.id.menu_browser_trackable: - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl()))); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getBrowserUrl()))); return true; - default: - return false; } + return super.onOptionsItemSelected(item); } @Override public boolean onPrepareOptionsMenu(Menu menu) { if (trackable != null) { - menu.findItem(R.id.menu_log_touch).setEnabled(StringUtils.isNotBlank(geocode) && trackable.isLoggable()); - menu.findItem(R.id.menu_browser_trackable).setEnabled(StringUtils.isNotBlank(trackable.getUrl())); + menu.findItem(R.id.menu_log_touch).setVisible(StringUtils.isNotBlank(geocode) && trackable.isLoggable()); + menu.findItem(R.id.menu_browser_trackable).setVisible(StringUtils.isNotBlank(trackable.getBrowserUrl())); } return super.onPrepareOptionsMenu(menu); } @@ -399,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; @@ -411,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)); @@ -480,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 @@ -499,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 @@ -508,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 @@ -539,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 b35f6e3..a732f65 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActionBarActivity.java @@ -20,14 +20,15 @@ public class AbstractActionBarActivity extends AbstractActivity { showProgress(false); } - @Override - protected void onCreate(Bundle savedInstanceState, int resourceLayoutID, boolean useDialogTheme) { - super.onCreate(savedInstanceState, resourceLayoutID, useDialogTheme); - initUpAction(); - showProgress(false); - } 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 42eb825..e3df1f7 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -12,15 +12,23 @@ 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; +import android.annotation.TargetApi; import android.content.Intent; import android.content.res.Resources; +import android.nfc.NdefMessage; +import android.nfc.NdefRecord; +import android.nfc.NfcAdapter; +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; @@ -43,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); } @@ -77,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); } @@ -114,21 +116,14 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs } protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID) { - onCreate(savedInstanceState, resourceLayoutID, false); - } - - protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID, boolean useDialogTheme) { super.onCreate(savedInstanceState); initializeCommonFields(); // non declarative part of layout - if (useDialogTheme) { - setTheme(ActivityMixin.getDialogTheme()); - } else { - setTheme(); - } + setTheme(); + setContentView(resourceLayoutID); // create view variables @@ -161,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) { @@ -175,27 +169,62 @@ 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; } } + + // Do not support older devices than Android 4.0 + // Although there even are 2.3 devices (Nexus S) + // these are so few that we don't want to deal with the older (non Android Beam) API + + public interface ActivitySharingInterface { + /** Return an URL that represent the current activity for sharing */ + public String getUri(); + } + + protected void initializeAndroidBeam(ActivitySharingInterface sharingInterface) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + initializeICSAndroidBeam(sharingInterface); + } + } + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + protected void initializeICSAndroidBeam(final ActivitySharingInterface sharingInterface) { + NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); + if (nfcAdapter == null) { + return; + } + nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() { + @Override + public NdefMessage createNdefMessage(NfcEvent event) { + NdefRecord record = NdefRecord.createUri(sharingInterface.getUri()); + return new NdefMessage(new NdefRecord[]{record}); + } + }, this); + + } } 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/WhereYouGoApp.java b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java index 79a5975..b2a2cad 100644 --- a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java +++ b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java @@ -3,14 +3,34 @@ package cgeo.geocaching.apps.cache; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.utils.TextUtils; + +import org.apache.commons.lang3.StringUtils; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; + +import java.util.regex.Pattern; public class WhereYouGoApp extends AbstractGeneralApp { + private static final Pattern PATTERN_CARTRIDGE = Pattern.compile("(" + Pattern.quote("http://www.wherigo.com/cartridge/details.aspx?") + ".*?)" + Pattern.quote("\"")); + public WhereYouGoApp() { super(getString(R.string.cache_menu_whereyougo), R.id.cache_app_whereyougo, "menion.android.whereyougo"); } @Override public boolean isEnabled(Geocache cache) { - return cache.getType() == CacheType.WHERIGO; + return cache.getType() == CacheType.WHERIGO && StringUtils.isNotEmpty(getWhereIGoUrl(cache)); + } + + @Override + public void navigate(Activity activity, Geocache cache) { + activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getWhereIGoUrl(cache)))); + } + + protected static String getWhereIGoUrl(Geocache cache) { + return TextUtils.getMatch(cache.getDescription(), PATTERN_CARTRIDGE, null); } } 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/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 6d8d79e..0d28b7f 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -142,7 +142,12 @@ public abstract class AbstractConnector implements IConnector { @Override public String getLongCacheUrl(final @NonNull Geocache cache) { - return getCacheUrl(cache); + return getCacheBrowserUrl(cache); + } + + @Override + public String getCgeoCacheUrl(@NonNull Geocache cache) { + return getLongCacheUrl(cache); } @Override diff --git a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java index 3992013..1aaaf53 100644 --- a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java +++ b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java @@ -14,7 +14,7 @@ public class GeocachingAustraliaConnector extends AbstractConnector { } @Override - public String getCacheUrl(final @NonNull Geocache cache) { + public String getCacheBrowserUrl(final @NonNull Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } diff --git a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java index aa08485..aa7ca1e 100644 --- a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java +++ b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java @@ -14,7 +14,7 @@ public class GeopeitusConnector extends AbstractConnector { } @Override - public String getCacheUrl(final @NonNull Geocache cache) { + public String getCacheBrowserUrl(final @NonNull Geocache cache) { return getCacheUrlPrefix() + StringUtils.stripStart(cache.getGeocode().substring(2), "0"); } diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index fbade5a..d103011 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -34,7 +34,15 @@ public interface IConnector { * @param cache * @return */ - public String getCacheUrl(final @NonNull Geocache cache); + public String getCacheBrowserUrl(final @NonNull Geocache cache); + + /** + * Get the URL that will default to CGEO opening the cache + * + * @param cache + * @return + */ + public String getCgeoCacheUrl(final @NonNull Geocache cache); /** * get long browser URL for the given cache diff --git a/main/src/cgeo/geocaching/connector/UnknownConnector.java b/main/src/cgeo/geocaching/connector/UnknownConnector.java index 05593d7..d254af1 100644 --- a/main/src/cgeo/geocaching/connector/UnknownConnector.java +++ b/main/src/cgeo/geocaching/connector/UnknownConnector.java @@ -14,7 +14,7 @@ public class UnknownConnector extends AbstractConnector { } @Override - public String getCacheUrl(@NonNull Geocache cache) { + public String getCacheBrowserUrl(@NonNull Geocache cache) { return null; // we have no url for these caches } diff --git a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java index 282ee31..d1e4e41 100644 --- a/main/src/cgeo/geocaching/connector/WaymarkingConnector.java +++ b/main/src/cgeo/geocaching/connector/WaymarkingConnector.java @@ -14,7 +14,7 @@ public class WaymarkingConnector extends AbstractConnector { } @Override - public String getCacheUrl(@NonNull Geocache cache) { + public String getCacheBrowserUrl(@NonNull Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } diff --git a/main/src/cgeo/geocaching/connector/ec/ECConnector.java b/main/src/cgeo/geocaching/connector/ec/ECConnector.java index 71716fe..ebc1a92 100644 --- a/main/src/cgeo/geocaching/connector/ec/ECConnector.java +++ b/main/src/cgeo/geocaching/connector/ec/ECConnector.java @@ -68,7 +68,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, } @Override - public String getCacheUrl(@NonNull Geocache cache) { + public String getCacheBrowserUrl(@NonNull Geocache cache) { return CACHE_URL + cache.getGeocode().replace("EC", ""); } @@ -178,7 +178,7 @@ public class ECConnector extends AbstractConnector implements ISearchByGeocode, @Override public String getLicenseText(final @NonNull Geocache cache) { // NOT TO BE TRANSLATED - return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, CC BY-NC-ND 3.0, alle Logeinträge © jeweiliger Autor"; + return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheBrowserUrl(cache) + "\">" + getName() + "</a>, CC BY-NC-ND 3.0, alle Logeinträge © jeweiliger Autor"; } @Override diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index a38bad0..723d873 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -84,12 +84,17 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } @Override + public String getCgeoCacheUrl(@NonNull Geocache cache) { + return getLongCacheUrl(cache).replace("//", "/"); + } + + @Override public String getLongCacheUrl(@NonNull Geocache cache) { return CACHE_URL_LONG + cache.getGeocode(); } @Override - public String getCacheUrl(@NonNull Geocache cache) { + public String getCacheBrowserUrl(@NonNull Geocache cache) { return CACHE_URL_SHORT + cache.getGeocode(); } diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java index 284234e..4357e79 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java @@ -45,7 +45,7 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode { @Override public String getLicenseText(final @NonNull Geocache cache) { // NOT TO BE TRANSLATED - return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a>, " + licenseString; + return "© " + cache.getOwnerDisplayName() + ", <a href=\"" + getCacheBrowserUrl(cache) + "\">" + getName() + "</a>, " + licenseString; } @Override diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java index 1ba88d5..0131c73 100644 --- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java +++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java @@ -39,7 +39,7 @@ public class OCConnector extends AbstractConnector { } @Override - public String getCacheUrl(@NonNull Geocache cache) { + public String getCacheBrowserUrl(@NonNull Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } diff --git a/main/src/cgeo/geocaching/connector/ox/OXConnector.java b/main/src/cgeo/geocaching/connector/ox/OXConnector.java index 7d4cf7f..b95a5b8 100644 --- a/main/src/cgeo/geocaching/connector/ox/OXConnector.java +++ b/main/src/cgeo/geocaching/connector/ox/OXConnector.java @@ -35,7 +35,7 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I } @Override - public String getCacheUrl(@NonNull Geocache cache) { + public String getCacheBrowserUrl(@NonNull Geocache cache) { return getCacheUrlPrefix() + cache.getGeocode(); } @@ -52,7 +52,7 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I @Override public String getLicenseText(@NonNull Geocache cache) { // NOT TO BE TRANSLATED - return "<a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons CC-BY-SA 3.0 License"; + return "<a href=\"" + getCacheBrowserUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons CC-BY-SA 3.0 License"; } @Override diff --git a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java index fb554b9..15e32fb 100644 --- a/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/AbstractTrackableConnector.java @@ -1,5 +1,6 @@ package cgeo.geocaching.connector.trackable; +import cgeo.geocaching.Trackable; import cgeo.geocaching.connector.AbstractConnector; import cgeo.geocaching.connector.UserAction; @@ -22,6 +23,11 @@ public abstract class AbstractTrackableConnector implements TrackableConnector { } @Override + public String getCgeoUrl(Trackable trackable) { + return getBrowserUrl(trackable); + } + + @Override public @NonNull List<UserAction> getUserActions() { return AbstractConnector.getDefaultUserActions(); diff --git a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java index 03052f9..709ec70 100644 --- a/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/GeokretyConnector.java @@ -20,7 +20,7 @@ public class GeokretyConnector extends AbstractTrackableConnector { } @Override - public String getUrl(Trackable trackable) { + public String getBrowserUrl(Trackable trackable) { return "http://geokrety.org/konkret.php?id=" + getId(trackable.getGeocode()); } @@ -38,7 +38,7 @@ public class GeokretyConnector extends AbstractTrackableConnector { final String hex = geocode.substring(2); return Integer.parseInt(hex, 16); } catch (final NumberFormatException e) { - Log.e("Trackable.getUrl", e); + Log.e("Trackable.getBrowserUrl", e); } return -1; } diff --git a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java index 6071b5f..f91c4ba 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TrackableConnector.java @@ -16,7 +16,9 @@ public interface TrackableConnector { public boolean canHandleTrackable(final String geocode); - public String getUrl(final Trackable trackable); + public String getBrowserUrl(final Trackable trackable); + + public String getCgeoUrl(final Trackable trackable); public boolean isLoggable(); diff --git a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java index 77848d7..3b4077e 100644 --- a/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/TravelBugConnector.java @@ -25,7 +25,12 @@ public class TravelBugConnector extends AbstractTrackableConnector { } @Override - public String getUrl(Trackable trackable) { + public String getCgeoUrl(Trackable trackable) { + return getBrowserUrl(trackable).replace("//", "/"); + } + + @Override + public String getBrowserUrl(Trackable trackable) { return "http://www.geocaching.com//track/details.aspx?tracker=" + trackable.getGeocode(); } diff --git a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java index 0295927..ea1d0ae 100644 --- a/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java +++ b/main/src/cgeo/geocaching/connector/trackable/UnknownTrackableConnector.java @@ -12,7 +12,7 @@ public class UnknownTrackableConnector extends AbstractTrackableConnector { } @Override - public String getUrl(Trackable trackable) { + public String getBrowserUrl(Trackable trackable) { return StringUtils.EMPTY; } diff --git a/main/src/cgeo/geocaching/export/GpxSerializer.java b/main/src/cgeo/geocaching/export/GpxSerializer.java index b2587aa..8e71c08 100644 --- a/main/src/cgeo/geocaching/export/GpxSerializer.java +++ b/main/src/cgeo/geocaching/export/GpxSerializer.java @@ -111,7 +111,7 @@ public final class GpxSerializer { XmlUtils.multipleTexts(gpx, PREFIX_GPX, "name", cache.getGeocode(), "desc", cache.getName(), - "url", cache.getUrl(), + "url", cache.getCgeoUrl(), "urlname", cache.getName(), "sym", cache.isFound() ? "Geocache Found" : "Geocache", "type", "Geocache|" + cache.getType().pattern); 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/geopoint/Units.java b/main/src/cgeo/geocaching/geopoint/Units.java index b99e00e..d00e075 100644 --- a/main/src/cgeo/geocaching/geopoint/Units.java +++ b/main/src/cgeo/geocaching/geopoint/Units.java @@ -4,6 +4,8 @@ import cgeo.geocaching.settings.Settings; import org.apache.commons.lang3.tuple.ImmutablePair; +import java.util.Locale; + public class Units { public static ImmutablePair<Double, String> scaleDistance(final double distanceKilometers) { @@ -51,11 +53,10 @@ public class Units { return getDistanceFromKilometers(meters / 1000f); } - public static String getSpeed(float kilometersPerHour) { - final String speed = getDistanceFromKilometers(kilometersPerHour); - if (speed.endsWith("mi")) { - return speed.substring(0, speed.length() - 2) + "mph"; + public static String getSpeed(final float kilometersPerHour) { + if (Settings.isUseImperialUnits()) { + return String.format(Locale.US, "%.0f mph", kilometersPerHour / IConversion.MILES_TO_KILOMETER); } - return speed + (!Settings.isUseImperialUnits() ? "/h" : "ph"); + return String.format(Locale.US, "%.0f km/h", kilometersPerHour); } } 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 b4cb4b8..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; @@ -214,50 +215,62 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto // handlers /** Updates the titles */ - final private Handler displayHandler = new Handler() { + private final static class DisplayHandler extends Handler { + + private final WeakReference<CGeoMap> mapRef; + + public DisplayHandler(@NonNull final CGeoMap map) { + this.mapRef = new WeakReference<CGeoMap>(map); + } @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) { + return; + } switch (what) { case UPDATE_TITLE: // set title final StringBuilder title = new StringBuilder(); - if (mapMode == MapMode.LIVE && isLiveEnabled) { - title.append(res.getString(R.string.map_live)); + if (map.mapMode == MapMode.LIVE && map.isLiveEnabled) { + title.append(map.res.getString(R.string.map_live)); } else { - title.append(mapTitle); + title.append(map.mapTitle); } - countVisibleCaches(); - if (caches != null && !caches.isEmpty() && !mapTitle.contains("[")) { - title.append(" [").append(cachesCnt); - if (cachesCnt != caches.size()) { - title.append('/').append(caches.size()); + map.countVisibleCaches(); + if (map.caches != null && !map.caches.isEmpty() && !map.mapTitle.contains("[")) { + title.append(" [").append(map.cachesCnt); + if (map.cachesCnt != map.caches.size()) { + title.append('/').append(map.caches.size()); } title.append(']'); } - if (Settings.isDebug() && lastSearchResult != null && StringUtils.isNotBlank(lastSearchResult.getUrl())) { - title.append('[').append(lastSearchResult.getUrl()).append(']'); + if (Settings.isDebug() && map.lastSearchResult != null && StringUtils.isNotBlank(map.lastSearchResult.getUrl())) { + title.append('[').append(map.lastSearchResult.getUrl()).append(']'); } - setTitle(title.toString()); + map.setTitle(title.toString()); break; case INVALIDATE_MAP: - mapView.repaintRequired(null); + map.mapView.repaintRequired(null); break; default: break; } } - }; + } + + final private Handler displayHandler = new DisplayHandler(this); - private void setTitle(String title) { - /* Compatibily for the old Action Bar, only used by the maps activity at the moment */ + 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) { titleview.setText(title); @@ -269,17 +282,21 @@ 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); } /** Updates the progress. */ - final private Handler showProgressHandler = new Handler() { - + private static final class ShowProgressHandler extends Handler { private int counter = 0; + @NonNull private final WeakReference<CGeoMap> mapRef; + + public ShowProgressHandler(@NonNull final CGeoMap map) { + this.mapRef = new WeakReference<CGeoMap>(map); + } @Override - public void handleMessage(Message msg) { + public void handleMessage(final Message msg) { final int what = msg.what; if (what == HIDE_PROGRESS) { @@ -292,8 +309,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } - private void showProgress(boolean show) { - final ProgressBar progress = (ProgressBar) activity.findViewById(R.id.actionbar_progress); + private void showProgress(final boolean show) { + final CGeoMap map = mapRef.get(); + if (map == null) { + return; + } + + final ProgressBar progress = (ProgressBar) map.activity.findViewById(R.id.actionbar_progress); if (progress != null) { if (show) { progress.setVisibility(View.VISIBLE); @@ -303,20 +325,20 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } if (Build.VERSION.SDK_INT >= 11) { - activity.setProgressBarIndeterminateVisibility(show); + map.activity.setProgressBarIndeterminateVisibility(show); } } - }; - + } + final private Handler showProgressHandler = new ShowProgressHandler(this); 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; @@ -328,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)); } } @@ -351,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)); @@ -367,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); } @@ -402,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 @@ -410,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(); @@ -475,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(); @@ -509,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); } @@ -520,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(); } @@ -542,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 { @@ -556,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); @@ -567,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)); } } @@ -587,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); @@ -599,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); @@ -612,12 +634,12 @@ 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.setEnabled(mapSource.isAvailable()); + menuItem.setVisible(mapSource.isAvailable()); } } @@ -644,7 +666,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } final Set<String> geocodesInViewport = getGeocodesForCachesInViewport(); - menu.findItem(R.id.menu_store_caches).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches()); + menu.findItem(R.id.menu_store_caches).setVisible(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches()); item = menu.findItem(R.id.menu_circle_mode); // show circles if (overlayCaches != null && overlayCaches.getCircles()) { @@ -656,9 +678,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto item = menu.findItem(R.id.menu_theme_mode); // show theme selection item.setVisible(mapView.hasMapThemes()); - menu.findItem(R.id.menu_as_list).setEnabled(!isLoading()); + menu.findItem(R.id.menu_as_list).setVisible(!isLoading()); - menu.findItem(R.id.submenu_strategy).setEnabled(isLiveEnabled); + menu.findItem(R.id.submenu_strategy).setVisible(isLiveEnabled); switch (Settings.getLiveMapStrategy()) { case FASTEST: @@ -673,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); } @@ -681,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()); @@ -796,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(); } @@ -814,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); @@ -822,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) { @@ -888,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); @@ -966,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); } @@ -992,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) { @@ -1015,7 +1037,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } } - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Log.w("Failed to update location."); } } @@ -1073,50 +1095,63 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto return loadTimer; } - /** - * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}. - */ - private Subscription startLoadTimer() { - return Schedulers.newThread().createWorker().schedulePeriodically(new Action0() { - @Override - public void call() { - try { - if (mapView != null) { - // get current viewport - final Viewport viewportNow = mapView.getViewport(); - // Since zoomNow is used only for local comparison purposes, - // it is ok to use the Google Maps compatible zoom level of OSM Maps - final int zoomNow = mapView.getMapZoomLevel(); - - // check if map moved or zoomed - //TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move - final boolean moved = markersInvalidated || (isLiveEnabled && !downloaded) || (viewport == null) || zoomNow != zoom || - (mapMoved(viewport, viewportNow) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) || !viewport.includes(viewportNow))); - - // update title on any change - if (moved || !viewportNow.equals(viewport)) { - displayHandler.sendEmptyMessage(UPDATE_TITLE); - } - zoom = zoomNow; + private static final class LoadTimerAction implements Action0 { - // save new values - if (moved) { - markersInvalidated = false; + @NonNull private final WeakReference<CGeoMap> mapRef; - long currentTime = System.currentTimeMillis(); + public LoadTimerAction(@NonNull final CGeoMap map) { + this.mapRef = new WeakReference<CGeoMap>(map); + } - if (1000 < (currentTime - loadThreadRun)) { - viewport = viewportNow; - loadExecutor.execute(new LoadRunnable(viewport)); - } - } + @Override + public void call() { + final CGeoMap map = mapRef.get(); + if (map == null) { + return; + } + try { + if (map.mapView != null) { + // get current viewport + final Viewport viewportNow = map.mapView.getViewport(); + // Since zoomNow is used only for local comparison purposes, + // it is ok to use the Google Maps compatible zoom level of OSM Maps + final int zoomNow = map.mapView.getMapZoomLevel(); + + // check if map moved or zoomed + //TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move + final boolean moved = map.markersInvalidated || (map.isLiveEnabled && !map.downloaded) || (map.viewport == null) || zoomNow != map.zoom || + (mapMoved(map.viewport, viewportNow) && (map.cachesCnt <= 0 || CollectionUtils.isEmpty(map.caches) || !map.viewport.includes(viewportNow))); + + // update title on any change + if (moved || !viewportNow.equals(map.viewport)) { + map.displayHandler.sendEmptyMessage(UPDATE_TITLE); } + map.zoom = zoomNow; - } catch (Exception e) { - Log.w("CGeoMap.startLoadtimer.start", e); + // save new values + if (moved) { + map.markersInvalidated = false; + + final long currentTime = System.currentTimeMillis(); + + if (1000 < (currentTime - map.loadThreadRun)) { + map.viewport = viewportNow; + loadExecutor.execute(new LoadRunnable(map)); + } + } } + + } catch (final Exception e) { + Log.w("CGeoMap.startLoadtimer.start", e); } - }, 250, 250, TimeUnit.MILLISECONDS); + } + } + + /** + * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}. + */ + private Subscription startLoadTimer() { + return Schedulers.newThread().createWorker().schedulePeriodically(new LoadTimerAction(this), 250, 250, TimeUnit.MILLISECONDS); } /** @@ -1136,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 } + } /** @@ -1216,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(); - } - - // display caches - final List<Geocache> cachesToDisplay = caches.getAsList(); - final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints); - final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>(); + final CGeoMap map = getMap(); + if (map != null) { + map.doDisplayRun(); + } + } + } - 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) { + private void doDisplayRun() { + try { + showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); + if (mapView == null || caches == null) { + throw new ThreadDeath(); + } - if (waypoint == null || waypoint.getCoords() == null) { - continue; - } + // display caches + final List<Geocache> cachesToDisplay = caches.getAsList(); + final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints); + final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>(); - itemsToDisplay.add(getWaypointItem(waypoint)); - } - } - for (Geocache cache : cachesToDisplay) { + 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) { - 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); } } @@ -1338,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(); } } @@ -1351,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); @@ -1362,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 { @@ -1423,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 @@ -1437,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); } @@ -1480,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); } @@ -1511,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); } @@ -1520,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); } @@ -1538,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(); @@ -1559,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; @@ -1705,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/network/OAuthAuthorizationActivity.java b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java index 527f024..eb56f0b 100644 --- a/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java +++ b/main/src/cgeo/geocaching/network/OAuthAuthorizationActivity.java @@ -4,7 +4,7 @@ import butterknife.InjectView; import cgeo.geocaching.Intents; import cgeo.geocaching.R; -import cgeo.geocaching.activity.AbstractActionBarActivity; +import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.utils.BundleUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.MatcherWrapper; @@ -32,7 +32,7 @@ import android.widget.TextView; import java.io.IOException; import java.util.regex.Pattern; -public abstract class OAuthAuthorizationActivity extends AbstractActionBarActivity { +public abstract class OAuthAuthorizationActivity extends AbstractActivity { public static final int NOT_AUTHENTICATED = 0; public static final int AUTHENTICATED = 1; @@ -106,7 +106,7 @@ public abstract class OAuthAuthorizationActivity extends AbstractActionBarActivi @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState, R.layout.authorization_activity, true); + super.onCreate(savedInstanceState, R.layout.authorization_activity); Bundle extras = getIntent().getExtras(); if (extras != null) { diff --git a/main/src/cgeo/geocaching/settings/Settings.java b/main/src/cgeo/geocaching/settings/Settings.java index a527fc5..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) { @@ -1008,4 +1008,12 @@ public class Settings { return getString(R.string.pref_ec_icons, "1"); } + /* Store last version for the changelog display */ + public static int getLastChangelogVersion() { + return getInt(R.string.pref_changelog_last_version, 0); + } + + public static void setLastChangelogVersion(int version) { + putInt(R.string.pref_changelog_last_version, version); + } } 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/CoordinatesInputDialog.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java index 67b8923..00b5abe 100644 --- a/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java +++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java @@ -3,7 +3,6 @@ package cgeo.geocaching.ui.dialog; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.activity.AbstractActivity; -import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.sensors.IGeoData; @@ -12,12 +11,14 @@ import cgeo.geocaching.settings.Settings.CoordInputFormatEnum; import cgeo.geocaching.utils.EditUtils; import org.apache.commons.lang3.StringUtils; -import org.eclipse.jdt.annotation.NonNull; import android.os.Bundle; +import android.support.v4.app.DialogFragment; import android.text.Editable; import android.text.TextWatcher; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; @@ -26,14 +27,11 @@ import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; -import java.lang.ref.WeakReference; +public class CoordinatesInputDialog extends DialogFragment { -public class CoordinatesInputDialog extends NoTitleDialog { - - final private WeakReference<AbstractActivity> context; - final private IGeoData geo; - final private Geocache cache; private Geopoint gp; + private Geopoint gpinitial; + private Geopoint cacheCoords; private EditText eLat, eLon; private Button bLat, bLon; @@ -42,34 +40,64 @@ public class CoordinatesInputDialog extends NoTitleDialog { private TextView tLatSep1, tLatSep2, tLatSep3; private TextView tLonSep1, tLonSep2, tLonSep3; - private CoordinateUpdate cuListener; - private CoordInputFormatEnum currentFormat = null; - public CoordinatesInputDialog(final @NonNull AbstractActivity context, final Geocache cache, final Geopoint gp, final IGeoData geo) { - super(context, ActivityMixin.getDialogTheme()); - this.context = new WeakReference<AbstractActivity>(context); - this.geo = geo; - this.cache = cache; + + private static final String GEOPOINT_ARG = "GEOPOINT"; + private static final String GEOPOINT_INTIAL_ARG = "GEOPOINT_INITIAL"; + private static final String CACHECOORDS_ARG = "CACHECOORDS"; + + + public static CoordinatesInputDialog getInstance(final Geocache cache, final Geopoint gp, final IGeoData geo) { + + Bundle args = new Bundle(); if (gp != null) { - this.gp = gp; + args.putParcelable(GEOPOINT_ARG, gp); } else if (geo != null && geo.getCoords() != null) { - this.gp = geo.getCoords(); + args.putParcelable(GEOPOINT_ARG, geo.getCoords()); } else { - this.gp = Geopoint.ZERO; + args.putParcelable(GEOPOINT_ARG, Geopoint.ZERO); } + + if (geo !=null) + args.putParcelable(GEOPOINT_INTIAL_ARG, geo.getCoords()); + + if (cache != null) + args.putParcelable(CACHECOORDS_ARG, cache.getCoords()); + + CoordinatesInputDialog cid = new CoordinatesInputDialog(); + cid.setArguments(args); + return cid; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + gp = getArguments().getParcelable(GEOPOINT_ARG); + gpinitial = getArguments().getParcelable(GEOPOINT_INTIAL_ARG); + cacheCoords = getArguments().getParcelable(CACHECOORDS_ARG); + + if (savedInstanceState != null && savedInstanceState.getParcelable(GEOPOINT_ARG)!=null) + gp = savedInstanceState.getParcelable(GEOPOINT_ARG); + + } - setContentView(R.layout.coordinatesinput_dialog); + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + // TODO: if current input is not commited in gp, read the current input into gp + outState.putParcelable(GEOPOINT_ARG, gp); + } + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + getDialog().setTitle(R.string.cache_coordinates); - final Spinner spinner = (Spinner) findViewById(R.id.spinnerCoordinateFormats); + View v = inflater.inflate(R.layout.coordinatesinput_dialog, container, false); + final Spinner spinner = (Spinner) v.findViewById(R.id.spinnerCoordinateFormats); final ArrayAdapter<CharSequence> adapter = - ArrayAdapter.createFromResource(context.get(), + ArrayAdapter.createFromResource(getActivity(), R.array.waypoint_coordinate_formats, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); @@ -77,25 +105,25 @@ public class CoordinatesInputDialog extends NoTitleDialog { spinner.setSelection(Settings.getCoordInputFormat().ordinal()); spinner.setOnItemSelectedListener(new CoordinateFormatListener()); - bLat = (Button) findViewById(R.id.ButtonLat); - eLat = (EditText) findViewById(R.id.latitude); - eLatDeg = (EditText) findViewById(R.id.EditTextLatDeg); - eLatMin = (EditText) findViewById(R.id.EditTextLatMin); - eLatSec = (EditText) findViewById(R.id.EditTextLatSec); - eLatSub = (EditText) findViewById(R.id.EditTextLatSecFrac); - tLatSep1 = (TextView) findViewById(R.id.LatSeparator1); - tLatSep2 = (TextView) findViewById(R.id.LatSeparator2); - tLatSep3 = (TextView) findViewById(R.id.LatSeparator3); - - bLon = (Button) findViewById(R.id.ButtonLon); - eLon = (EditText) findViewById(R.id.longitude); - eLonDeg = (EditText) findViewById(R.id.EditTextLonDeg); - eLonMin = (EditText) findViewById(R.id.EditTextLonMin); - eLonSec = (EditText) findViewById(R.id.EditTextLonSec); - eLonSub = (EditText) findViewById(R.id.EditTextLonSecFrac); - tLonSep1 = (TextView) findViewById(R.id.LonSeparator1); - tLonSep2 = (TextView) findViewById(R.id.LonSeparator2); - tLonSep3 = (TextView) findViewById(R.id.LonSeparator3); + bLat = (Button) v.findViewById(R.id.ButtonLat); + eLat = (EditText) v.findViewById(R.id.latitude); + eLatDeg = (EditText) v.findViewById(R.id.EditTextLatDeg); + eLatMin = (EditText) v.findViewById(R.id.EditTextLatMin); + eLatSec = (EditText) v.findViewById(R.id.EditTextLatSec); + eLatSub = (EditText) v.findViewById(R.id.EditTextLatSecFrac); + tLatSep1 = (TextView) v.findViewById(R.id.LatSeparator1); + tLatSep2 = (TextView) v.findViewById(R.id.LatSeparator2); + tLatSep3 = (TextView) v.findViewById(R.id.LatSeparator3); + + bLon = (Button) v.findViewById(R.id.ButtonLon); + eLon = (EditText) v.findViewById(R.id.longitude); + eLonDeg = (EditText) v.findViewById(R.id.EditTextLonDeg); + eLonMin = (EditText) v.findViewById(R.id.EditTextLonMin); + eLonSec = (EditText) v.findViewById(R.id.EditTextLonSec); + eLonSub = (EditText) v.findViewById(R.id.EditTextLonSecFrac); + tLonSep1 = (TextView) v.findViewById(R.id.LonSeparator1); + tLonSep2 = (TextView) v.findViewById(R.id.LonSeparator2); + tLonSep3 = (TextView) v.findViewById(R.id.LonSeparator3); eLatDeg.addTextChangedListener(new TextChanged(eLatDeg)); eLatMin.addTextChangedListener(new TextChanged(eLatMin)); @@ -118,18 +146,24 @@ public class CoordinatesInputDialog extends NoTitleDialog { bLat.setOnClickListener(new ButtonClickListener()); bLon.setOnClickListener(new ButtonClickListener()); - final Button buttonCurrent = (Button) findViewById(R.id.current); + final Button buttonCurrent = (Button) v.findViewById(R.id.current); buttonCurrent.setOnClickListener(new CurrentListener()); - final Button buttonCache = (Button) findViewById(R.id.cache); - if (cache != null) { + final Button buttonCache = (Button) v.findViewById(R.id.cache); + + if (cacheCoords != null) { buttonCache.setOnClickListener(new CacheListener()); } else { buttonCache.setVisibility(View.GONE); } - final Button buttonDone = (Button) findViewById(R.id.done); + + final Button buttonDone = (Button) v.findViewById(R.id.done); buttonDone.setOnClickListener(new InputDoneListener()); + + return v; } + + private void updateGUI() { if (gp == null) { return; @@ -140,14 +174,14 @@ public class CoordinatesInputDialog extends NoTitleDialog { switch (currentFormat) { case Plain: - findViewById(R.id.coordTable).setVisibility(View.GONE); + getView().findViewById(R.id.coordTable).setVisibility(View.GONE); eLat.setVisibility(View.VISIBLE); eLon.setVisibility(View.VISIBLE); eLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); eLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); break; case Deg: // DDD.DDDDD° - findViewById(R.id.coordTable).setVisibility(View.VISIBLE); + getView().findViewById(R.id.coordTable).setVisibility(View.VISIBLE); eLat.setVisibility(View.GONE); eLon.setVisibility(View.GONE); eLatSec.setVisibility(View.GONE); @@ -168,7 +202,7 @@ public class CoordinatesInputDialog extends NoTitleDialog { eLonMin.setText(addZeros(gp.getLonDegFrac(), 5)); break; case Min: // DDD° MM.MMM - findViewById(R.id.coordTable).setVisibility(View.VISIBLE); + getView().findViewById(R.id.coordTable).setVisibility(View.VISIBLE); eLat.setVisibility(View.GONE); eLon.setVisibility(View.GONE); eLatSec.setVisibility(View.VISIBLE); @@ -193,7 +227,7 @@ public class CoordinatesInputDialog extends NoTitleDialog { eLonSec.setText(addZeros(gp.getLonMinFrac(), 3)); break; case Sec: // DDD° MM SS.SSS - findViewById(R.id.coordTable).setVisibility(View.VISIBLE); + getView().findViewById(R.id.coordTable).setVisibility(View.VISIBLE); eLat.setVisibility(View.GONE); eLon.setVisibility(View.GONE); eLatSec.setVisibility(View.VISIBLE); @@ -374,7 +408,7 @@ public class CoordinatesInputDialog extends NoTitleDialog { // Signaled and returned below } if (signalError) { - final AbstractActivity activity = context.get(); + final AbstractActivity activity = (AbstractActivity) getActivity(); activity.showToast(activity.getResources().getString(R.string.err_parse_lat_lon)); } return false; @@ -403,8 +437,8 @@ public class CoordinatesInputDialog extends NoTitleDialog { // Start new format with an acceptable value: either the current one // entered by the user, else our current coordinates, else (0,0). if (!areCurrentCoordinatesValid(false)) { - if (geo != null && geo.getCoords() != null) { - gp = geo.getCoords(); + if (gpinitial != null) { + gp = gpinitial; } else { gp = Geopoint.ZERO; } @@ -426,13 +460,13 @@ public class CoordinatesInputDialog extends NoTitleDialog { @Override public void onClick(View v) { - if (geo == null || geo.getCoords() == null) { - final AbstractActivity activity = context.get(); + if (gpinitial == null) { + final AbstractActivity activity = (AbstractActivity) getActivity(); activity.showToast(activity.getResources().getString(R.string.err_point_unknown_position)); return; } - gp = geo.getCoords(); + gp = gpinitial; updateGUI(); } } @@ -441,17 +475,18 @@ public class CoordinatesInputDialog extends NoTitleDialog { @Override public void onClick(View v) { - if (cache == null || cache.getCoords() == null) { - final AbstractActivity activity = context.get(); + if (cacheCoords == null) { + final AbstractActivity activity = (AbstractActivity) getActivity(); activity.showToast(activity.getResources().getString(R.string.err_location_unknown)); return; } - gp = cache.getCoords(); + gp = cacheCoords; updateGUI(); } } + private class InputDoneListener implements View.OnClickListener { @Override @@ -460,18 +495,14 @@ public class CoordinatesInputDialog extends NoTitleDialog { return; } if (gp != null) { - cuListener.update(gp); + ((CoordinateUpdate) getActivity()).updateCoordinates(gp); } dismiss(); } } - public void setOnCoordinateUpdate(CoordinateUpdate cu) { - cuListener = cu; - } - public interface CoordinateUpdate { - public void update(final Geopoint gp); + public void updateCoordinates(final Geopoint gp); } } diff --git a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java index 18f8e2e..fc69f44 100644 --- a/main/src/cgeo/geocaching/ui/dialog/DateDialog.java +++ b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java @@ -2,48 +2,56 @@ package cgeo.geocaching.ui.dialog; import cgeo.geocaching.R; -import android.app.Activity; import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import android.widget.DatePicker; import java.util.Calendar; -public class DateDialog extends NoTitleDialog { +public class DateDialog extends DialogFragment { public interface DateDialogParent { abstract public void setDate(final Calendar date); } - private final DateDialogParent parent; - private final Calendar date; + private Calendar date; - public DateDialog(Activity contextIn, DateDialogParent parentIn, Calendar dateIn) { - super(contextIn); - - // init - this.date = dateIn; - this.parent = parentIn; + public static DateDialog getInstance(Calendar date) { + DateDialog dd = new DateDialog(); + Bundle args = new Bundle(); + args.putSerializable("date", date); + dd.setArguments(args); + return dd; } @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setStyle(DialogFragment.STYLE_NO_TITLE, 0); + Bundle args = getArguments(); + date = (Calendar) args.getSerializable("date"); + } - setContentView(R.layout.date); + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.date, container, false); - final DatePicker picker = (DatePicker) findViewById(R.id.picker); + final DatePicker picker = (DatePicker) v.findViewById(R.id.picker); picker.init(date.get(Calendar.YEAR), date.get(Calendar.MONTH), date.get(Calendar.DATE), new DatePickerListener()); + return v; } private class DatePickerListener implements DatePicker.OnDateChangedListener { @Override public void onDateChanged(DatePicker picker, int year, int month, int day) { - if (parent != null) { - date.set(year, month, day); + date.set(year, month, day); + + ((DateDialogParent) getActivity()).setDate(date); - parent.setDate(date); - } } } }
\ No newline at end of file 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/ui/dialog/NoTitleDialog.java b/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java deleted file mode 100644 index 8660a7b..0000000 --- a/main/src/cgeo/geocaching/ui/dialog/NoTitleDialog.java +++ /dev/null @@ -1,32 +0,0 @@ -package cgeo.geocaching.ui.dialog; - -import cgeo.geocaching.utils.Log; - -import android.app.Dialog; -import android.content.Context; -import android.os.Bundle; -import android.view.ViewGroup.LayoutParams; -import android.view.Window; - -public abstract class NoTitleDialog extends Dialog { - - public NoTitleDialog(Context context) { - super(context); - } - - public NoTitleDialog(Context context, int theme) { - super(context, theme); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - try { - requestWindowFeature(Window.FEATURE_NO_TITLE); - getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - } catch (final Exception e) { - Log.e("NoTitleDialog.onCreate", e); - } - } -} diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java index 5fa0982..1ddede5 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,22 +202,22 @@ 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(); + return trackable.getBrowserUrl(); } - Geocache cache = context.getCache(); + final Geocache cache = context.getCache(); if (cache != null) { - return cache.getUrl(); + return cache.getBrowserUrl(); } return StringUtils.EMPTY; } }); 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; |
