diff options
14 files changed, 302 insertions, 79 deletions
diff --git a/main/res/values/attrs.xml b/main/res/values/attrs.xml index 5eaa6a0..ab1db9f 100644 --- a/main/res/values/attrs.xml +++ b/main/res/values/attrs.xml @@ -46,6 +46,7 @@ <attr name="text" format="string" /> <attr name="url" format="string" /> <attr name="urlButton" format="string" /> + <attr name="connector" format="string" /> <!-- others --> <attr name="compass" format="integer" /> diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index 5c6c8ae..ca669ac 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -532,6 +532,18 @@ <string name="init_ec_icons">Map Icons</string> <string name="settings_ec_icons_other">Other</string> <string name="settings_ec_icons_oc">OC</string> + <string name="settings_features">Supported Features</string> + <string name="feature_description">The following <b>online</b> features of this website are supported in c:geo (in addition to the offline features):</string> + <string name="feature_personal_notes">Personal notes</string> + <string name="feature_online_logging">Online logging</string> + <string name="feature_log_images">Attach images to logs</string> + <string name="feature_watch_list">Watch list</string> + <string name="feature_own_coordinates">Storing of modified coordinates</string> + <string name="feature_search_user">Search by owner/finder</string> + <string name="feature_search_keyword">Search by keyword</string> + <string name="feature_search_live_map">Live map</string> + <string name="feature_search_center">Search by position</string> + <string name="feature_search_geocode">Search by geocode</string> <!-- map sources --> <string name="map_source_google_map">Google: Map</string> diff --git a/main/res/xml/preferences.xml b/main/res/xml/preferences.xml index b7fd880..a173601 100644 --- a/main/res/xml/preferences.xml +++ b/main/res/xml/preferences.xml @@ -59,6 +59,10 @@ </PreferenceScreen> </PreferenceCategory> <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="GC" /> + <cgeo.geocaching.settings.InfoPreference android:text="@string/settings_info_facebook_login" android:title="@string/settings_info_facebook_login_title" @@ -87,6 +91,9 @@ android:key="@string/pref_fakekey_ocde_authorization" /> </PreferenceCategory> <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="OC" /> <Preference android:key="@string/pref_fakekey_ocde_website" android:title="@string/settings_open_website" /> @@ -109,6 +116,9 @@ android:key="@string/pref_fakekey_ocpl_authorization" /> </PreferenceCategory> <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="OP" /> <Preference android:key="@string/pref_fakekey_ocpl_website" android:title="@string/settings_open_website" /> @@ -155,6 +165,9 @@ android:entryValues="@array/ECIconsValues" /> </PreferenceCategory> <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="EC" /> <Preference android:key="@string/pref_fakekey_ec_website" android:title="@string/settings_open_website" /> @@ -167,31 +180,11 @@ android:defaultValue="false" android:key="@string/pref_connectorOXActive" android:title="@string/settings_activate_ox" /> -<!-- - <EditTextPreference - android:dependency="@string/pref_connectorECActive" - android:dialogTitle="@string/init_username" - android:hint="@string/init_username" - android:imeOptions="actionDone" - android:key="@string/pref_ecusername" - android:singleLine="true" - android:title="@string/init_username" /> - - <cgeo.geocaching.settings.EditPasswordPreference - android:dependency="@string/pref_connectorECActive" - android:dialogTitle="@string/init_password" - android:hint="@string/init_password" - android:imeOptions="actionDone" - android:inputType="textPassword" - android:key="@string/pref_ecpassword" - android:singleLine="true" - android:title="@string/init_password" /> - <cgeo.geocaching.settings.CheckECCredentialsPreference - android:dependency="@string/pref_connectorECActive" - android:title="@string/init_login" /> - --> </PreferenceCategory> <PreferenceCategory android:title="@string/settings_information" > + <cgeo.geocaching.settings.CapabilitiesPreference + android:title="@string/settings_features" + cgeo:connector="OX" /> <Preference android:key="@string/pref_fakekey_ox_website" android:title="@string/settings_open_website" /> diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java index 4edb6d6..ea37553 100644 --- a/main/src/cgeo/geocaching/connector/AbstractConnector.java +++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java @@ -1,8 +1,13 @@ package cgeo.geocaching.connector; +import cgeo.geocaching.CgeoApplication; import cgeo.geocaching.Geocache; import cgeo.geocaching.LogCacheActivity; import cgeo.geocaching.R; +import cgeo.geocaching.connector.capability.ISearchByCenter; +import cgeo.geocaching.connector.capability.ISearchByGeocode; +import cgeo.geocaching.connector.capability.ISearchByKeyword; +import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.enumerations.CacheType; import cgeo.geocaching.enumerations.LogType; import cgeo.geocaching.geopoint.Geopoint; @@ -10,6 +15,8 @@ import cgeo.geocaching.geopoint.Geopoint; import org.apache.commons.lang3.StringUtils; import org.eclipse.jdt.annotation.NonNull; +import android.text.Html; + import java.util.ArrayList; import java.util.List; @@ -206,4 +213,45 @@ public abstract class AbstractConnector implements IConnector { public int getMaxTerrain() { return 5; } + + @Override + public final String getCapabilitiesMessage() { + StringBuilder builder = new StringBuilder("<p>" + + CgeoApplication.getInstance().getString(R.string.feature_description) + "<ul>"); + builder.append(capability(ISearchByViewPort.class, R.string.feature_search_live_map)); + builder.append(capability(ISearchByKeyword.class, R.string.feature_search_keyword)); + builder.append(capability(ISearchByCenter.class, R.string.feature_search_center)); + builder.append(capability(ISearchByGeocode.class, R.string.feature_search_geocode)); + if (supportsUserActions()) { + builder.append(feature(R.string.feature_search_user)); + } + if (supportsLogging()) { + builder.append(feature(R.string.feature_online_logging)); + } + if (supportsLogImages()) { + builder.append(feature(R.string.feature_log_images)); + } + if (supportsPersonalNote()) { + builder.append(feature(R.string.feature_personal_notes)); + } + if (supportsOwnCoordinates()) { + builder.append(feature(R.string.feature_own_coordinates)); + } + if (supportsWatchList()) { + builder.append(feature(R.string.feature_watch_list)); + } + builder.append("</ul></p>"); + return builder.toString(); + } + + private String capability(Class<? extends IConnector> clazz, final int featureResourceId) { + if (clazz.isInstance(this)) { + return feature(featureResourceId); + } + return StringUtils.EMPTY; + } + + private static String feature(int featureResourceId) { + return "<li>" + Html.escapeHtml(CgeoApplication.getInstance().getString(featureResourceId)) + "</li>"; + } } diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java index a07c2d8..8de6070 100644 --- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java +++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java @@ -149,6 +149,9 @@ public final class ConnectorFactory { public static IConnector getConnector(final String geocodeInput) { // this may come from user input final String geocode = StringUtils.trim(geocodeInput); + if (geocode == null) { + return UNKNOWN_CONNECTOR; + } if (isInvalidGeocode(geocode)) { return UNKNOWN_CONNECTOR; } diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java index a0deb5c..04787b3 100644 --- a/main/src/cgeo/geocaching/connector/IConnector.java +++ b/main/src/cgeo/geocaching/connector/IConnector.java @@ -247,4 +247,11 @@ public interface IConnector { * @return */ public int getMaxTerrain(); + + /** + * Creates a text listing all features of this connector to be displayed to the user. + * + * @return + */ + public String getCapabilitiesMessage(); } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java index 3dd16e5..aea0bca 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java @@ -12,6 +12,7 @@ import cgeo.geocaching.connector.ILoggingManager; import cgeo.geocaching.connector.capability.ILogin; import cgeo.geocaching.connector.capability.ISearchByCenter; import cgeo.geocaching.connector.capability.ISearchByGeocode; +import cgeo.geocaching.connector.capability.ISearchByKeyword; import cgeo.geocaching.connector.capability.ISearchByViewPort; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.geopoint.Geopoint; @@ -31,7 +32,7 @@ import android.os.Handler; import java.util.regex.Pattern; -public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ILogin { +public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort, ISearchByKeyword, ILogin { private static final String CACHE_URL_SHORT = "http://coord.info/"; // Double slash is used to force open in browser @@ -205,11 +206,12 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, /** * Add a cache to the favorites list. - * + * * This must not be called from the UI thread. - * - * @param cache the cache to add - * @return <code>true</code> if the cache was sucessfully added, <code>false</code> otherwise + * + * @param cache + * the cache to add + * @return <code>true</code> if the cache was successfully added, <code>false</code> otherwise */ public static boolean addToFavorites(Geocache cache) { @@ -222,11 +224,12 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, /** * Remove a cache from the favorites list. - * + * * This must not be called from the UI thread. - * - * @param cache the cache to add - * @return <code>true</code> if the cache was sucessfully added, <code>false</code> otherwise + * + * @param cache + * the cache to add + * @return <code>true</code> if the cache was successfully added, <code>false</code> otherwise */ public static boolean removeFromFavorites(Geocache cache) { @@ -352,4 +355,10 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode, } return prefix; } + + @Override + public SearchResult searchByName(@NonNull String name) { + // TODO make the connector use this method. Currently it is only a marker interface. + return null; + } } diff --git a/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java b/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java new file mode 100644 index 0000000..1930c17 --- /dev/null +++ b/main/src/cgeo/geocaching/settings/AbstractAttributeBasedPrefence.java @@ -0,0 +1,54 @@ +package cgeo.geocaching.settings; + +import org.eclipse.jdt.annotation.Nullable; + +import android.content.Context; +import android.content.res.TypedArray; +import android.preference.Preference; +import android.util.AttributeSet; + +/** + * Base class for preferences which evaluate their XML attributes for further processing. + * + */ +public abstract class AbstractAttributeBasedPrefence extends Preference { + + public AbstractAttributeBasedPrefence(Context context) { + super(context); + } + + public AbstractAttributeBasedPrefence(Context context, AttributeSet attrs) { + super(context, attrs); + processAttributes(context, attrs, 0); + } + + public AbstractAttributeBasedPrefence(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + processAttributes(context, attrs, defStyle); + } + + private void processAttributes(Context context, @Nullable AttributeSet attrs, int defStyle) { + if (attrs == null) { + return; + } + TypedArray types = context.obtainStyledAttributes(attrs, getAttributeNames(), + defStyle, 0); + + processAttributeValues(types); + + types.recycle(); + } + + /** + * Evaluate the attributes which where requested in {@link AbstractAttributeBasedPrefence#getAttributeNames()}. + * + * @param values + */ + protected abstract void processAttributeValues(TypedArray values); + + /** + * @return the names of the attributes you want to read in your preference implementation + */ + protected abstract int[] getAttributeNames(); + +} diff --git a/main/src/cgeo/geocaching/settings/CapabilitiesPreference.java b/main/src/cgeo/geocaching/settings/CapabilitiesPreference.java new file mode 100644 index 0000000..d7e55a4 --- /dev/null +++ b/main/src/cgeo/geocaching/settings/CapabilitiesPreference.java @@ -0,0 +1,82 @@ +package cgeo.geocaching.settings; + +import cgeo.geocaching.R; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.IConnector; + +import org.apache.commons.lang3.StringUtils; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.TypedArray; +import android.preference.Preference; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebView; + +/** + * Preference for displaying the supported capabilities of an {@link IConnector} implementation. + */ +public class CapabilitiesPreference extends AbstractAttributeBasedPrefence { + + private String connectorCode; + + public CapabilitiesPreference(Context context) { + super(context); + } + + public CapabilitiesPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CapabilitiesPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public View getView(View convertView, ViewGroup parent) { + setOnPreferenceClickListener(new ClickListener()); + return super.getView(convertView, parent); + } + + private final class ClickListener implements OnPreferenceClickListener { + @Override + public boolean onPreferenceClick(final Preference preference) { + WebView htmlView = new WebView(preference.getContext()); + htmlView.loadData(createCapabilitiesMessage(), "text/html", null); + AlertDialog.Builder builder = new AlertDialog.Builder(preference.getContext()); + builder.setView(htmlView) + .setIcon(android.R.drawable.ic_dialog_info) + .setTitle(R.string.settings_features) + .setPositiveButton(R.string.err_none, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + builder.create().show(); + return false; + } + } + + public String createCapabilitiesMessage() { + // TODO: this needs a better key for the connectors + IConnector connector = ConnectorFactory.getConnector(connectorCode + "1234"); + if (connector == null) { + return StringUtils.EMPTY; + } + return connector.getCapabilitiesMessage(); + } + + @Override + protected void processAttributeValues(TypedArray values) { + connectorCode = values.getString(0); + } + + @Override + protected int[] getAttributeNames() { + return new int[] { R.attr.connector }; + } +} diff --git a/main/src/cgeo/geocaching/settings/EditPasswordPreference.java b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java index b127f52..af07041 100644 --- a/main/src/cgeo/geocaching/settings/EditPasswordPreference.java +++ b/main/src/cgeo/geocaching/settings/EditPasswordPreference.java @@ -7,11 +7,10 @@ import android.preference.EditTextPreference; import android.util.AttributeSet; /** - * This is just a dummy preference, to be able check for the type. + * Password preference. It will only show a row of asterisks as summary instead of the password. * <p> * Use it exactly as an EditTextPreference - * - * @see SettingsActivity - search for EditPasswordPreference + * */ public class EditPasswordPreference extends EditTextPreference { diff --git a/main/src/cgeo/geocaching/settings/InfoPreference.java b/main/src/cgeo/geocaching/settings/InfoPreference.java index ea740b4..3b59bcc 100644 --- a/main/src/cgeo/geocaching/settings/InfoPreference.java +++ b/main/src/cgeo/geocaching/settings/InfoPreference.java @@ -17,48 +17,61 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; -public class InfoPreference extends Preference { - - // strings for the popup dialog +/** + * Preference which shows a dialog containing textual explanation. The dialog has two buttons, where one will open a + * hyper link with more detailed information. + * <p> + * The URL for the hyper link and the text are given as custom attributes in the preference XML definition. + * </p> + * + */ +public class InfoPreference extends AbstractAttributeBasedPrefence { + + /** + * Content of the dialog, filled from preferences XML. + */ private String text; + /** + * URL for the second button, filled from preferences XML. + */ private String url; + /** + * text for the second button to open an URL, filled from preferences XML. + */ private String urlButton; private LayoutInflater inflater; public InfoPreference(Context context) { super(context); - init(context, null, 0); + init(context); } public InfoPreference(Context context, AttributeSet attrs) { super(context, attrs); - init(context, attrs, 0); + init(context); } public InfoPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - init(context, attrs, defStyle); + init(context); } - private void init(Context context, AttributeSet attrs, int defStyle) { + private void init(Context context) { inflater = ((Activity) context).getLayoutInflater(); - setPersistent(false); + } - if (attrs == null) { - return; // coward's retreat - } - - TypedArray types = context.obtainStyledAttributes(attrs, new int[] { - android.R.attr.text, R.attr.url, R.attr.urlButton }, - defStyle, 0); - - text = types.getString(0); - url = types.getString(1); - urlButton = types.getString(2); + @Override + protected int[] getAttributeNames() { + return new int[] { android.R.attr.text, R.attr.url, R.attr.urlButton }; + } - types.recycle(); + @Override + protected void processAttributeValues(TypedArray values) { + text = values.getString(0); + url = values.getString(1); + urlButton = values.getString(2); } @Override diff --git a/main/src/cgeo/geocaching/settings/SettingsActivity.java b/main/src/cgeo/geocaching/settings/SettingsActivity.java index 6b4a71b..46dacb2 100644 --- a/main/src/cgeo/geocaching/settings/SettingsActivity.java +++ b/main/src/cgeo/geocaching/settings/SettingsActivity.java @@ -476,7 +476,7 @@ public class SettingsActivity extends PreferenceActivity { final int mapSourceId = Integer.valueOf(stringValue); mapSource = MapProviderFactory.getMapSource(mapSourceId); } catch (final NumberFormatException e) { - Log.e("SettingsActivity.onPreferenceChange: bad source id `" + stringValue + "'"); + Log.e("SettingsActivity.onPreferenceChange: bad source id '" + stringValue + "'"); mapSource = null; } // If there is no corresponding map source (because some map sources were diff --git a/main/src/cgeo/geocaching/settings/TextPreference.java b/main/src/cgeo/geocaching/settings/TextPreference.java index bcd03ff..eecf4cc 100644 --- a/main/src/cgeo/geocaching/settings/TextPreference.java +++ b/main/src/cgeo/geocaching/settings/TextPreference.java @@ -4,21 +4,26 @@ import cgeo.geocaching.R; import android.content.Context; import android.content.res.TypedArray; -import android.preference.Preference; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** - * Preference to simply show a text message. + * Preference to simply show a text message. Links are not shown. * <p> - * Links are not shown - I tried everything (koem) - * <p> - * example: <cgeo.geocaching.settings.TextPreference android:text="@string/legal_note" - * android:layout="@string/text_preference_default_layout" /> + * Usage: The displayed text is taken from the "android:text" attribute of the preference definition. Example: + * + * <pre> + * <cgeo.geocaching.settings.TextPreference + * android:text="@string/legal_note" + * android:layout="@string/text_preference_default_layout" + * /> + * </pre> + * + * </p> */ -public class TextPreference extends Preference { +public class TextPreference extends AbstractAttributeBasedPrefence { private String text; private TextView summaryView; @@ -30,23 +35,20 @@ public class TextPreference extends Preference { public TextPreference(Context context, AttributeSet attrs) { super(context, attrs); - processAttributes(context, attrs, 0); } public TextPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - processAttributes(context, attrs, defStyle); } - private void processAttributes(Context context, AttributeSet attrs, int defStyle) { - if (attrs == null) { - return; - } + @Override + protected int[] getAttributeNames() { + return new int[] { android.R.attr.text }; + } - TypedArray types = context.obtainStyledAttributes(attrs, new int[] { - android.R.attr.text }, defStyle, 0); - this.text = types.getString(0); - types.recycle(); + @Override + protected void processAttributeValues(TypedArray values) { + this.text = values.getString(0); } @Override @@ -67,20 +69,21 @@ public class TextPreference extends Preference { @Override public void setSummary(CharSequence summaryText) { // the layout hasn't been inflated yet, save the summaryText for later use - if (this.summaryView == null) { + if (summaryView == null) { this.summaryText = summaryText; return; } - // if summaryText is null, take it from the previous saved summary + // if summaryText is null, take it from the previously saved summary if (summaryText == null) { if (this.summaryText == null) { return; } - this.summaryView.setText(this.summaryText); + summaryView.setText(this.summaryText); } else { - this.summaryView.setText(summaryText); + summaryView.setText(summaryText); } this.summaryView.setVisibility(View.VISIBLE); } + } diff --git a/main/src/cgeo/geocaching/settings/WpThresholdPreference.java b/main/src/cgeo/geocaching/settings/WpThresholdPreference.java index 867714f..4c43acf 100644 --- a/main/src/cgeo/geocaching/settings/WpThresholdPreference.java +++ b/main/src/cgeo/geocaching/settings/WpThresholdPreference.java @@ -1,7 +1,6 @@ package cgeo.geocaching.settings; import cgeo.geocaching.R; -import cgeo.geocaching.settings.Settings; import android.content.Context; import android.preference.Preference; @@ -14,7 +13,7 @@ import android.widget.TextView; public class WpThresholdPreference extends Preference { - TextView valueView; + private TextView valueView; public WpThresholdPreference(Context context) { super(context); |
